From 831b0baddd7812f5cc20b61bcd7dfab85887ab80 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 4 Feb 2025 20:29:39 +0100 Subject: [PATCH] :zap: Improve efficiency of grouping and sorting token types --- .../app/main/ui/workspace/tokens/sidebar.cljs | 76 +++++++++++-------- .../main/ui/workspace/tokens/token_pill.cljs | 10 +-- frontend/src/app/util/array.cljs | 11 ++- 3 files changed, 59 insertions(+), 38 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs b/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs index 1067f78fb..98e614382 100644 --- a/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs @@ -35,6 +35,7 @@ [app.main.ui.workspace.tokens.token :as wtt] [app.main.ui.workspace.tokens.token-pill :refer [token-pill*]] [app.main.ui.workspace.tokens.token-types :as wtty] + [app.util.array :as array] [app.util.dom :as dom] [app.util.i18n :refer [tr]] [app.util.webapi :as wapi] @@ -74,10 +75,12 @@ (mf/defc token-group* {::mf/private true} - [{:keys [type tokens selected-shapes token-type-props active-theme-tokens]}] + [{:keys [type tokens selected-shapes active-theme-tokens]}] (let [open? (mf/deref (-> (l/key type) (l/derived lens:token-type-open-status))) - {:keys [modal attributes all-attributes title]} token-type-props + + {:keys [modal attributes all-attributes title] :as token-type-props} + (get wtty/token-types type) tokens (mf/with-memo [tokens] @@ -150,7 +153,6 @@ [:> token-pill* {:key (:name token) - :token-type-props token-type-props :token (d/nilv theme-token token) :selected-shapes selected-shapes :active-theme-tokens active-theme-tokens @@ -163,19 +165,23 @@ :on-context-menu on-context-menu}]))]])]])) (defn- get-sorted-token-groups - "Separate token-types into groups of `:empty` or `:filled` depending if tokens exist for that type. - Sort each group alphabetically (by their `:token-key`)." - [tokens] - (let [tokens-by-type (ctob/group-by-type tokens) - {:keys [empty filled]} (->> wtty/token-types - (map (fn [[token-key token-type-props]] - {:token-key token-key - :token-type-props token-type-props - :tokens (get tokens-by-type token-key [])})) - (group-by (fn [{:keys [tokens]}] - (if (empty? tokens) :empty :filled))))] - {:empty (sort-by :token-key empty) - :filled (sort-by :token-key filled)})) + "Separate token-types into groups of `empty` or `filled` depending if + tokens exist for that type. Sort each group alphabetically (by + their type)." + [tokens-by-type] + (loop [empty #js [] + filled #js [] + types (-> wtty/token-types keys seq)] + (if-let [type (first types)] + (if (not-empty (get tokens-by-type type)) + (recur empty + (array/conj! filled type) + (rest types)) + (recur (array/conj! empty type) + filled + (rest types))) + [(seq (array/sort! empty)) + (seq (array/sort! filled))]))) (mf/defc themes-header [_props] @@ -283,31 +289,39 @@ selected-token-set-name (mf/deref refs/workspace-selected-token-set-name) - token-groups + tokens-by-type (mf/with-memo [tokens selected-token-set-tokens] - (-> (select-keys tokens (keys selected-token-set-tokens)) - (get-sorted-token-groups)))] + (let [tokens (reduce-kv (fn [tokens k _] + (if (contains? selected-token-set-tokens k) + tokens + (dissoc tokens k))) + tokens + tokens)] + (ctob/group-by-type tokens))) + + [empty-group filled-group] + (mf/with-memo [tokens-by-type] + (get-sorted-token-groups tokens-by-type))] [:* [:& token-context-menu] [:& title-bar {:all-clickable true :title (tr "workspace.token.tokens-section-title" selected-token-set-name)}] - (for [{:keys [token-key token-type-props tokens]} (:filled token-groups)] - [:> token-group* {:key token-key - :type token-key - :selected-shapes selected-shapes - :active-theme-tokens active-theme-tokens - :tokens tokens - :token-type-props token-type-props}]) + (for [type filled-group] + (let [tokens (get tokens-by-type type)] + [:> token-group* {:key (name type) + :type type + :selected-shapes selected-shapes + :active-theme-tokens active-theme-tokens + :tokens tokens}])) - (for [{:keys [token-key token-type-props tokens]} (:empty token-groups)] - [:> token-group* {:key token-key - :type token-key + (for [type empty-group] + [:> token-group* {:key (name type) + :type type :selected-shapes selected-shapes :active-theme-tokens active-theme-tokens - :tokens tokens - :token-type-props token-type-props}])])) + :tokens []}])])) (mf/defc import-export-button {::mf/wrap-props false} diff --git a/frontend/src/app/main/ui/workspace/tokens/token_pill.cljs b/frontend/src/app/main/ui/workspace/tokens/token_pill.cljs index 24553bdfe..3cc333d46 100644 --- a/frontend/src/app/main/ui/workspace/tokens/token_pill.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/token_pill.cljs @@ -9,6 +9,7 @@ [app.main.ui.ds.foundations.assets.icon :refer [icon*]] [app.main.ui.ds.foundations.utilities.token.token-status :refer [token-status-icon*]] [app.main.ui.workspace.tokens.token :as wtt] + [app.main.ui.workspace.tokens.token-types :as wtty] [app.util.dom :as dom] [app.util.i18n :refer [tr]] [cuerdas.core :as str] @@ -95,9 +96,9 @@ (defn- generate-tooltip "Generates a tooltip for a given token" - [is-viewer shape token-type-props token half-applied no-valid-value ref-not-in-active-set] + [is-viewer shape token half-applied no-valid-value ref-not-in-active-set] (let [{:keys [name value resolved-value type]} token - {:keys [title]} token-type-props + {:keys [title] :as token-type-props} (get wtty/token-types (:type token)) applied-tokens (:applied-tokens shape) app-token-vals (set (vals applied-tokens)) app-token-keys (keys applied-tokens) @@ -142,7 +143,7 @@ (contains? active-tokens match))) (mf/defc token-pill* - [{:keys [on-click token full-applied on-context-menu half-applied selected-shapes token-type-props active-theme-tokens]}] + [{:keys [on-click token full-applied on-context-menu half-applied selected-shapes active-theme-tokens]}] (let [{:keys [name value errors]} token is-reference? (wtt/is-reference? token) @@ -203,8 +204,7 @@ (mf/deps selected-shapes is-viewer) (fn [event] (let [node (dom/get-current-target event) - title (generate-tooltip is-viewer (first selected-shapes) - token-type-props token + title (generate-tooltip is-viewer (first selected-shapes) token half-applied no-valid-value ref-not-in-active-set)] (dom/set-attribute! node "title" title))))] diff --git a/frontend/src/app/util/array.cljs b/frontend/src/app/util/array.cljs index 1e56d99b3..18ef45aef 100644 --- a/frontend/src/app/util/array.cljs +++ b/frontend/src/app/util/array.cljs @@ -6,9 +6,10 @@ (ns app.util.array "A collection of helpers for work with javascript arrays." - (:refer-clojure :exclude [conj! conj filter map reduce find]) + (:refer-clojure :exclude [conj! conj filter map reduce find sort]) (:require - [cljs.core :as c])) + [cljs.core :as c] + [goog.array :as garray])) (defn conj "A conj like function for js arrays." @@ -67,3 +68,9 @@ (defn find [f v] (.find ^js/Array v f)) + +(defn sort! + [a] + (garray/sort a compare) + a) +