0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-13 00:01:51 -05:00

Add performance oriented refactor on colorpicker libraries component

This commit is contained in:
Andrey Antukh 2025-01-16 21:33:11 +01:00
parent de2475cca6
commit 2a63f8e966

View file

@ -10,6 +10,7 @@
[app.common.colors :as c] [app.common.colors :as c]
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.types.color :as ctc]
[app.main.data.event :as ev] [app.main.data.event :as ev]
[app.main.data.workspace :as dw] [app.main.data.workspace :as dw]
[app.main.data.workspace.colors :as mdc] [app.main.data.workspace.colors :as mdc]
@ -17,6 +18,7 @@
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.color-bullet :as cb] [app.main.ui.components.color-bullet :as cb]
[app.main.ui.components.select :refer [select]] [app.main.ui.components.select :refer [select]]
[app.main.ui.context :as ctx]
[app.main.ui.hooks :as h] [app.main.ui.hooks :as h]
[app.main.ui.hooks.resize :as r] [app.main.ui.hooks.resize :as r]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
@ -27,103 +29,107 @@
(mf/defc libraries (mf/defc libraries
[{:keys [state on-select-color on-add-library-color disable-gradient disable-opacity disable-image]}] [{:keys [state on-select-color on-add-library-color disable-gradient disable-opacity disable-image]}]
(let [selected (h/use-shared-state mdc/colorpicker-selected-broadcast-key :recent) (let [selected* (h/use-shared-state mdc/colorpicker-selected-broadcast-key :recent)
current-colors (mf/use-state []) selected (deref selected*)
shared-libs (mf/deref refs/libraries) file-id (mf/use-ctx ctx/current-file-id)
file-colors (mf/deref refs/workspace-file-colors)
current-colors* (mf/use-state [])
current-colors (deref current-colors*)
libraries (mf/deref refs/libraries)
recent-colors (mf/deref refs/recent-colors) recent-colors (mf/deref refs/recent-colors)
recent-colors (h/use-equal-memo (filter #(or (:gradient %) (:color %) (:image %)) recent-colors)) recent-colors (mf/with-memo [recent-colors]
(filterv ctc/valid-color? recent-colors))
library-options
(mf/with-memo []
[{:value "recent" :label (tr "workspace.libraries.colors.recent-colors")}
{:value "file" :label (tr "workspace.libraries.colors.file-library")}])
options
(mf/with-memo [library-options file-id]
(into library-options
(comp
(map val)
(map (fn [lib] {:value (d/name (:id lib)) :label (:name lib)})))
(dissoc libraries file-id)))
on-library-change on-library-change
(mf/use-fn (mf/use-fn
(fn [event] (fn [event]
(reset! selected (reset! selected*
(if (or (= event "recent") (if (or (= event "recent")
(= event "file")) (= event "file"))
(keyword event) (keyword event)
(parse-uuid event))))) (parse-uuid event)))))
check-valid-color? valid-color?
(mf/use-fn (mf/use-fn
(mf/deps disable-gradient disable-opacity disable-image)
(fn [color] (fn [color]
(and (or (not disable-gradient) (not (:gradient color))) (and (or (not disable-gradient) (not (:gradient color)))
(or (not disable-opacity) (= 1 (:opacity color))) (or (not disable-opacity) (= 1 (:opacity color)))
(or (not disable-image) (not (:image color)))))) (or (not disable-image) (not (:image color))))))
;; Sort colors by hue and lightness
get-sorted-colors
(mf/use-fn
(fn [colors]
(sort c/sort-colors (into [] (filter check-valid-color?) colors))))
toggle-palette toggle-palette
(mf/use-fn (mf/use-fn
(mf/deps @selected) (mf/deps selected)
(fn [] (fn []
(r/set-resize-type! :bottom) (r/set-resize-type! :bottom)
(dom/add-class! (dom/get-element-by-class "color-palette") "fade-out-down") (dom/add-class! (dom/get-element-by-class "color-palette") "fade-out-down")
(st/emit! (dw/remove-layout-flag :textpalette) (st/emit! (dw/remove-layout-flag :textpalette)
(-> (mdc/show-palette @selected) (-> (mdc/show-palette selected)
(vary-meta assoc ::ev/origin "workspace-colorpicker"))))) (vary-meta assoc ::ev/origin "workspace-colorpicker")))))
shared-libs-options (mapv (fn [lib] {:value (d/name (:id lib)) :label (:name lib)}) (vals shared-libs))
library-options [{:value "recent" :label (tr "workspace.libraries.colors.recent-colors")}
{:value "file" :label (tr "workspace.libraries.colors.file-library")}]
options (concat library-options shared-libs-options)
on-color-click on-color-click
(mf/use-fn (mf/use-fn
(mf/deps state @selected) (mf/deps state selected on-select-color)
(fn [event] (fn [event]
(when-not (= :recent @selected) (when-not (= :recent selected)
(st/emit! (ptk/event (st/emit! (ptk/event
::ev/event ::ev/event
{::ev/name "use-library-color" {::ev/name "use-library-color"
::ev/origin "colorpicker" ::ev/origin "colorpicker"
:external-library (not= :file @selected)}))) :external-library (not= :file selected)})))
(on-select-color state event)))] (on-select-color state event)))]
;; Load library colors when the select is changed ;; Load library colors when the select is changed
(mf/with-effect [@selected recent-colors file-colors] (mf/with-effect [selected recent-colors libraries file-id valid-color?]
(let [colors (cond (let [file-id (if (= selected :file)
(= @selected :recent) file-id
;; The `map?` check is to keep backwards compatibility. We transform from string to map selected)
(map #(if (map? %) % {:color %}) (reverse (or recent-colors [])))
(= @selected :file) colors (if (= selected :recent)
(->> (vals file-colors) (sort-by :name)) ;; NOTE: The `map?` check is to keep backwards
;; compatibility We transform from string to map
:else ;; Library UUID (->> (reverse recent-colors)
(as-> @selected file-id (filter valid-color?)
(->> (get-in shared-libs [file-id :data :colors]) (map-indexed (fn [index color]
(let [color (if (map? color) color {:color color})]
(assoc color ::id (dm/str index)))))
(sort c/sort-colors))
(->> (dm/get-in libraries [file-id :data :colors])
(vals) (vals)
(sort-by :name) (filter valid-color?)
(map #(assoc % :file-id file-id)))))] (map-indexed (fn [index color]
(-> color
(assoc :file-id file-id)
(assoc ::id (dm/str index)))))
(sort-by :name)))]
(if (not= @selected :recent) (reset! current-colors* colors)))
(reset! current-colors (get-sorted-colors colors))
(reset! current-colors (into [] (filter check-valid-color? colors))))))
;; If the file colors change and the file option is selected updates the state
(mf/with-effect [file-colors]
(when (= @selected :file)
(let [colors (vals file-colors)]
(reset! current-colors (get-sorted-colors colors)))))
[:div {:class (stl/css :libraries)} [:div {:class (stl/css :libraries)}
[:div {:class (stl/css :select-wrapper)} [:div {:class (stl/css :select-wrapper)}
[:& select [:& select
{:class (stl/css :shadow-type-select) {:class (stl/css :shadow-type-select)
:default-value (or (name @selected) "recent") :default-value (or (d/name selected) "recent")
:options options :options options
:on-change on-library-change}]] :on-change on-library-change}]]
[:div {:class (stl/css :selected-colors)} [:div {:class (stl/css :selected-colors)}
(when (= @selected :file) (when (= selected :file)
[:button {:class (stl/css :add-color-btn) [:button {:class (stl/css :add-color-btn)
:on-click on-add-library-color} :on-click on-add-library-color}
i/add]) i/add])
@ -132,8 +138,8 @@
:on-click toggle-palette} :on-click toggle-palette}
i/swatches] i/swatches]
(for [[idx color] (map-indexed vector @current-colors)] (for [color current-colors]
[:& cb/color-bullet [:& cb/color-bullet
{:key (dm/str "color-" idx) {:key (dm/str "color-" (::id color))
:color color :color color
:on-click on-color-click}])]])) :on-click on-color-click}])]]))