0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-12 15:51:37 -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.data :as d]
[app.common.data.macros :as dm]
[app.common.types.color :as ctc]
[app.main.data.event :as ev]
[app.main.data.workspace :as dw]
[app.main.data.workspace.colors :as mdc]
@ -17,6 +18,7 @@
[app.main.store :as st]
[app.main.ui.components.color-bullet :as cb]
[app.main.ui.components.select :refer [select]]
[app.main.ui.context :as ctx]
[app.main.ui.hooks :as h]
[app.main.ui.hooks.resize :as r]
[app.main.ui.icons :as i]
@ -27,103 +29,107 @@
(mf/defc libraries
[{: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)
current-colors (mf/use-state [])
(let [selected* (h/use-shared-state mdc/colorpicker-selected-broadcast-key :recent)
selected (deref selected*)
shared-libs (mf/deref refs/libraries)
file-colors (mf/deref refs/workspace-file-colors)
file-id (mf/use-ctx ctx/current-file-id)
current-colors* (mf/use-state [])
current-colors (deref current-colors*)
libraries (mf/deref refs/libraries)
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
(mf/use-fn
(fn [event]
(reset! selected
(reset! selected*
(if (or (= event "recent")
(= event "file"))
(keyword event)
(parse-uuid event)))))
check-valid-color?
valid-color?
(mf/use-fn
(mf/deps disable-gradient disable-opacity disable-image)
(fn [color]
(and (or (not disable-gradient) (not (:gradient color)))
(or (not disable-opacity) (= 1 (:opacity 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
(mf/use-fn
(mf/deps @selected)
(mf/deps selected)
(fn []
(r/set-resize-type! :bottom)
(dom/add-class! (dom/get-element-by-class "color-palette") "fade-out-down")
(st/emit! (dw/remove-layout-flag :textpalette)
(-> (mdc/show-palette @selected)
(-> (mdc/show-palette selected)
(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
(mf/use-fn
(mf/deps state @selected)
(mf/deps state selected on-select-color)
(fn [event]
(when-not (= :recent @selected)
(when-not (= :recent selected)
(st/emit! (ptk/event
::ev/event
{::ev/name "use-library-color"
::ev/origin "colorpicker"
:external-library (not= :file @selected)})))
:external-library (not= :file selected)})))
(on-select-color state event)))]
;; Load library colors when the select is changed
(mf/with-effect [@selected recent-colors file-colors]
(let [colors (cond
(= @selected :recent)
;; The `map?` check is to keep backwards compatibility. We transform from string to map
(map #(if (map? %) % {:color %}) (reverse (or recent-colors [])))
(mf/with-effect [selected recent-colors libraries file-id valid-color?]
(let [file-id (if (= selected :file)
file-id
selected)
(= @selected :file)
(->> (vals file-colors) (sort-by :name))
:else ;; Library UUID
(as-> @selected file-id
(->> (get-in shared-libs [file-id :data :colors])
colors (if (= selected :recent)
;; NOTE: The `map?` check is to keep backwards
;; compatibility We transform from string to map
(->> (reverse recent-colors)
(filter valid-color?)
(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)
(sort-by :name)
(map #(assoc % :file-id file-id)))))]
(filter valid-color?)
(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 (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)))))
(reset! current-colors* colors)))
[:div {:class (stl/css :libraries)}
[:div {:class (stl/css :select-wrapper)}
[:& select
{:class (stl/css :shadow-type-select)
:default-value (or (name @selected) "recent")
:default-value (or (d/name selected) "recent")
:options options
:on-change on-library-change}]]
[:div {:class (stl/css :selected-colors)}
(when (= @selected :file)
(when (= selected :file)
[:button {:class (stl/css :add-color-btn)
:on-click on-add-library-color}
i/add])
@ -132,8 +138,8 @@
:on-click toggle-palette}
i/swatches]
(for [[idx color] (map-indexed vector @current-colors)]
(for [color current-colors]
[:& cb/color-bullet
{:key (dm/str "color-" idx)
{:key (dm/str "color-" (::id color))
:color color
:on-click on-color-click}])]]))