From f82c6824219ed96ad69168fbd87b8b07253ee689 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 28 Aug 2023 11:14:59 +0200 Subject: [PATCH 01/16] :zap: Delimit attrs on update-shape-flags impl --- frontend/src/app/main/data/workspace/shapes.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/main/data/workspace/shapes.cljs b/frontend/src/app/main/data/workspace/shapes.cljs index 37d52b9dcd..9631d626ee 100644 --- a/frontend/src/app/main/data/workspace/shapes.cljs +++ b/frontend/src/app/main/data/workspace/shapes.cljs @@ -474,7 +474,7 @@ ids (if (boolean? blocked) (into ids (->> ids (mapcat #(cph/get-children-ids objects %)))) ids)] - (rx/of (dch/update-shapes ids update-fn)))))) + (rx/of (dch/update-shapes ids update-fn {:attrs #{:blocked :hidden}})))))) (defn toggle-visibility-selected [] From 7f91619075528dc05e0d8c2efb93475e47f002b6 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 28 Aug 2023 11:16:13 +0200 Subject: [PATCH 02/16] :zap: Add improved text change detection on viewport text renderer --- .../shapes/text/viewport_texts_html.cljs | 41 +++++++++---------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/shapes/text/viewport_texts_html.cljs b/frontend/src/app/main/ui/workspace/shapes/text/viewport_texts_html.cljs index 65804663b1..d1a8b3b4dc 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/viewport_texts_html.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/viewport_texts_html.cljs @@ -125,34 +125,32 @@ (defn text-properties-equal? [shape other] + ;; FIXME: use dm/get-prop (or (identical? shape other) - (and - ;; Check if both shapes are equivalent removing their geometry data - (= (dissoc shape :migrate :points :selrect :height :width :x :y :position-data :modifiers) - (dissoc other :migrate :points :selrect :height :width :x :y :position-data :modifiers)) - - ;; Check if the position and size is close. If any of these changes the shape has changed - ;; and if not there is no geometry relevant change - (mth/close? (:x shape) (:x other)) - (mth/close? (:y shape) (:y other)) - (mth/close? (:width shape) (:width other)) - (mth/close? (:height shape) (:height other))))) + (and (= (:content shape) (:content other)) + ;; Check if the position and size is close. If any of these changes the shape has changed + ;; and if not there is no geometry relevant change + (mth/close? (:x shape) (:x other)) + (mth/close? (:y shape) (:y other)) + (mth/close? (:width shape) (:width other)) + (mth/close? (:height shape) (:height other))))) (mf/defc text-changes-renderer {::mf/wrap-props false} [props] - (let [text-shapes (obj/get props "text-shapes") + (let [text-shapes (unchecked-get props "text-shapes") prev-text-shapes (hooks/use-previous text-shapes) ;; We store in the state the texts still pending to be calculated so we can ;; get its position - pending-update (mf/use-state {}) + pending-update* (mf/use-state {}) + pending-update (deref pending-update*) text-change? (fn [id] (let [new-shape (get text-shapes id) old-shape (get prev-text-shapes id) - remote? (some? (-> new-shape meta :session-id))] + remote? (some? (-> new-shape meta :session-id))] (or (and (not remote?) ;; changes caused by a remote peer are not re-calculated (not (text-properties-equal? old-shape new-shape))) @@ -160,9 +158,8 @@ (nil? (:position-data new-shape))))) changed-texts - (mf/use-memo - (mf/deps text-shapes @pending-update) - #(let [pending-shapes (into #{} (vals @pending-update))] + (mf/with-memo [text-shapes pending-update] + (let [pending-shapes (into #{} (vals pending-update))] (->> (keys text-shapes) (filter (fn [id] (or (contains? pending-shapes id) @@ -170,18 +167,18 @@ (map (d/getf text-shapes))))) handle-update-shape - (mf/use-callback + (mf/use-fn (fn [shape node] ;; Unique to indentify the pending state (let [uid (js/Symbol)] - (swap! pending-update assoc uid (:id shape)) + (swap! pending-update* assoc uid (:id shape)) (p/then (update-text-shape shape node) - #(swap! pending-update dissoc uid)))))] + #(swap! pending-update* dissoc uid)))))] [:.text-changes-renderer (for [{:keys [id] :as shape} changed-texts] - [:& text-container {:key (str (dm/str "text-container-" id)) + [:& text-container {:key (dm/str "text-container-" id) :shape shape :on-update handle-update-shape}])])) @@ -213,7 +210,7 @@ [:.text-changes-renderer (for [{:keys [id] :as shape} changed-texts] - [:& text-container {:key (str (dm/str "text-container-" id)) + [:& text-container {:key (dm/str "text-container-" id) :shape shape :on-update handle-update-shape}])])) From b28cad2250e6b18d65b24b170fa75fbeeea73951 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 28 Aug 2023 14:58:41 +0200 Subject: [PATCH 03/16] :zap: Improve efficiency of equiv impl of jvm-custom-record --- common/src/app/common/record.cljc | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/common/src/app/common/record.cljc b/common/src/app/common/record.cljc index c551fbbaf7..db808fa879 100644 --- a/common/src/app/common/record.cljc +++ b/common/src/app/common/record.cljc @@ -9,8 +9,7 @@ (:refer-clojure :exclude [defrecord assoc! clone]) #?(:cljs (:require-macros [app.common.record])) #?(:clj - (:import java.util.Map - java.util.Map$Entry))) + (:import java.util.Map$Entry))) #_:clj-kondo/ignore (defmacro caching-hash @@ -44,11 +43,12 @@ key-sym (gensym "key-") val-sym (gensym "val-") this-sym (with-meta 'this {:tag tagname})] - ['cljs.core/ICloneable + ['cljs.core/IRecord + 'cljs.core/ICloneable `(~'-clone [~this-sym] (new ~tagname ~@(generate-field-access this-sym val-sym fields))) - 'IHash + 'cljs.core/IHash `(~'-hash [~this-sym] (caching-hash ~this-sym (fn [coll#] @@ -175,16 +175,17 @@ val-sym 'val this-sym (with-meta 'this {:tag tagname})] - ['clojure.lang.MapEquivalence + ['clojure.lang.IRecord 'clojure.lang.IPersistentMap - - `(~'equiv [~this-sym ~'other] - (and (instance? java.util.Map ~'other) (= (.count ~this-sym) (.size ^Map ~'other)) - (every? (fn [^clojure.lang.MapEntry e#] - (let [k# (.key e#)] - (and (.containsKey ^Map ~'other k#) - (= (.val e#) (.get ^Map ~'other k#))))) - (.seq ~this-sym)))) + `(~'equiv [~this-sym ~val-sym] + (and (some? ~val-sym) + (instance? ~tagname ~val-sym) + ~@(map (fn [field] + `(= (.. ~this-sym ~(property-symbol field)) + (.. ~(with-meta val-sym {:tag tagname}) ~(property-symbol field)))) + base-fields) + (= (. ~this-sym ~'-$extmap) + (. ~(with-meta val-sym {:tag tagname}) ~'-$extmap)))) `(~'entryAt [~this-sym ~key-sym] (let [v# (.valAt ~this-sym ~key-sym ::not-found)] From 58f788455f7f165691938b8a2f5c776dcecc4260 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 28 Aug 2023 15:36:23 +0200 Subject: [PATCH 04/16] :zap: Add experimental equality with exceptions props checking to frames --- common/src/app/common/record.cljc | 50 +++++++++++++++---- .../src/app/main/ui/workspace/shapes.cljs | 46 +++++++++-------- .../app/main/ui/workspace/shapes/frame.cljs | 28 +++++++++-- 3 files changed, 90 insertions(+), 34 deletions(-) diff --git a/common/src/app/common/record.cljc b/common/src/app/common/record.cljc index db808fa879..97c25cc4a0 100644 --- a/common/src/app/common/record.cljc +++ b/common/src/app/common/record.cljc @@ -36,12 +36,17 @@ :else `(. ~this-sym ~(property-symbol field)))) fields))) + +(defprotocol ICustomRecordEquiv + (-equiv-with-exceptions [_ other exceptions])) + #?(:clj (defn emit-impl-js [tagname base-fields] (let [fields (conj base-fields '$meta '$extmap (with-meta '$hash {:mutable true})) key-sym (gensym "key-") val-sym (gensym "val-") + othr-sym (with-meta 'other {:tag tagname}) this-sym (with-meta 'this {:tag tagname})] ['cljs.core/IRecord 'cljs.core/ICloneable @@ -58,16 +63,41 @@ (. ~this-sym ~'-$hash))) 'cljs.core/IEquiv - `(~'-equiv [~this-sym ~val-sym] - (and (some? ~val-sym) - (identical? (.-constructor ~this-sym) - (.-constructor ~val-sym)) - ~@(map (fn [field] - `(= (.. ~this-sym ~(property-symbol field)) - (.. ~(with-meta val-sym {:tag tagname}) ~(property-symbol field)))) - base-fields) - (= (. ~this-sym ~'-$extmap) - (. ~(with-meta val-sym {:tag tagname}) ~'-$extmap)))) + `(~'-equiv [~this-sym ~othr-sym] + (or (identical? ~this-sym ~othr-sym) + (and (some? ~othr-sym) + (identical? (.-constructor ~this-sym) + (.-constructor ~othr-sym)) + ~@(map (fn [field] + `(= (.. ~this-sym ~(property-symbol field)) + (.. ~(with-meta othr-sym {:tag tagname}) ~(property-symbol field)))) + base-fields) + + (= (. ~this-sym ~'-$extmap) + (. ~(with-meta othr-sym {:tag tagname}) ~'-$extmap))))) + + `ICustomRecordEquiv + `(~'-equiv-with-exceptions [~this-sym ~othr-sym ~'exceptions] + (or (identical? ~this-sym ~othr-sym) + (and (some? ~othr-sym) + (identical? (.-constructor ~this-sym) + (.-constructor ~othr-sym)) + (and ~@(->> base-fields + (map (fn [field] + `(= (.. ~this-sym ~(property-symbol field)) + (.. ~(with-meta othr-sym {:tag tagname}) ~(property-symbol field)))))) + (== (count (. ~this-sym ~'-$extmap)) + (count (. ~othr-sym ~'-$extmap)))) + + (reduce-kv (fn [~'_ ~'k ~'v] + (if (contains? ~'exceptions ~'k) + true + (if (= (get (. ~this-sym ~'-$extmap) ~'k ::not-exists) ~'v) + true + (reduced false)))) + true + (. ~othr-sym ~'-$extmap))))) + 'cljs.core/IMeta `(~'-meta [~this-sym] (. ~this-sym ~'-$meta)) diff --git a/frontend/src/app/main/ui/workspace/shapes.cljs b/frontend/src/app/main/ui/workspace/shapes.cljs index 36f02ddc38..2db204d3e0 100644 --- a/frontend/src/app/main/ui/workspace/shapes.cljs +++ b/frontend/src/app/main/ui/workspace/shapes.cljs @@ -68,46 +68,52 @@ [:g.frame-children (for [shape shapes] - [:g.ws-shape-wrapper {:key (:id shape)} - (cond - (not (cph/frame-shape? shape)) + [:g.ws-shape-wrapper {:key (dm/str (dm/get-prop shape :id))} + (if (not ^boolean (cph/frame-shape? shape)) [:& shape-wrapper {:shape shape}] + (if ^boolean (cph/is-direct-child-of-root? shape) + [:& root-frame-wrapper + {:shape shape + :objects (get frame-objects (dm/get-prop shape :id)) + :thumbnail? (not (contains? active-frames (dm/get-prop shape :id)))}] + [:& nested-frame-wrapper + {:shape shape + :objects (get frame-objects (dm/get-prop shape :id))}]))])]]])) - (cph/is-direct-child-of-root? shape) - [:& root-frame-wrapper - {:shape shape - :objects (get frame-objects (:id shape)) - :thumbnail? (not (contains? active-frames (:id shape)))}] - - :else - [:& nested-frame-wrapper - {:shape shape - :objects (get frame-objects (:id shape))}])])]]])) +(defn- check-shape-wrapper-props + [np op] + (frame/check-shape (unchecked-get np "shape") + (unchecked-get op "shape"))) (mf/defc shape-wrapper - {::mf/wrap [#(mf/memo' % (mf/check-props ["shape"]))] + {::mf/wrap [#(mf/memo' % check-shape-wrapper-props)] ::mf/wrap-props false} [props] - (let [shape (obj/get props "shape") + (let [shape (unchecked-get props "shape") + shape-type (dm/get-prop shape :type) + shape-id (dm/get-prop shape :id) + ;; FIXME: WARN: this breaks react rule of hooks (hooks can't be under conditional) active-frames - (when (cph/is-direct-child-of-root? shape) (mf/use-ctx ctx/active-frames)) + (when (cph/is-direct-child-of-root? shape) + (mf/use-ctx ctx/active-frames)) thumbnail? (and (some? active-frames) - (not (contains? active-frames (:id shape)))) + (not (contains? active-frames shape-id))) opts #js {:shape shape :thumbnail? thumbnail?} [wrapper wrapper-props] - (if (= :svg-raw (:type shape)) + (if (= :svg-raw shape-type) [mf/Fragment nil] ["g" #js {:className "workspace-shape-wrapper"}])] - (when (and (some? shape) (not (:hidden shape))) + (when (and (some? shape) + (not ^boolean (:hidden shape))) [:> wrapper wrapper-props - (case (:type shape) + (case shape-type :path [:> path/path-wrapper opts] :text [:> text/text-wrapper opts] :group [:> group-wrapper opts] diff --git a/frontend/src/app/main/ui/workspace/shapes/frame.cljs b/frontend/src/app/main/ui/workspace/shapes/frame.cljs index 87c216d03f..24437dc94b 100644 --- a/frontend/src/app/main/ui/workspace/shapes/frame.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/frame.cljs @@ -9,6 +9,7 @@ [app.common.data :as d] [app.common.data.macros :as dm] [app.common.pages.helpers :as cph] + [app.common.record :as cr] [app.main.data.workspace.state-helpers :as wsh] [app.main.data.workspace.thumbnails :as dwt] [app.main.refs :as refs] @@ -25,17 +26,36 @@ [beicon.core :as rx] [rumext.v2 :as mf])) +(def ^:private excluded-attrs + #{:blocked + :hide-fill-on-export + :collapsed + :remote-synced + :exports}) + +(defn check-shape + [new-shape old-shape] + (cr/-equiv-with-exceptions old-shape new-shape excluded-attrs)) + +(defn check-frame-props + [np op] + (check-shape (unchecked-get np "shape") + (unchecked-get op "shape"))) + (defn frame-shape-factory [shape-wrapper] (let [frame-shape (frame/frame-shape shape-wrapper)] (mf/fnc frame-shape-inner - {::mf/wrap [#(mf/memo' % (mf/check-props ["shape"]))] + {::mf/wrap [#(mf/memo' % check-frame-props)] ::mf/wrap-props false ::mf/forward-ref true} [props ref] (let [shape (unchecked-get props "shape") - childs-ref (mf/use-memo (mf/deps (:id shape)) #(refs/children-objects (:id shape))) + shape-id (dm/get-prop shape :id) + + childs-ref (mf/with-memo [shape-id] + (refs/children-objects shape-id)) childs (mf/deref childs-ref)] [:& (mf/provider embed/context) {:value true} @@ -46,8 +66,8 @@ [new-props old-props] (and (= (unchecked-get new-props "thumbnail?") (unchecked-get old-props "thumbnail?")) - (= (unchecked-get new-props "shape") - (unchecked-get old-props "shape")))) + (check-shape (unchecked-get new-props "shape") + (unchecked-get old-props "shape")))) (defn nested-frame-wrapper-factory [shape-wrapper] From 82f1b965036d9a03ce0a2289399f1d58d6b2de70 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 28 Aug 2023 15:56:41 +0200 Subject: [PATCH 05/16] :zap: Add micro optimization to `is-direct-child-of-root?` helper --- common/src/app/common/pages/helpers.cljc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/common/src/app/common/pages/helpers.cljc b/common/src/app/common/pages/helpers.cljc index 29a0e7437a..58124284d0 100644 --- a/common/src/app/common/pages/helpers.cljc +++ b/common/src/app/common/pages/helpers.cljc @@ -29,9 +29,10 @@ (defn is-direct-child-of-root? ([objects id] (is-direct-child-of-root? (get objects id))) - ([{:keys [frame-id type]}] - (and (= type :frame) - (= frame-id uuid/zero)))) + ([shape] + (and (some? shape) + (= (dm/get-prop shape :type) :frame) + (= (dm/get-prop shape :frame-id) uuid/zero)))) (defn frame-shape? ([objects id] From 1a1e55037b75431c27a56360b68354f746a1ab27 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 28 Aug 2023 15:57:13 +0200 Subject: [PATCH 06/16] :fire: Remove unused conditional on root-shape component --- .../src/app/main/ui/workspace/shapes.cljs | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/shapes.cljs b/frontend/src/app/main/ui/workspace/shapes.cljs index 2db204d3e0..4618c37bc8 100644 --- a/frontend/src/app/main/ui/workspace/shapes.cljs +++ b/frontend/src/app/main/ui/workspace/shapes.cljs @@ -53,9 +53,8 @@ ;; We group the objects together per frame-id so if an object of a different ;; frame changes won't affect the rendering frame frame-objects - (mf/use-memo - (mf/deps objects) - #(cph/objects-by-frame objects))] + (mf/with-memo [objects] + (cph/objects-by-frame objects))] [:g {:id (dm/str "shape-" uuid/zero)} [:& (mf/provider ctx/active-frames) {:value active-frames} @@ -69,17 +68,12 @@ [:g.frame-children (for [shape shapes] [:g.ws-shape-wrapper {:key (dm/str (dm/get-prop shape :id))} - (if (not ^boolean (cph/frame-shape? shape)) - [:& shape-wrapper - {:shape shape}] - (if ^boolean (cph/is-direct-child-of-root? shape) - [:& root-frame-wrapper - {:shape shape - :objects (get frame-objects (dm/get-prop shape :id)) - :thumbnail? (not (contains? active-frames (dm/get-prop shape :id)))}] - [:& nested-frame-wrapper - {:shape shape - :objects (get frame-objects (dm/get-prop shape :id))}]))])]]])) + (if ^boolean (cph/frame-shape? shape) + [:& root-frame-wrapper + {:shape shape + :objects (get frame-objects (dm/get-prop shape :id)) + :thumbnail? (not (contains? active-frames (dm/get-prop shape :id)))}] + [:& shape-wrapper {:shape shape}])])]]])) (defn- check-shape-wrapper-props [np op] From c6e248b52f6630224293cf9661a1a18e47e48b96 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 28 Aug 2023 16:08:37 +0200 Subject: [PATCH 07/16] :sparkles: Add correct impl for `is-direct-child-of-root?` helper And we restore the previously removed helper and incorrectly replaced by the `is-direct-child-of-root?`. In penpot exists two concepts: root and root-frame; root is the artificially created shape that represents the ROOT, and root-frame means a frame that is shape of frame type which is a direct children of ROOT. --- common/src/app/common/pages/helpers.cljc | 10 ++++++++-- frontend/src/app/main/ui/viewer/inspect/render.cljs | 4 ++-- frontend/src/app/main/ui/workspace/shapes.cljs | 3 +-- frontend/src/app/main/ui/workspace/viewport.cljs | 4 ++-- .../src/app/main/ui/workspace/viewport/guides.cljs | 2 +- .../src/app/main/ui/workspace/viewport/hooks.cljs | 11 ++++++----- frontend/src/app/util/code_gen/style_css_values.cljs | 6 +++--- 7 files changed, 23 insertions(+), 17 deletions(-) diff --git a/common/src/app/common/pages/helpers.cljc b/common/src/app/common/pages/helpers.cljc index 58124284d0..96dd03c8fd 100644 --- a/common/src/app/common/pages/helpers.cljc +++ b/common/src/app/common/pages/helpers.cljc @@ -29,6 +29,12 @@ (defn is-direct-child-of-root? ([objects id] (is-direct-child-of-root? (get objects id))) + ([shape] + (and (some? shape) (= (dm/get-prop shape :frame-id) uuid/zero)))) + +(defn root-frame? + ([objects id] + (root-frame? (get objects id))) ([shape] (and (some? shape) (= (dm/get-prop shape :type) :frame) @@ -229,7 +235,7 @@ (or (root? frame) (nil? frame)) nil - (is-direct-child-of-root? frame) + (root-frame? frame) frame :else @@ -614,7 +620,7 @@ (->> (get-parent-ids objects shape-id) (cons shape-id) (map (d/getf objects)) - (d/seek is-direct-child-of-root?) + (d/seek root-frame?) :id)) (defn comparator-layout-z-index diff --git a/frontend/src/app/main/ui/viewer/inspect/render.cljs b/frontend/src/app/main/ui/viewer/inspect/render.cljs index a2d944bfa9..136f593b8b 100644 --- a/frontend/src/app/main/ui/viewer/inspect/render.cljs +++ b/frontend/src/app/main/ui/viewer/inspect/render.cljs @@ -34,7 +34,7 @@ [shape hover?] (fn [event] (when-not (or (cph/group-shape? shape) - (cph/is-direct-child-of-root? shape)) + (cph/root-frame? shape)) (dom/prevent-default event) (dom/stop-propagation event) (st/emit! (dv/hover-shape (:id shape) hover?))))) @@ -42,7 +42,7 @@ (defn select-shape [shape] (fn [event] (when-not (or (cph/group-shape? shape) - (cph/is-direct-child-of-root? shape)) + (cph/root-frame? shape)) (dom/stop-propagation event) (dom/prevent-default event) (cond diff --git a/frontend/src/app/main/ui/workspace/shapes.cljs b/frontend/src/app/main/ui/workspace/shapes.cljs index 4618c37bc8..ce440a8900 100644 --- a/frontend/src/app/main/ui/workspace/shapes.cljs +++ b/frontend/src/app/main/ui/workspace/shapes.cljs @@ -90,7 +90,7 @@ ;; FIXME: WARN: this breaks react rule of hooks (hooks can't be under conditional) active-frames - (when (cph/is-direct-child-of-root? shape) + (when (cph/root-frame? shape) (mf/use-ctx ctx/active-frames)) thumbnail? @@ -125,4 +125,3 @@ (def bool-wrapper (bool/bool-wrapper-factory shape-wrapper)) (def root-frame-wrapper (frame/root-frame-wrapper-factory shape-wrapper)) (def nested-frame-wrapper (frame/nested-frame-wrapper-factory shape-wrapper)) - diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 4fc1a0d766..275d9f4a0c 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -141,7 +141,7 @@ (fn [] (let [parent-id (->> @hover-ids - (d/seek (partial cph/is-direct-child-of-root? base-objects)))] + (d/seek (partial cph/root-frame? base-objects)))] (when (some? parent-id) (get base-objects parent-id))))) @@ -244,7 +244,7 @@ first-selected-shape (first selected-shapes) selecting-first-level-frame? (and one-selected-shape? - (cph/is-direct-child-of-root? first-selected-shape)) + (cph/root-frame? first-selected-shape)) offset-x (if selecting-first-level-frame? (:x first-selected-shape) diff --git a/frontend/src/app/main/ui/workspace/viewport/guides.cljs b/frontend/src/app/main/ui/workspace/viewport/guides.cljs index 5d8a254e74..1182ca4ea4 100644 --- a/frontend/src/app/main/ui/workspace/viewport/guides.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/guides.cljs @@ -293,7 +293,7 @@ (not (is-guide-inside-frame? (assoc guide :position pos) frame)))] (when (or (nil? frame) - (and (cph/is-direct-child-of-root? frame) + (and (cph/root-frame? frame) (not (ctst/rotated-frame? frame)))) [:g.guide-area {:opacity (when frame-guide-outside? 0)} (when-not disabled-guides? diff --git a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs index d2652212f1..3423a5da7c 100644 --- a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs @@ -217,7 +217,7 @@ root-frame-with-data? #(as-> (get objects %) obj - (and (cph/is-direct-child-of-root? obj) + (and (cph/root-frame? obj) (d/not-empty? (:shapes obj)) (not (ctk/instance-head? obj)) (not (ctk/main-instance? obj)))) @@ -240,9 +240,10 @@ no-fill-nested-frames? (fn [id] - (and (cph/frame-shape? objects id) - (not (cph/is-direct-child-of-root? objects id)) - (empty? (dm/get-in objects [id :fills])))) + (let [shape (get objects id)] + (and (cph/frame-shape? shape) + (not (cph/is-direct-child-of-root? shape)) + (empty? (get shape :fills))))) hover-shape (->> ids @@ -276,7 +277,7 @@ (let [all-frames (mf/use-memo (mf/deps objects) #(ctt/get-root-frames-ids objects)) selected-frames (mf/use-memo (mf/deps selected) #(->> all-frames (filter selected))) - xf-selected-frame (comp (remove cph/is-direct-child-of-root?) + xf-selected-frame (comp (remove cph/root-frame?) (map #(cph/get-shape-id-root-frame objects %))) selected-shapes-frames (mf/use-memo (mf/deps selected) #(into #{} xf-selected-frame selected)) diff --git a/frontend/src/app/util/code_gen/style_css_values.cljs b/frontend/src/app/util/code_gen/style_css_values.cljs index c45e2679d3..53805f28f2 100644 --- a/frontend/src/app/util/code_gen/style_css_values.cljs +++ b/frontend/src/app/util/code_gen/style_css_values.cljs @@ -30,7 +30,7 @@ (not (ctl/layout-absolute? shape)) (or (cph/group-shape? shape) (cph/frame-shape? shape))) - (cph/is-direct-child-of-root? shape)) + (cph/root-frame? shape)) :relative (and (ctl/any-layout-immediate-child? objects shape) @@ -54,14 +54,14 @@ ;;shape (gsh/transform-shape) shape-value (get selrect coord) ] - (when (and (not (cph/is-direct-child-of-root? shape)) + (when (and (not (cph/root-frame? shape)) (or (not (ctl/any-layout-immediate-child? objects shape)) (ctl/layout-absolute? shape))) (- shape-value parent-value)))) #_(defn get-shape-position [shape objects coord] - (when-not (or (cph/is-direct-child-of-root? shape) + (when-not (or (cph/root-frame? shape) (and (ctl/any-layout-immediate-child? objects shape) (not (ctl/layout-absolute? shape)))) (let [parent (get objects (:parent-id shape)) From b649adf544d884a5e8a3a2fe116570fe91f3554c Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 28 Aug 2023 19:24:20 +0200 Subject: [PATCH 08/16] :lipstick: Add cosmetic improvements to sidebar assets namespace --- .../app/main/ui/workspace/sidebar/assets.cljs | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs index 242475b517..6bb7c755a0 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs @@ -5,7 +5,7 @@ ;; Copyright (c) KALEIDOS INC (ns app.main.ui.workspace.sidebar.assets - (:require-macros [app.main.style :refer [css]]) + (:require-macros [app.main.style :as stl]) (:require [app.common.data.macros :as dm] [app.main.data.modal :as modal] @@ -80,7 +80,6 @@ :open-menu false}) filters (deref filters*) term (:term filters) - ordering (:ordering filters) list-style (:list-style filters) menu-open? (:open-menu filters) section (:section filters) @@ -175,22 +174,22 @@ :data-test "typographies"}]] (if ^boolean new-css-system - [:div {:class (css :assets-bar)} - [:div {:class (css :assets-header)} + [:div {:class (stl/css :assets-bar)} + [:div {:class (stl/css :assets-header)} (when-not ^boolean read-only? - [:button {:class (css :libraries-button) - :on-click #(modal/show! :libraries-dialog {})} - [:span {:class (css :libraries-icon)} + [:button {:class (stl/css :libraries-button) + :on-click show-libraries-dialog} + [:span {:class (stl/css :libraries-icon)} i/library-refactor] (tr "workspace.assets.libraries")]) - [:div {:class (css :search-wrapper)} + [:div {:class (stl/css :search-wrapper)} [:& search-bar {:on-change on-search-term-change :value term :placeholder (tr "workspace.assets.search")} [:button {:on-click on-open-menu - :class (dom/classnames (css :section-button) true)} + :class (stl/css :section-button)} i/filter-refactor]] [:& context-menu-a11y {:on-close on-menu-close @@ -203,7 +202,7 @@ :left 64 :options options :workspace? true}] - [:button {:class (css :sort-button) + [:button {:class (stl/css :sort-button) :on-click toggle-ordering} (if reverse-sort? i/asc-sort-refactor @@ -212,7 +211,7 @@ [:& (mf/provider cmm/assets-filters) {:value filters} [:& (mf/provider cmm/assets-toggle-ordering) {:value toggle-ordering} [:& (mf/provider cmm/assets-toggle-list-style) {:value toggle-list-style} - [:div {:class (dom/classnames (css :libraries-wrapper) true)} + [:div {:class (stl/css :libraries-wrapper)} [:& assets-local-library {:filters filters}] [:& assets-libraries {:filters filters}]]]]]] From 50a49e5fbfc78b7e1053f467eee56f2a72e2c2bc Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 28 Aug 2023 19:24:57 +0200 Subject: [PATCH 09/16] :sparkles: Show by default assets as not visible --- .../workspace/sidebar/assets/file_library.cljs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/file_library.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/file_library.cljs index 881c6c4548..5b8c657297 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/file_library.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/file_library.cljs @@ -248,7 +248,7 @@ :local? local? :components components :listing-thumbs? listing-thumbs? - :open? (get open-status :components true) + :open? (get open-status :components false) :open-status-ref open-status-ref :reverse-sort? reverse-sort? :selected selected @@ -263,7 +263,7 @@ :local? local? :objects media :listing-thumbs? listing-thumbs? - :open? (get open-status :graphics true) + :open? (get open-status :graphics false) :open-status-ref open-status-ref :reverse-sort? reverse-sort? :selected selected @@ -276,7 +276,7 @@ {:file-id file-id :local? local? :colors colors - :open? (get open-status :colors true) + :open? (get open-status :colors false) :open-status-ref open-status-ref :reverse-sort? reverse-sort? :selected selected @@ -290,7 +290,7 @@ :file-id (:id file) :local? local? :typographies typographies - :open? (get open-status :typographies true) + :open? (get open-status :typographies false) :open-status-ref open-status-ref :reverse-sort? reverse-sort? :selected selected @@ -327,7 +327,7 @@ :local? local? :components components :listing-thumbs? listing-thumbs? - :open? (get open-status :components true) + :open? (get open-status :components false) :open-status-ref open-status-ref :reverse-sort? reverse-sort? :selected selected @@ -342,7 +342,7 @@ :local? local? :objects media :listing-thumbs? listing-thumbs? - :open? (get open-status :graphics true) + :open? (get open-status :graphics false) :open-status-ref open-status-ref :reverse-sort? reverse-sort? :selected selected @@ -355,7 +355,7 @@ {:file-id file-id :local? local? :colors colors - :open? (get open-status :colors true) + :open? (get open-status :colors false) :open-status-ref open-status-ref :reverse-sort? reverse-sort? :selected selected @@ -369,7 +369,7 @@ :file-id (:id file) :local? local? :typographies typographies - :open? (get open-status :typographies true) + :open? (get open-status :typographies false) :open-status-ref open-status-ref :reverse-sort? reverse-sort? :selected selected From 62f15f9b9d690a53e1d661c9a331b90c1d7b3e45 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 29 Aug 2023 10:03:02 +0200 Subject: [PATCH 10/16] :zap: Make components assets gropups collapsed by default on assets tab --- .../workspace/sidebar/assets/components.cljs | 39 ++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs index 2e8999a068..79b477fc08 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs @@ -206,7 +206,7 @@ on-drag-start do-rename cancel-rename on-rename-group on-group on-ungroup on-context-menu selected-full]}] - (let [group-open? (get open-groups prefix true) + (let [group-open? (get open-groups prefix (if (= prefix "") true false)) new-css-system (mf/use-ctx ctx/new-css-system) dragging* (mf/use-state false) dragging? (deref dragging*) @@ -232,6 +232,7 @@ (mf/deps dragging* prefix selected-paths selected-full) (fn [event] (cmm/on-drop-asset-group event dragging* prefix selected-paths selected-full dwl/rename-component)))] + (if ^boolean new-css-system [:div {:class (dom/classnames (css :component-group) true) :on-drag-enter on-drag-enter @@ -599,24 +600,26 @@ :multi true :ref input-ref :on-selected on-file-selected}]])])) + [:& cmm/asset-section-block {:role :content} - [:& components-group {:file-id file-id - :prefix "" - :groups groups - :open-groups open-groups - :renaming (when ^boolean renaming? current-component-id) - :listing-thumbs? listing-thumbs? - :selected selected - :on-asset-click on-asset-click - :on-drag-start on-drag-start - :do-rename do-rename - :cancel-rename cancel-rename - :on-rename-group on-rename-group - :on-group on-group - :on-ungroup on-ungroup - :on-context-menu on-context-menu - :selected-full selected-full}] - (when local? + (when ^boolean open? + [:& components-group {:file-id file-id + :prefix "" + :groups groups + :open-groups open-groups + :renaming (when ^boolean renaming? current-component-id) + :listing-thumbs? listing-thumbs? + :selected selected + :on-asset-click on-asset-click + :on-drag-start on-drag-start + :do-rename do-rename + :cancel-rename cancel-rename + :on-rename-group on-rename-group + :on-group on-group + :on-ungroup on-ungroup + :on-context-menu on-context-menu + :selected-full selected-full}]) + (when ^boolean local? [:& cmm/assets-context-menu {:on-close on-close-menu :state @menu-state From 9804bd88c21cdb0e9a86d7faa5da6ce478acf21b Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 29 Aug 2023 11:33:13 +0200 Subject: [PATCH 11/16] :sparkles: Add improvements to css modules related macros --- frontend/src/app/main/style.clj | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/frontend/src/app/main/style.clj b/frontend/src/app/main/style.clj index 7ce0585cec..2ffbcc6043 100644 --- a/frontend/src/app/main/style.clj +++ b/frontend/src/app/main/style.clj @@ -15,9 +15,18 @@ (def ^:dynamic *css-data* nil) (def ^:private xform-css - (map (fn [k] - (let [cn (name k)] - (or (get *css-data* (keyword cn)) cn))))) + (keep (fn [k] + (cond + (keyword? k) + (let [knm (name k) + kns (namespace k)] + (case kns + "global" knm + "old-css" (if (nil? *css-data*) knm "") + (or (get *css-data* (keyword knm)) knm))) + + (string? k) + k)))) (defmacro css* "Just coerces all params to strings and concats them with @@ -35,7 +44,8 @@ (let [fname (-> *ns* meta :file) path (str (subs fname 0 (- (count fname) 4)) "css.json") data (-> (slurp (io/resource path)) - (json/read-str :key-fn keyword))] + (json/read-str :key-fn keyword) + (or {}))] (if (symbol? (first selectors)) `(if ~(with-meta (first selectors) {:tag 'boolean}) @@ -51,7 +61,8 @@ (let [fname (-> *ns* meta :file) path (str (subs fname 0 (- (count fname) 4)) "css.json")] (-> (slurp (io/resource path)) - (json/read-str :key-fn keyword)))) + (json/read-str :key-fn keyword) + (or {})))) (def ^:private xform-css-case (comp @@ -59,8 +70,13 @@ (keep (fn [[k v]] (let [cls (cond (keyword? k) - (let [cn (name k)] - (or (get *css-data* (keyword cn)) cn)) + (let [knm (name k) + kns (namespace k)] + (case kns + "global" knm + "old-css" (if (nil? *css-data*) knm "") + (or (get *css-data* (keyword knm)) knm))) + (string? k) k)] (when cls @@ -75,7 +91,8 @@ (let [fname (-> *ns* meta :file) path (str (subs fname 0 (- (count fname) 4)) "css.json") data (-> (slurp (io/resource path)) - (json/read-str :key-fn keyword))] + (json/read-str :key-fn keyword) + (or {}))] (if (symbol? (first params)) `(if ~(with-meta (first params) {:tag 'boolean}) From e278d042ea1d6e0d1c5550b2fc4858d719d1f4f7 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 29 Aug 2023 13:48:53 +0200 Subject: [PATCH 12/16] :sparkles: Improve usability of assets tab on search Automatically uncollapse assets groups when a total searched results is less than a threshold of 60 (current default) --- .../ui/workspace/sidebar/assets/colors.cljs | 10 +++-- .../workspace/sidebar/assets/components.cljs | 13 +++++-- .../sidebar/assets/file_library.cljs | 39 ++++++++++++++----- .../ui/workspace/sidebar/assets/graphics.cljs | 7 +++- .../sidebar/assets/typographies.cljs | 7 +++- 5 files changed, 56 insertions(+), 20 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/colors.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/colors.cljs index a4b3cfc391..1107177531 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/colors.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/colors.cljs @@ -303,11 +303,12 @@ [:div.dragging])]))) (mf/defc colors-group - [{:keys [file-id prefix groups open-groups local? selected + [{:keys [file-id prefix groups open-groups force-open? local? selected multi-colors? multi-assets? on-asset-click on-assets-delete on-clear-selection on-group on-rename-group on-ungroup colors selected-full]}] - (let [group-open? (get open-groups prefix true) + (let [group-open? (or ^boolean force-open? + ^boolean (get open-groups prefix (if (= prefix "") true false))) new-css-system (mf/use-ctx ctx/new-css-system) dragging* (mf/use-state false) dragging? (deref dragging*) @@ -391,6 +392,7 @@ :key (dm/str "group-" path-item) :groups content :open-groups open-groups + :force-open? force-open? :local? local? :selected selected :multi-colors? multi-colors? @@ -454,6 +456,7 @@ :key (dm/str "group-" path-item) :groups content :open-groups open-groups + :force-open? force-open? :local? local? :selected selected :multi-colors? multi-colors? @@ -468,7 +471,7 @@ :selected-full selected-full}]))])]))) (mf/defc colors-section - [{:keys [file-id local? colors open? open-status-ref selected reverse-sort? + [{:keys [file-id local? colors open? force-open? open-status-ref selected reverse-sort? on-asset-click on-assets-delete on-clear-selection] :as props}] (let [selected (:colors selected) @@ -607,6 +610,7 @@ :prefix "" :groups groups :open-groups open-groups + :force-open? force-open? :local? local? :selected selected :multi-colors? multi-colors? diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs index 79b477fc08..9d54ea2e44 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs @@ -202,11 +202,12 @@ (mf/defc components-group {::mf/wrap-props false} - [{:keys [file-id prefix groups open-groups renaming listing-thumbs? selected on-asset-click + [{:keys [file-id prefix groups open-groups force-open? renaming listing-thumbs? selected on-asset-click on-drag-start do-rename cancel-rename on-rename-group on-group on-ungroup on-context-menu selected-full]}] - (let [group-open? (get open-groups prefix (if (= prefix "") true false)) + (let [group-open? (or ^boolean force-open? + ^boolean (get open-groups prefix (if (= prefix "") true false))) new-css-system (mf/use-ctx ctx/new-css-system) dragging* (mf/use-state false) dragging? (deref dragging*) @@ -295,6 +296,7 @@ :prefix (cph/merge-path-item prefix path-item) :groups content :open-groups open-groups + :force-open? force-open? :renaming renaming :listing-thumbs? listing-thumbs? :selected selected @@ -368,6 +370,7 @@ :prefix (cph/merge-path-item prefix path-item) :groups content :open-groups open-groups + :force-open? force-open? :renaming renaming :listing-thumbs? listing-thumbs? :selected selected @@ -382,8 +385,9 @@ (mf/defc components-section {::mf/wrap-props false} - [{:keys [file-id local? components listing-thumbs? open? reverse-sort? selected - on-asset-click on-assets-delete on-clear-selection open-status-ref]}] + [{:keys [file-id local? components listing-thumbs? open? force-open? + reverse-sort? selected on-asset-click on-assets-delete + on-clear-selection open-status-ref]}] (let [input-ref (mf/use-ref nil) @@ -607,6 +611,7 @@ :prefix "" :groups groups :open-groups open-groups + :force-open? force-open? :renaming (when ^boolean renaming? current-component-id) :listing-thumbs? listing-thumbs? :selected selected diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/file_library.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/file_library.cljs index 5b8c657297..9befc10c5a 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/file_library.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/file_library.cljs @@ -149,7 +149,6 @@ (or (pos? (count typographies)) (str/empty? filters-term))) - selected-lens (mf/with-memo [file-id] (-> (l/key file-id) (l/derived lens:selected))) @@ -160,6 +159,12 @@ (count (get selected :colors)) (count (get selected :typographies))) + has-term? (not ^boolean (str/empty? filters-term)) + force-open-components? (when ^boolean has-term? (> 60 (count components))) + force-open-colors? (when ^boolean has-term? (> 60 (count colors))) + force-open-graphics? (when ^boolean has-term? (> 60 (count media))) + force-open-typographies? (when ^boolean has-term? (> 60 (count typographies))) + extend-selected (fn [type asset-groups asset-id] (letfn [(flatten-groups [groups] @@ -248,7 +253,9 @@ :local? local? :components components :listing-thumbs? listing-thumbs? - :open? (get open-status :components false) + :open? (or ^boolean force-open-components? + ^boolean (get open-status :components false)) + :force-open? force-open-components? :open-status-ref open-status-ref :reverse-sort? reverse-sort? :selected selected @@ -263,7 +270,9 @@ :local? local? :objects media :listing-thumbs? listing-thumbs? - :open? (get open-status :graphics false) + :open? (or ^boolean force-open-graphics? + ^boolean (get open-status :graphics false)) + :force-open? force-open-graphics? :open-status-ref open-status-ref :reverse-sort? reverse-sort? :selected selected @@ -276,7 +285,9 @@ {:file-id file-id :local? local? :colors colors - :open? (get open-status :colors false) + :open? (or ^boolean force-open-colors? + ^boolean (get open-status :colors false)) + :force-open? force-open-colors? :open-status-ref open-status-ref :reverse-sort? reverse-sort? :selected selected @@ -290,7 +301,9 @@ :file-id (:id file) :local? local? :typographies typographies - :open? (get open-status :typographies false) + :open? (or ^boolean force-open-typographies? + ^boolean (get open-status :typographies false)) + :force-open? force-open-typographies? :open-status-ref open-status-ref :reverse-sort? reverse-sort? :selected selected @@ -327,7 +340,9 @@ :local? local? :components components :listing-thumbs? listing-thumbs? - :open? (get open-status :components false) + :open? (or ^boolean force-open-components? + ^boolean (get open-status :components false)) + :force-open? force-open-components? :open-status-ref open-status-ref :reverse-sort? reverse-sort? :selected selected @@ -342,7 +357,9 @@ :local? local? :objects media :listing-thumbs? listing-thumbs? - :open? (get open-status :graphics false) + :open? (or ^boolean force-open-graphics? + ^boolean (get open-status :graphics false)) + :force-open? force-open-graphics? :open-status-ref open-status-ref :reverse-sort? reverse-sort? :selected selected @@ -355,7 +372,9 @@ {:file-id file-id :local? local? :colors colors - :open? (get open-status :colors false) + :open? (or ^boolean force-open-colors? + ^boolean (get open-status :colors false)) + :force-open? force-open-colors? :open-status-ref open-status-ref :reverse-sort? reverse-sort? :selected selected @@ -369,7 +388,9 @@ :file-id (:id file) :local? local? :typographies typographies - :open? (get open-status :typographies false) + :open? (or ^boolean force-open-typographies? + ^boolean (get open-status :typographies false)) + :force-open? force-open-typographies? :open-status-ref open-status-ref :reverse-sort? reverse-sort? :selected selected diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/graphics.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/graphics.cljs index 37f502b8fd..73fd831dc4 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/graphics.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/graphics.cljs @@ -161,7 +161,7 @@ [:div.dragging])])])]))) (mf/defc graphics-group - [{:keys [file-id prefix groups open-groups renaming listing-thumbs? selected-objects on-asset-click + [{:keys [file-id prefix groups open-groups force-open? renaming listing-thumbs? selected-objects on-asset-click on-drag-start do-rename cancel-rename on-rename-group on-ungroup on-context-menu selected-full]}] (let [group-open? (get open-groups prefix true) @@ -249,6 +249,7 @@ :prefix (cph/merge-path-item prefix path-item) :groups content :open-groups open-groups + :force-open? force-open? :renaming renaming :listing-thumbs? listing-thumbs? :selected-objects selected-objects @@ -315,6 +316,7 @@ :prefix (cph/merge-path-item prefix path-item) :groups content :open-groups open-groups + :force-open? force-open? :renaming renaming :listing-thumbs? listing-thumbs? :selected-objects selected-objects @@ -330,7 +332,7 @@ (mf/defc graphics-section {::mf/wrap-props false} - [{:keys [file-id project-id local? objects listing-thumbs? open? open-status-ref selected reverse-sort? + [{:keys [file-id project-id local? objects listing-thumbs? open? force-open? open-status-ref selected reverse-sort? on-asset-click on-assets-delete on-clear-selection]}] (let [input-ref (mf/use-ref nil) state (mf/use-state {:renaming nil :object-id nil}) @@ -518,6 +520,7 @@ :prefix "" :groups groups :open-groups open-groups + :force-open? force-open? :renaming (:renaming @state) :listing-thumbs? listing-thumbs? :selected selected diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/typographies.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/typographies.cljs index 46d90841e4..fc1e1f94fe 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/typographies.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/typographies.cljs @@ -149,7 +149,7 @@ (mf/defc typographies-group {::mf/wrap-props false} - [{:keys [file-id prefix groups open-groups file local? selected local-data + [{:keys [file-id prefix groups open-groups force-open? file local? selected local-data editing-id renaming-id on-asset-click handle-change apply-typography on-rename-group on-ungroup on-context-menu selected-full]}] (let [group-open? (get open-groups prefix true) @@ -236,6 +236,7 @@ :key (dm/str "group-" path-item) :groups content :open-groups open-groups + :force-open? force-open? :file file :local? local? :selected selected @@ -297,6 +298,7 @@ :key (dm/str "group-" path-item) :groups content :open-groups open-groups + :force-open? force-open? :file file :local? local? :selected selected @@ -312,7 +314,7 @@ (mf/defc typographies-section {::mf/wrap-props false} - [{:keys [file file-id local? typographies open? open-status-ref selected reverse-sort? + [{:keys [file file-id local? typographies open? force-open? open-status-ref selected reverse-sort? on-asset-click on-assets-delete on-clear-selection]}] (let [state (mf/use-state {:detail-open? false :id nil}) local-data (mf/deref lens:typography-section-state) @@ -506,6 +508,7 @@ :prefix "" :groups groups :open-groups open-groups + :force-open? force-open? :state state :file file :local? local? From 8ff18a2a9e4aafeec9410386b32ae46755efd927 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 29 Aug 2023 13:53:25 +0200 Subject: [PATCH 13/16] :sparkles: Add asset item full path to the search filtering --- .../src/app/main/ui/workspace/sidebar/assets/common.cljs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs index c75c199c9b..f83759b137 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs @@ -39,11 +39,10 @@ (->> coll (filter (fn [item] (or (matches-search (:name item "!$!") term) + (matches-search (:path item "!$!") term) (matches-search (:value item "!$!") term)))) - ; Sort by folder order, but - ; putting all "root" items - ; always first, independently - ; of sort order. + ;; Sort by folder order, but putting all "root" items always + ;; first, independently of sort order. (sort-by #(str/lower (cph/merge-path-item (if (empty? (:path %)) (if reverse? "z" "a") (:path %)) From 937d3b495426f0ab0aa29bae5c5af5ecd321965a Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 29 Aug 2023 14:01:08 +0200 Subject: [PATCH 14/16] :zap: Don't perform assets filtering if term is empty --- .../ui/workspace/sidebar/assets/common.cljs | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs index f83759b137..cf6448b53a 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/common.cljs @@ -34,20 +34,23 @@ (defn apply-filters [coll {:keys [ordering term] :as filters}] - (let [reverse? (= :desc ordering) - comp-fn (if ^boolean reverse? > <)] - (->> coll - (filter (fn [item] - (or (matches-search (:name item "!$!") term) - (matches-search (:path item "!$!") term) - (matches-search (:value item "!$!") term)))) - ;; Sort by folder order, but putting all "root" items always - ;; first, independently of sort order. - (sort-by #(str/lower (cph/merge-path-item (if (empty? (:path %)) - (if reverse? "z" "a") - (:path %)) - (:name %))) - comp-fn)))) + (let [reverse? (= :desc ordering)] + (cond->> coll + (not ^boolean (str/empty? term)) + (filter (fn [item] + (or (matches-search (:name item "!$!") term) + (matches-search (:path item "!$!") term) + (matches-search (:value item "!$!") term)))) + + ;; Sort by folder order, but putting all "root" items always + ;; first, independently of sort order. + :always + (sort-by (fn [{:keys [path name] :as item}] + (let [path (if (str/empty? path) + (if reverse? "z" "a") + path)] + (str/lower (cph/merge-path-item path name)))) + (if ^boolean reverse? > <))))) (defn add-group [asset group-name] From 1e2603f1f59c6bec15d7f7cbba51d93b8f51d515 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 29 Aug 2023 17:16:40 +0200 Subject: [PATCH 15/16] :sparkles: Add minor improvements to use-visible hook --- frontend/src/app/main/ui/hooks.cljs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/frontend/src/app/main/ui/hooks.cljs b/frontend/src/app/main/ui/hooks.cljs index d311d71e1f..c0748fe450 100644 --- a/frontend/src/app/main/ui/hooks.cljs +++ b/frontend/src/app/main/ui/hooks.cljs @@ -302,11 +302,14 @@ (fn [entries _] (run! (partial rx/push! intersection-subject) (seq entries))) #js {:rootMargin "0px" - :threshold 1.0}))) + :threshold #js [0 1.0]}))) (defn use-visible [ref & {:keys [once?]}] - (let [[state update-state!] (mf/useState false)] + (let [state (mf/useState false) + update-state! (aget state 1) + state (aget state 0)] + (mf/with-effect [once?] (let [node (mf/ref-val ref) stream (->> intersection-subject @@ -314,15 +317,16 @@ (let [target (unchecked-get entry "target")] (identical? target node)))) (rx/map (fn [entry] - (let [ratio (unchecked-get entry "intersectionRatio") - intersecting? (unchecked-get entry "isIntersecting")] - (or intersecting? (> ratio 0.5))))) + (let [ratio (unchecked-get entry "intersectionRatio") + intersecting? (unchecked-get entry "isIntersecting") + intersecting? (or ^boolean intersecting? + ^boolean (> ratio 0.5))] + (when (and (true? intersecting?) (true? once?)) + (.unobserve ^js @intersection-observer node)) + + intersecting?))) + (rx/dedupe)) - stream (if once? - (->> stream - (rx/filter identity) - (rx/take 1)) - stream) subs (rx/subscribe stream update-state!)] (.observe ^js @intersection-observer node) (fn [] From 8a4fcc1d10a91e4e3844e2212fdfa86ffba63784 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 29 Aug 2023 17:17:26 +0200 Subject: [PATCH 16/16] :zap: Delimit rendering of components when they are visible on workspace assets tab --- .../app/main/ui/workspace/sidebar/assets/components.cljs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs index 9d54ea2e44..e248ac130c 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/components.cljs @@ -25,6 +25,7 @@ [app.main.ui.components.file-uploader :refer [file-uploader]] [app.main.ui.components.radio-buttons :refer [radio-button radio-buttons]] [app.main.ui.context :as ctx] + [app.main.ui.hooks :as h] [app.main.ui.icons :as i] [app.main.ui.workspace.sidebar.assets.common :as cmm] [app.main.ui.workspace.sidebar.assets.groups :as grp] @@ -65,6 +66,8 @@ new-css-system (mf/use-ctx ctx/new-css-system) component-id (:id component) + visible? (h/use-visible item-ref :once? true) + ;; NOTE: we don't use reactive deref for it because we don't ;; really need rerender on any change on the file change. If ;; the component changes, it will trigger rerender anyway. @@ -180,8 +183,9 @@ (when (and (some? root-shape) (some? container)) [:* - [:& component-svg {:root-shape root-shape - :objects (:objects container)}] + (when visible? + [:& component-svg {:root-shape root-shape + :objects (:objects container)}]) (let [renaming? (= renaming (:id component))] [:* [:& editable-label