Merge pull request #3570 from penpot/niwinz-develop-experiments-1

 Add performance enhancements (part 2)
This commit is contained in:
Alejandro 2023-09-01 12:58:54 +02:00 committed by GitHub
commit 6080b778d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 295 additions and 175 deletions

View File

@ -29,9 +29,16 @@
(defn is-direct-child-of-root? (defn is-direct-child-of-root?
([objects id] ([objects id]
(is-direct-child-of-root? (get objects id))) (is-direct-child-of-root? (get objects id)))
([{:keys [frame-id type]}] ([shape]
(and (= type :frame) (and (some? shape) (= (dm/get-prop shape :frame-id) uuid/zero))))
(= frame-id uuid/zero))))
(defn root-frame?
([objects id]
(root-frame? (get objects id)))
([shape]
(and (some? shape)
(= (dm/get-prop shape :type) :frame)
(= (dm/get-prop shape :frame-id) uuid/zero))))
(defn frame-shape? (defn frame-shape?
([objects id] ([objects id]
@ -228,7 +235,7 @@
(or (root? frame) (nil? frame)) (or (root? frame) (nil? frame))
nil nil
(is-direct-child-of-root? frame) (root-frame? frame)
frame frame
:else :else
@ -613,7 +620,7 @@
(->> (get-parent-ids objects shape-id) (->> (get-parent-ids objects shape-id)
(cons shape-id) (cons shape-id)
(map (d/getf objects)) (map (d/getf objects))
(d/seek is-direct-child-of-root?) (d/seek root-frame?)
:id)) :id))
(defn comparator-layout-z-index (defn comparator-layout-z-index

View File

@ -9,8 +9,7 @@
(:refer-clojure :exclude [defrecord assoc! clone]) (:refer-clojure :exclude [defrecord assoc! clone])
#?(:cljs (:require-macros [app.common.record])) #?(:cljs (:require-macros [app.common.record]))
#?(:clj #?(:clj
(:import java.util.Map (:import java.util.Map$Entry)))
java.util.Map$Entry)))
#_:clj-kondo/ignore #_:clj-kondo/ignore
(defmacro caching-hash (defmacro caching-hash
@ -37,18 +36,24 @@
:else `(. ~this-sym ~(property-symbol field)))) :else `(. ~this-sym ~(property-symbol field))))
fields))) fields)))
(defprotocol ICustomRecordEquiv
(-equiv-with-exceptions [_ other exceptions]))
#?(:clj #?(:clj
(defn emit-impl-js (defn emit-impl-js
[tagname base-fields] [tagname base-fields]
(let [fields (conj base-fields '$meta '$extmap (with-meta '$hash {:mutable true})) (let [fields (conj base-fields '$meta '$extmap (with-meta '$hash {:mutable true}))
key-sym (gensym "key-") key-sym (gensym "key-")
val-sym (gensym "val-") val-sym (gensym "val-")
othr-sym (with-meta 'other {:tag tagname})
this-sym (with-meta 'this {:tag tagname})] this-sym (with-meta 'this {:tag tagname})]
['cljs.core/ICloneable ['cljs.core/IRecord
'cljs.core/ICloneable
`(~'-clone [~this-sym] `(~'-clone [~this-sym]
(new ~tagname ~@(generate-field-access this-sym val-sym fields))) (new ~tagname ~@(generate-field-access this-sym val-sym fields)))
'IHash 'cljs.core/IHash
`(~'-hash [~this-sym] `(~'-hash [~this-sym]
(caching-hash ~this-sym (caching-hash ~this-sym
(fn [coll#] (fn [coll#]
@ -58,16 +63,41 @@
(. ~this-sym ~'-$hash))) (. ~this-sym ~'-$hash)))
'cljs.core/IEquiv 'cljs.core/IEquiv
`(~'-equiv [~this-sym ~val-sym] `(~'-equiv [~this-sym ~othr-sym]
(and (some? ~val-sym) (or (identical? ~this-sym ~othr-sym)
(identical? (.-constructor ~this-sym) (and (some? ~othr-sym)
(.-constructor ~val-sym)) (identical? (.-constructor ~this-sym)
~@(map (fn [field] (.-constructor ~othr-sym))
`(= (.. ~this-sym ~(property-symbol field)) ~@(map (fn [field]
(.. ~(with-meta val-sym {:tag tagname}) ~(property-symbol field)))) `(= (.. ~this-sym ~(property-symbol field))
base-fields) (.. ~(with-meta othr-sym {:tag tagname}) ~(property-symbol field))))
(= (. ~this-sym ~'-$extmap) base-fields)
(. ~(with-meta val-sym {:tag tagname}) ~'-$extmap))))
(= (. ~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 'cljs.core/IMeta
`(~'-meta [~this-sym] (. ~this-sym ~'-$meta)) `(~'-meta [~this-sym] (. ~this-sym ~'-$meta))
@ -175,16 +205,17 @@
val-sym 'val val-sym 'val
this-sym (with-meta 'this {:tag tagname})] this-sym (with-meta 'this {:tag tagname})]
['clojure.lang.MapEquivalence ['clojure.lang.IRecord
'clojure.lang.IPersistentMap 'clojure.lang.IPersistentMap
`(~'equiv [~this-sym ~val-sym]
`(~'equiv [~this-sym ~'other] (and (some? ~val-sym)
(and (instance? java.util.Map ~'other) (= (.count ~this-sym) (.size ^Map ~'other)) (instance? ~tagname ~val-sym)
(every? (fn [^clojure.lang.MapEntry e#] ~@(map (fn [field]
(let [k# (.key e#)] `(= (.. ~this-sym ~(property-symbol field))
(and (.containsKey ^Map ~'other k#) (.. ~(with-meta val-sym {:tag tagname}) ~(property-symbol field))))
(= (.val e#) (.get ^Map ~'other k#))))) base-fields)
(.seq ~this-sym)))) (= (. ~this-sym ~'-$extmap)
(. ~(with-meta val-sym {:tag tagname}) ~'-$extmap))))
`(~'entryAt [~this-sym ~key-sym] `(~'entryAt [~this-sym ~key-sym]
(let [v# (.valAt ~this-sym ~key-sym ::not-found)] (let [v# (.valAt ~this-sym ~key-sym ::not-found)]

View File

@ -474,7 +474,7 @@
ids (if (boolean? blocked) ids (if (boolean? blocked)
(into ids (->> ids (mapcat #(cph/get-children-ids objects %)))) (into ids (->> ids (mapcat #(cph/get-children-ids objects %))))
ids)] ids)]
(rx/of (dch/update-shapes ids update-fn)))))) (rx/of (dch/update-shapes ids update-fn {:attrs #{:blocked :hidden}}))))))
(defn toggle-visibility-selected (defn toggle-visibility-selected
[] []

View File

@ -15,9 +15,18 @@
(def ^:dynamic *css-data* nil) (def ^:dynamic *css-data* nil)
(def ^:private xform-css (def ^:private xform-css
(map (fn [k] (keep (fn [k]
(let [cn (name k)] (cond
(or (get *css-data* (keyword cn)) cn))))) (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* (defmacro css*
"Just coerces all params to strings and concats them with "Just coerces all params to strings and concats them with
@ -35,7 +44,8 @@
(let [fname (-> *ns* meta :file) (let [fname (-> *ns* meta :file)
path (str (subs fname 0 (- (count fname) 4)) "css.json") path (str (subs fname 0 (- (count fname) 4)) "css.json")
data (-> (slurp (io/resource path)) data (-> (slurp (io/resource path))
(json/read-str :key-fn keyword))] (json/read-str :key-fn keyword)
(or {}))]
(if (symbol? (first selectors)) (if (symbol? (first selectors))
`(if ~(with-meta (first selectors) {:tag 'boolean}) `(if ~(with-meta (first selectors) {:tag 'boolean})
@ -51,7 +61,8 @@
(let [fname (-> *ns* meta :file) (let [fname (-> *ns* meta :file)
path (str (subs fname 0 (- (count fname) 4)) "css.json")] path (str (subs fname 0 (- (count fname) 4)) "css.json")]
(-> (slurp (io/resource path)) (-> (slurp (io/resource path))
(json/read-str :key-fn keyword)))) (json/read-str :key-fn keyword)
(or {}))))
(def ^:private xform-css-case (def ^:private xform-css-case
(comp (comp
@ -59,8 +70,13 @@
(keep (fn [[k v]] (keep (fn [[k v]]
(let [cls (cond (let [cls (cond
(keyword? k) (keyword? k)
(let [cn (name k)] (let [knm (name k)
(or (get *css-data* (keyword cn)) cn)) kns (namespace k)]
(case kns
"global" knm
"old-css" (if (nil? *css-data*) knm "")
(or (get *css-data* (keyword knm)) knm)))
(string? k) (string? k)
k)] k)]
(when cls (when cls
@ -75,7 +91,8 @@
(let [fname (-> *ns* meta :file) (let [fname (-> *ns* meta :file)
path (str (subs fname 0 (- (count fname) 4)) "css.json") path (str (subs fname 0 (- (count fname) 4)) "css.json")
data (-> (slurp (io/resource path)) data (-> (slurp (io/resource path))
(json/read-str :key-fn keyword))] (json/read-str :key-fn keyword)
(or {}))]
(if (symbol? (first params)) (if (symbol? (first params))
`(if ~(with-meta (first params) {:tag 'boolean}) `(if ~(with-meta (first params) {:tag 'boolean})

View File

@ -302,11 +302,14 @@
(fn [entries _] (fn [entries _]
(run! (partial rx/push! intersection-subject) (seq entries))) (run! (partial rx/push! intersection-subject) (seq entries)))
#js {:rootMargin "0px" #js {:rootMargin "0px"
:threshold 1.0}))) :threshold #js [0 1.0]})))
(defn use-visible (defn use-visible
[ref & {:keys [once?]}] [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?] (mf/with-effect [once?]
(let [node (mf/ref-val ref) (let [node (mf/ref-val ref)
stream (->> intersection-subject stream (->> intersection-subject
@ -314,15 +317,16 @@
(let [target (unchecked-get entry "target")] (let [target (unchecked-get entry "target")]
(identical? target node)))) (identical? target node))))
(rx/map (fn [entry] (rx/map (fn [entry]
(let [ratio (unchecked-get entry "intersectionRatio") (let [ratio (unchecked-get entry "intersectionRatio")
intersecting? (unchecked-get entry "isIntersecting")] intersecting? (unchecked-get entry "isIntersecting")
(or intersecting? (> ratio 0.5))))) intersecting? (or ^boolean intersecting?
^boolean (> ratio 0.5))]
(when (and (true? intersecting?) (true? once?))
(.unobserve ^js @intersection-observer node))
intersecting?)))
(rx/dedupe)) (rx/dedupe))
stream (if once?
(->> stream
(rx/filter identity)
(rx/take 1))
stream)
subs (rx/subscribe stream update-state!)] subs (rx/subscribe stream update-state!)]
(.observe ^js @intersection-observer node) (.observe ^js @intersection-observer node)
(fn [] (fn []

View File

@ -34,7 +34,7 @@
[shape hover?] [shape hover?]
(fn [event] (fn [event]
(when-not (or (cph/group-shape? shape) (when-not (or (cph/group-shape? shape)
(cph/is-direct-child-of-root? shape)) (cph/root-frame? shape))
(dom/prevent-default event) (dom/prevent-default event)
(dom/stop-propagation event) (dom/stop-propagation event)
(st/emit! (dv/hover-shape (:id shape) hover?))))) (st/emit! (dv/hover-shape (:id shape) hover?)))))
@ -42,7 +42,7 @@
(defn select-shape [shape] (defn select-shape [shape]
(fn [event] (fn [event]
(when-not (or (cph/group-shape? shape) (when-not (or (cph/group-shape? shape)
(cph/is-direct-child-of-root? shape)) (cph/root-frame? shape))
(dom/stop-propagation event) (dom/stop-propagation event)
(dom/prevent-default event) (dom/prevent-default event)
(cond (cond

View File

@ -53,9 +53,8 @@
;; We group the objects together per frame-id so if an object of a different ;; We group the objects together per frame-id so if an object of a different
;; frame changes won't affect the rendering frame ;; frame changes won't affect the rendering frame
frame-objects frame-objects
(mf/use-memo (mf/with-memo [objects]
(mf/deps objects) (cph/objects-by-frame objects))]
#(cph/objects-by-frame objects))]
[:g {:id (dm/str "shape-" uuid/zero)} [:g {:id (dm/str "shape-" uuid/zero)}
[:& (mf/provider ctx/active-frames) {:value active-frames} [:& (mf/provider ctx/active-frames) {:value active-frames}
@ -68,46 +67,47 @@
[:g.frame-children [:g.frame-children
(for [shape shapes] (for [shape shapes]
[:g.ws-shape-wrapper {:key (:id shape)} [:g.ws-shape-wrapper {:key (dm/str (dm/get-prop shape :id))}
(cond (if ^boolean (cph/frame-shape? shape)
(not (cph/frame-shape? shape))
[:& shape-wrapper
{:shape shape}]
(cph/is-direct-child-of-root? shape)
[:& root-frame-wrapper [:& root-frame-wrapper
{:shape shape {:shape shape
:objects (get frame-objects (:id shape)) :objects (get frame-objects (dm/get-prop shape :id))
:thumbnail? (not (contains? active-frames (:id shape)))}] :thumbnail? (not (contains? active-frames (dm/get-prop shape :id)))}]
[:& shape-wrapper {:shape shape}])])]]]))
:else (defn- check-shape-wrapper-props
[:& nested-frame-wrapper [np op]
{:shape shape (frame/check-shape (unchecked-get np "shape")
:objects (get frame-objects (:id shape))}])])]]])) (unchecked-get op "shape")))
(mf/defc shape-wrapper (mf/defc shape-wrapper
{::mf/wrap [#(mf/memo' % (mf/check-props ["shape"]))] {::mf/wrap [#(mf/memo' % check-shape-wrapper-props)]
::mf/wrap-props false} ::mf/wrap-props false}
[props] [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 active-frames
(when (cph/is-direct-child-of-root? shape) (mf/use-ctx ctx/active-frames)) (when (cph/root-frame? shape)
(mf/use-ctx ctx/active-frames))
thumbnail? thumbnail?
(and (some? active-frames) (and (some? active-frames)
(not (contains? active-frames (:id shape)))) (not (contains? active-frames shape-id)))
opts #js {:shape shape :thumbnail? thumbnail?} opts #js {:shape shape :thumbnail? thumbnail?}
[wrapper wrapper-props] [wrapper wrapper-props]
(if (= :svg-raw (:type shape)) (if (= :svg-raw shape-type)
[mf/Fragment nil] [mf/Fragment nil]
["g" #js {:className "workspace-shape-wrapper"}])] ["g" #js {:className "workspace-shape-wrapper"}])]
(when (and (some? shape) (not (:hidden shape))) (when (and (some? shape)
(not ^boolean (:hidden shape)))
[:> wrapper wrapper-props [:> wrapper wrapper-props
(case (:type shape) (case shape-type
:path [:> path/path-wrapper opts] :path [:> path/path-wrapper opts]
:text [:> text/text-wrapper opts] :text [:> text/text-wrapper opts]
:group [:> group-wrapper opts] :group [:> group-wrapper opts]
@ -125,4 +125,3 @@
(def bool-wrapper (bool/bool-wrapper-factory shape-wrapper)) (def bool-wrapper (bool/bool-wrapper-factory shape-wrapper))
(def root-frame-wrapper (frame/root-frame-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)) (def nested-frame-wrapper (frame/nested-frame-wrapper-factory shape-wrapper))

View File

@ -9,6 +9,7 @@
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.pages.helpers :as cph] [app.common.pages.helpers :as cph]
[app.common.record :as cr]
[app.main.data.workspace.state-helpers :as wsh] [app.main.data.workspace.state-helpers :as wsh]
[app.main.data.workspace.thumbnails :as dwt] [app.main.data.workspace.thumbnails :as dwt]
[app.main.refs :as refs] [app.main.refs :as refs]
@ -25,17 +26,36 @@
[beicon.core :as rx] [beicon.core :as rx]
[rumext.v2 :as mf])) [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 (defn frame-shape-factory
[shape-wrapper] [shape-wrapper]
(let [frame-shape (frame/frame-shape shape-wrapper)] (let [frame-shape (frame/frame-shape shape-wrapper)]
(mf/fnc frame-shape-inner (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/wrap-props false
::mf/forward-ref true} ::mf/forward-ref true}
[props ref] [props ref]
(let [shape (unchecked-get props "shape") (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)] childs (mf/deref childs-ref)]
[:& (mf/provider embed/context) {:value true} [:& (mf/provider embed/context) {:value true}
@ -46,8 +66,8 @@
[new-props old-props] [new-props old-props]
(and (= (unchecked-get new-props "thumbnail?") (and (= (unchecked-get new-props "thumbnail?")
(unchecked-get old-props "thumbnail?")) (unchecked-get old-props "thumbnail?"))
(= (unchecked-get new-props "shape") (check-shape (unchecked-get new-props "shape")
(unchecked-get old-props "shape")))) (unchecked-get old-props "shape"))))
(defn nested-frame-wrapper-factory (defn nested-frame-wrapper-factory
[shape-wrapper] [shape-wrapper]

View File

@ -125,34 +125,32 @@
(defn text-properties-equal? (defn text-properties-equal?
[shape other] [shape other]
;; FIXME: use dm/get-prop
(or (identical? shape other) (or (identical? shape other)
(and (and (= (:content shape) (:content other))
;; Check if both shapes are equivalent removing their geometry data ;; Check if the position and size is close. If any of these changes the shape has changed
(= (dissoc shape :migrate :points :selrect :height :width :x :y :position-data :modifiers) ;; and if not there is no geometry relevant change
(dissoc other :migrate :points :selrect :height :width :x :y :position-data :modifiers)) (mth/close? (:x shape) (:x other))
(mth/close? (:y shape) (:y other))
;; Check if the position and size is close. If any of these changes the shape has changed (mth/close? (:width shape) (:width other))
;; and if not there is no geometry relevant change (mth/close? (:height shape) (:height other)))))
(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/defc text-changes-renderer
{::mf/wrap-props false} {::mf/wrap-props false}
[props] [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) prev-text-shapes (hooks/use-previous text-shapes)
;; We store in the state the texts still pending to be calculated so we can ;; We store in the state the texts still pending to be calculated so we can
;; get its position ;; get its position
pending-update (mf/use-state {}) pending-update* (mf/use-state {})
pending-update (deref pending-update*)
text-change? text-change?
(fn [id] (fn [id]
(let [new-shape (get text-shapes id) (let [new-shape (get text-shapes id)
old-shape (get prev-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 (or (and (not remote?) ;; changes caused by a remote peer are not re-calculated
(not (text-properties-equal? old-shape new-shape))) (not (text-properties-equal? old-shape new-shape)))
@ -160,9 +158,8 @@
(nil? (:position-data new-shape))))) (nil? (:position-data new-shape)))))
changed-texts changed-texts
(mf/use-memo (mf/with-memo [text-shapes pending-update]
(mf/deps text-shapes @pending-update) (let [pending-shapes (into #{} (vals pending-update))]
#(let [pending-shapes (into #{} (vals @pending-update))]
(->> (keys text-shapes) (->> (keys text-shapes)
(filter (fn [id] (filter (fn [id]
(or (contains? pending-shapes id) (or (contains? pending-shapes id)
@ -170,18 +167,18 @@
(map (d/getf text-shapes))))) (map (d/getf text-shapes)))))
handle-update-shape handle-update-shape
(mf/use-callback (mf/use-fn
(fn [shape node] (fn [shape node]
;; Unique to indentify the pending state ;; Unique to indentify the pending state
(let [uid (js/Symbol)] (let [uid (js/Symbol)]
(swap! pending-update assoc uid (:id shape)) (swap! pending-update* assoc uid (:id shape))
(p/then (p/then
(update-text-shape shape node) (update-text-shape shape node)
#(swap! pending-update dissoc uid)))))] #(swap! pending-update* dissoc uid)))))]
[:.text-changes-renderer [:.text-changes-renderer
(for [{:keys [id] :as shape} changed-texts] (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 :shape shape
:on-update handle-update-shape}])])) :on-update handle-update-shape}])]))
@ -213,7 +210,7 @@
[:.text-changes-renderer [:.text-changes-renderer
(for [{:keys [id] :as shape} changed-texts] (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 :shape shape
:on-update handle-update-shape}])])) :on-update handle-update-shape}])]))

View File

@ -5,7 +5,7 @@
;; Copyright (c) KALEIDOS INC ;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.assets (ns app.main.ui.workspace.sidebar.assets
(:require-macros [app.main.style :refer [css]]) (:require-macros [app.main.style :as stl])
(:require (:require
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.main.data.modal :as modal] [app.main.data.modal :as modal]
@ -80,7 +80,6 @@
:open-menu false}) :open-menu false})
filters (deref filters*) filters (deref filters*)
term (:term filters) term (:term filters)
ordering (:ordering filters)
list-style (:list-style filters) list-style (:list-style filters)
menu-open? (:open-menu filters) menu-open? (:open-menu filters)
section (:section filters) section (:section filters)
@ -175,22 +174,22 @@
:data-test "typographies"}]] :data-test "typographies"}]]
(if ^boolean new-css-system (if ^boolean new-css-system
[:div {:class (css :assets-bar)} [:div {:class (stl/css :assets-bar)}
[:div {:class (css :assets-header)} [:div {:class (stl/css :assets-header)}
(when-not ^boolean read-only? (when-not ^boolean read-only?
[:button {:class (css :libraries-button) [:button {:class (stl/css :libraries-button)
:on-click #(modal/show! :libraries-dialog {})} :on-click show-libraries-dialog}
[:span {:class (css :libraries-icon)} [:span {:class (stl/css :libraries-icon)}
i/library-refactor] i/library-refactor]
(tr "workspace.assets.libraries")]) (tr "workspace.assets.libraries")])
[:div {:class (css :search-wrapper)} [:div {:class (stl/css :search-wrapper)}
[:& search-bar {:on-change on-search-term-change [:& search-bar {:on-change on-search-term-change
:value term :value term
:placeholder (tr "workspace.assets.search")} :placeholder (tr "workspace.assets.search")}
[:button [:button
{:on-click on-open-menu {:on-click on-open-menu
:class (dom/classnames (css :section-button) true)} :class (stl/css :section-button)}
i/filter-refactor]] i/filter-refactor]]
[:& context-menu-a11y [:& context-menu-a11y
{:on-close on-menu-close {:on-close on-menu-close
@ -203,7 +202,7 @@
:left 64 :left 64
:options options :options options
:workspace? true}] :workspace? true}]
[:button {:class (css :sort-button) [:button {:class (stl/css :sort-button)
:on-click toggle-ordering} :on-click toggle-ordering}
(if reverse-sort? (if reverse-sort?
i/asc-sort-refactor i/asc-sort-refactor
@ -212,7 +211,7 @@
[:& (mf/provider cmm/assets-filters) {:value filters} [:& (mf/provider cmm/assets-filters) {:value filters}
[:& (mf/provider cmm/assets-toggle-ordering) {:value toggle-ordering} [:& (mf/provider cmm/assets-toggle-ordering) {:value toggle-ordering}
[:& (mf/provider cmm/assets-toggle-list-style) {:value toggle-list-style} [:& (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-local-library {:filters filters}]
[:& assets-libraries {:filters filters}]]]]]] [:& assets-libraries {:filters filters}]]]]]]

View File

@ -303,11 +303,12 @@
[:div.dragging])]))) [:div.dragging])])))
(mf/defc colors-group (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 multi-colors? multi-assets? on-asset-click on-assets-delete
on-clear-selection on-group on-rename-group on-ungroup colors on-clear-selection on-group on-rename-group on-ungroup colors
selected-full]}] 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) new-css-system (mf/use-ctx ctx/new-css-system)
dragging* (mf/use-state false) dragging* (mf/use-state false)
dragging? (deref dragging*) dragging? (deref dragging*)
@ -391,6 +392,7 @@
:key (dm/str "group-" path-item) :key (dm/str "group-" path-item)
:groups content :groups content
:open-groups open-groups :open-groups open-groups
:force-open? force-open?
:local? local? :local? local?
:selected selected :selected selected
:multi-colors? multi-colors? :multi-colors? multi-colors?
@ -454,6 +456,7 @@
:key (dm/str "group-" path-item) :key (dm/str "group-" path-item)
:groups content :groups content
:open-groups open-groups :open-groups open-groups
:force-open? force-open?
:local? local? :local? local?
:selected selected :selected selected
:multi-colors? multi-colors? :multi-colors? multi-colors?
@ -468,7 +471,7 @@
:selected-full selected-full}]))])]))) :selected-full selected-full}]))])])))
(mf/defc colors-section (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}] on-asset-click on-assets-delete on-clear-selection] :as props}]
(let [selected (:colors selected) (let [selected (:colors selected)
@ -607,6 +610,7 @@
:prefix "" :prefix ""
:groups groups :groups groups
:open-groups open-groups :open-groups open-groups
:force-open? force-open?
:local? local? :local? local?
:selected selected :selected selected
:multi-colors? multi-colors? :multi-colors? multi-colors?

View File

@ -34,21 +34,23 @@
(defn apply-filters (defn apply-filters
[coll {:keys [ordering term] :as filters}] [coll {:keys [ordering term] :as filters}]
(let [reverse? (= :desc ordering) (let [reverse? (= :desc ordering)]
comp-fn (if ^boolean reverse? > <)] (cond->> coll
(->> coll (not ^boolean (str/empty? term))
(filter (fn [item] (filter (fn [item]
(or (matches-search (:name item "!$!") term) (or (matches-search (:name item "!$!") term)
(matches-search (:value item "!$!") term)))) (matches-search (:path item "!$!") term)
; Sort by folder order, but (matches-search (:value item "!$!") term))))
; putting all "root" items
; always first, independently ;; Sort by folder order, but putting all "root" items always
; of sort order. ;; first, independently of sort order.
(sort-by #(str/lower (cph/merge-path-item (if (empty? (:path %)) :always
(if reverse? "z" "a") (sort-by (fn [{:keys [path name] :as item}]
(:path %)) (let [path (if (str/empty? path)
(:name %))) (if reverse? "z" "a")
comp-fn)))) path)]
(str/lower (cph/merge-path-item path name))))
(if ^boolean reverse? > <)))))
(defn add-group (defn add-group
[asset group-name] [asset group-name]

View File

@ -25,6 +25,7 @@
[app.main.ui.components.file-uploader :refer [file-uploader]] [app.main.ui.components.file-uploader :refer [file-uploader]]
[app.main.ui.components.radio-buttons :refer [radio-button radio-buttons]] [app.main.ui.components.radio-buttons :refer [radio-button radio-buttons]]
[app.main.ui.context :as ctx] [app.main.ui.context :as ctx]
[app.main.ui.hooks :as h]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.assets.common :as cmm] [app.main.ui.workspace.sidebar.assets.common :as cmm]
[app.main.ui.workspace.sidebar.assets.groups :as grp] [app.main.ui.workspace.sidebar.assets.groups :as grp]
@ -65,6 +66,8 @@
new-css-system (mf/use-ctx ctx/new-css-system) new-css-system (mf/use-ctx ctx/new-css-system)
component-id (:id component) 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 ;; NOTE: we don't use reactive deref for it because we don't
;; really need rerender on any change on the file change. If ;; really need rerender on any change on the file change. If
;; the component changes, it will trigger rerender anyway. ;; the component changes, it will trigger rerender anyway.
@ -180,8 +183,9 @@
(when (and (some? root-shape) (when (and (some? root-shape)
(some? container)) (some? container))
[:* [:*
[:& component-svg {:root-shape root-shape (when visible?
:objects (:objects container)}] [:& component-svg {:root-shape root-shape
:objects (:objects container)}])
(let [renaming? (= renaming (:id component))] (let [renaming? (= renaming (:id component))]
[:* [:*
[:& editable-label [:& editable-label
@ -202,11 +206,12 @@
(mf/defc components-group (mf/defc components-group
{::mf/wrap-props false} {::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 on-drag-start do-rename cancel-rename on-rename-group on-group on-ungroup on-context-menu
selected-full]}] 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) new-css-system (mf/use-ctx ctx/new-css-system)
dragging* (mf/use-state false) dragging* (mf/use-state false)
dragging? (deref dragging*) dragging? (deref dragging*)
@ -232,6 +237,7 @@
(mf/deps dragging* prefix selected-paths selected-full) (mf/deps dragging* prefix selected-paths selected-full)
(fn [event] (fn [event]
(cmm/on-drop-asset-group event dragging* prefix selected-paths selected-full dwl/rename-component)))] (cmm/on-drop-asset-group event dragging* prefix selected-paths selected-full dwl/rename-component)))]
(if ^boolean new-css-system (if ^boolean new-css-system
[:div {:class (dom/classnames (css :component-group) true) [:div {:class (dom/classnames (css :component-group) true)
:on-drag-enter on-drag-enter :on-drag-enter on-drag-enter
@ -294,6 +300,7 @@
:prefix (cph/merge-path-item prefix path-item) :prefix (cph/merge-path-item prefix path-item)
:groups content :groups content
:open-groups open-groups :open-groups open-groups
:force-open? force-open?
:renaming renaming :renaming renaming
:listing-thumbs? listing-thumbs? :listing-thumbs? listing-thumbs?
:selected selected :selected selected
@ -367,6 +374,7 @@
:prefix (cph/merge-path-item prefix path-item) :prefix (cph/merge-path-item prefix path-item)
:groups content :groups content
:open-groups open-groups :open-groups open-groups
:force-open? force-open?
:renaming renaming :renaming renaming
:listing-thumbs? listing-thumbs? :listing-thumbs? listing-thumbs?
:selected selected :selected selected
@ -381,8 +389,9 @@
(mf/defc components-section (mf/defc components-section
{::mf/wrap-props false} {::mf/wrap-props false}
[{:keys [file-id local? components listing-thumbs? open? reverse-sort? selected [{:keys [file-id local? components listing-thumbs? open? force-open?
on-asset-click on-assets-delete on-clear-selection open-status-ref]}] reverse-sort? selected on-asset-click on-assets-delete
on-clear-selection open-status-ref]}]
(let [input-ref (mf/use-ref nil) (let [input-ref (mf/use-ref nil)
@ -599,24 +608,27 @@
:multi true :multi true
:ref input-ref :ref input-ref
:on-selected on-file-selected}]])])) :on-selected on-file-selected}]])]))
[:& cmm/asset-section-block {:role :content} [:& cmm/asset-section-block {:role :content}
[:& components-group {:file-id file-id (when ^boolean open?
:prefix "" [:& components-group {:file-id file-id
:groups groups :prefix ""
:open-groups open-groups :groups groups
:renaming (when ^boolean renaming? current-component-id) :open-groups open-groups
:listing-thumbs? listing-thumbs? :force-open? force-open?
:selected selected :renaming (when ^boolean renaming? current-component-id)
:on-asset-click on-asset-click :listing-thumbs? listing-thumbs?
:on-drag-start on-drag-start :selected selected
:do-rename do-rename :on-asset-click on-asset-click
:cancel-rename cancel-rename :on-drag-start on-drag-start
:on-rename-group on-rename-group :do-rename do-rename
:on-group on-group :cancel-rename cancel-rename
:on-ungroup on-ungroup :on-rename-group on-rename-group
:on-context-menu on-context-menu :on-group on-group
:selected-full selected-full}] :on-ungroup on-ungroup
(when local? :on-context-menu on-context-menu
:selected-full selected-full}])
(when ^boolean local?
[:& cmm/assets-context-menu [:& cmm/assets-context-menu
{:on-close on-close-menu {:on-close on-close-menu
:state @menu-state :state @menu-state

View File

@ -149,7 +149,6 @@
(or (pos? (count typographies)) (or (pos? (count typographies))
(str/empty? filters-term))) (str/empty? filters-term)))
selected-lens (mf/with-memo [file-id] selected-lens (mf/with-memo [file-id]
(-> (l/key file-id) (-> (l/key file-id)
(l/derived lens:selected))) (l/derived lens:selected)))
@ -160,6 +159,12 @@
(count (get selected :colors)) (count (get selected :colors))
(count (get selected :typographies))) (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 extend-selected
(fn [type asset-groups asset-id] (fn [type asset-groups asset-id]
(letfn [(flatten-groups [groups] (letfn [(flatten-groups [groups]
@ -248,7 +253,9 @@
:local? local? :local? local?
:components components :components components
:listing-thumbs? listing-thumbs? :listing-thumbs? listing-thumbs?
:open? (get open-status :components true) :open? (or ^boolean force-open-components?
^boolean (get open-status :components false))
:force-open? force-open-components?
:open-status-ref open-status-ref :open-status-ref open-status-ref
:reverse-sort? reverse-sort? :reverse-sort? reverse-sort?
:selected selected :selected selected
@ -263,7 +270,9 @@
:local? local? :local? local?
:objects media :objects media
:listing-thumbs? listing-thumbs? :listing-thumbs? listing-thumbs?
:open? (get open-status :graphics true) :open? (or ^boolean force-open-graphics?
^boolean (get open-status :graphics false))
:force-open? force-open-graphics?
:open-status-ref open-status-ref :open-status-ref open-status-ref
:reverse-sort? reverse-sort? :reverse-sort? reverse-sort?
:selected selected :selected selected
@ -276,7 +285,9 @@
{:file-id file-id {:file-id file-id
:local? local? :local? local?
:colors colors :colors colors
:open? (get open-status :colors true) :open? (or ^boolean force-open-colors?
^boolean (get open-status :colors false))
:force-open? force-open-colors?
:open-status-ref open-status-ref :open-status-ref open-status-ref
:reverse-sort? reverse-sort? :reverse-sort? reverse-sort?
:selected selected :selected selected
@ -290,7 +301,9 @@
:file-id (:id file) :file-id (:id file)
:local? local? :local? local?
:typographies typographies :typographies typographies
:open? (get open-status :typographies true) :open? (or ^boolean force-open-typographies?
^boolean (get open-status :typographies false))
:force-open? force-open-typographies?
:open-status-ref open-status-ref :open-status-ref open-status-ref
:reverse-sort? reverse-sort? :reverse-sort? reverse-sort?
:selected selected :selected selected
@ -327,7 +340,9 @@
:local? local? :local? local?
:components components :components components
:listing-thumbs? listing-thumbs? :listing-thumbs? listing-thumbs?
:open? (get open-status :components true) :open? (or ^boolean force-open-components?
^boolean (get open-status :components false))
:force-open? force-open-components?
:open-status-ref open-status-ref :open-status-ref open-status-ref
:reverse-sort? reverse-sort? :reverse-sort? reverse-sort?
:selected selected :selected selected
@ -342,7 +357,9 @@
:local? local? :local? local?
:objects media :objects media
:listing-thumbs? listing-thumbs? :listing-thumbs? listing-thumbs?
:open? (get open-status :graphics true) :open? (or ^boolean force-open-graphics?
^boolean (get open-status :graphics false))
:force-open? force-open-graphics?
:open-status-ref open-status-ref :open-status-ref open-status-ref
:reverse-sort? reverse-sort? :reverse-sort? reverse-sort?
:selected selected :selected selected
@ -355,7 +372,9 @@
{:file-id file-id {:file-id file-id
:local? local? :local? local?
:colors colors :colors colors
:open? (get open-status :colors true) :open? (or ^boolean force-open-colors?
^boolean (get open-status :colors false))
:force-open? force-open-colors?
:open-status-ref open-status-ref :open-status-ref open-status-ref
:reverse-sort? reverse-sort? :reverse-sort? reverse-sort?
:selected selected :selected selected
@ -369,7 +388,9 @@
:file-id (:id file) :file-id (:id file)
:local? local? :local? local?
:typographies typographies :typographies typographies
:open? (get open-status :typographies true) :open? (or ^boolean force-open-typographies?
^boolean (get open-status :typographies false))
:force-open? force-open-typographies?
:open-status-ref open-status-ref :open-status-ref open-status-ref
:reverse-sort? reverse-sort? :reverse-sort? reverse-sort?
:selected selected :selected selected

View File

@ -161,7 +161,7 @@
[:div.dragging])])])]))) [:div.dragging])])])])))
(mf/defc graphics-group (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-drag-start do-rename cancel-rename on-rename-group on-ungroup
on-context-menu selected-full]}] on-context-menu selected-full]}]
(let [group-open? (get open-groups prefix true) (let [group-open? (get open-groups prefix true)
@ -249,6 +249,7 @@
:prefix (cph/merge-path-item prefix path-item) :prefix (cph/merge-path-item prefix path-item)
:groups content :groups content
:open-groups open-groups :open-groups open-groups
:force-open? force-open?
:renaming renaming :renaming renaming
:listing-thumbs? listing-thumbs? :listing-thumbs? listing-thumbs?
:selected-objects selected-objects :selected-objects selected-objects
@ -315,6 +316,7 @@
:prefix (cph/merge-path-item prefix path-item) :prefix (cph/merge-path-item prefix path-item)
:groups content :groups content
:open-groups open-groups :open-groups open-groups
:force-open? force-open?
:renaming renaming :renaming renaming
:listing-thumbs? listing-thumbs? :listing-thumbs? listing-thumbs?
:selected-objects selected-objects :selected-objects selected-objects
@ -330,7 +332,7 @@
(mf/defc graphics-section (mf/defc graphics-section
{::mf/wrap-props false} {::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]}] on-asset-click on-assets-delete on-clear-selection]}]
(let [input-ref (mf/use-ref nil) (let [input-ref (mf/use-ref nil)
state (mf/use-state {:renaming nil :object-id nil}) state (mf/use-state {:renaming nil :object-id nil})
@ -518,6 +520,7 @@
:prefix "" :prefix ""
:groups groups :groups groups
:open-groups open-groups :open-groups open-groups
:force-open? force-open?
:renaming (:renaming @state) :renaming (:renaming @state)
:listing-thumbs? listing-thumbs? :listing-thumbs? listing-thumbs?
:selected selected :selected selected

View File

@ -149,7 +149,7 @@
(mf/defc typographies-group (mf/defc typographies-group
{::mf/wrap-props false} {::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 editing-id renaming-id on-asset-click handle-change apply-typography on-rename-group
on-ungroup on-context-menu selected-full]}] on-ungroup on-context-menu selected-full]}]
(let [group-open? (get open-groups prefix true) (let [group-open? (get open-groups prefix true)
@ -236,6 +236,7 @@
:key (dm/str "group-" path-item) :key (dm/str "group-" path-item)
:groups content :groups content
:open-groups open-groups :open-groups open-groups
:force-open? force-open?
:file file :file file
:local? local? :local? local?
:selected selected :selected selected
@ -297,6 +298,7 @@
:key (dm/str "group-" path-item) :key (dm/str "group-" path-item)
:groups content :groups content
:open-groups open-groups :open-groups open-groups
:force-open? force-open?
:file file :file file
:local? local? :local? local?
:selected selected :selected selected
@ -312,7 +314,7 @@
(mf/defc typographies-section (mf/defc typographies-section
{::mf/wrap-props false} {::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]}] on-asset-click on-assets-delete on-clear-selection]}]
(let [state (mf/use-state {:detail-open? false :id nil}) (let [state (mf/use-state {:detail-open? false :id nil})
local-data (mf/deref lens:typography-section-state) local-data (mf/deref lens:typography-section-state)
@ -506,6 +508,7 @@
:prefix "" :prefix ""
:groups groups :groups groups
:open-groups open-groups :open-groups open-groups
:force-open? force-open?
:state state :state state
:file file :file file
:local? local? :local? local?

View File

@ -141,7 +141,7 @@
(fn [] (fn []
(let [parent-id (let [parent-id
(->> @hover-ids (->> @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) (when (some? parent-id)
(get base-objects parent-id))))) (get base-objects parent-id)))))
@ -244,7 +244,7 @@
first-selected-shape (first selected-shapes) first-selected-shape (first selected-shapes)
selecting-first-level-frame? (and one-selected-shape? 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? offset-x (if selecting-first-level-frame?
(:x first-selected-shape) (:x first-selected-shape)

View File

@ -293,7 +293,7 @@
(not (is-guide-inside-frame? (assoc guide :position pos) frame)))] (not (is-guide-inside-frame? (assoc guide :position pos) frame)))]
(when (or (nil? frame) (when (or (nil? frame)
(and (cph/is-direct-child-of-root? frame) (and (cph/root-frame? frame)
(not (ctst/rotated-frame? frame)))) (not (ctst/rotated-frame? frame))))
[:g.guide-area {:opacity (when frame-guide-outside? 0)} [:g.guide-area {:opacity (when frame-guide-outside? 0)}
(when-not disabled-guides? (when-not disabled-guides?

View File

@ -217,7 +217,7 @@
root-frame-with-data? root-frame-with-data?
#(as-> (get objects %) obj #(as-> (get objects %) obj
(and (cph/is-direct-child-of-root? obj) (and (cph/root-frame? obj)
(d/not-empty? (:shapes obj)) (d/not-empty? (:shapes obj))
(not (ctk/instance-head? obj)) (not (ctk/instance-head? obj))
(not (ctk/main-instance? obj)))) (not (ctk/main-instance? obj))))
@ -240,9 +240,10 @@
no-fill-nested-frames? no-fill-nested-frames?
(fn [id] (fn [id]
(and (cph/frame-shape? objects id) (let [shape (get objects id)]
(not (cph/is-direct-child-of-root? objects id)) (and (cph/frame-shape? shape)
(empty? (dm/get-in objects [id :fills])))) (not (cph/is-direct-child-of-root? shape))
(empty? (get shape :fills)))))
hover-shape hover-shape
(->> ids (->> ids
@ -276,7 +277,7 @@
(let [all-frames (mf/use-memo (mf/deps objects) #(ctt/get-root-frames-ids objects)) (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))) 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 %))) (map #(cph/get-shape-id-root-frame objects %)))
selected-shapes-frames (mf/use-memo (mf/deps selected) #(into #{} xf-selected-frame selected)) selected-shapes-frames (mf/use-memo (mf/deps selected) #(into #{} xf-selected-frame selected))

View File

@ -30,7 +30,7 @@
(not (ctl/layout-absolute? shape)) (not (ctl/layout-absolute? shape))
(or (cph/group-shape? shape) (or (cph/group-shape? shape)
(cph/frame-shape? shape))) (cph/frame-shape? shape)))
(cph/is-direct-child-of-root? shape)) (cph/root-frame? shape))
:relative :relative
(and (ctl/any-layout-immediate-child? objects shape) (and (ctl/any-layout-immediate-child? objects shape)
@ -54,14 +54,14 @@
;;shape (gsh/transform-shape) ;;shape (gsh/transform-shape)
shape-value (get selrect coord) 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)) (or (not (ctl/any-layout-immediate-child? objects shape))
(ctl/layout-absolute? shape))) (ctl/layout-absolute? shape)))
(- shape-value parent-value)))) (- shape-value parent-value))))
#_(defn get-shape-position #_(defn get-shape-position
[shape objects coord] [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) (and (ctl/any-layout-immediate-child? objects shape)
(not (ctl/layout-absolute? shape)))) (not (ctl/layout-absolute? shape))))
(let [parent (get objects (:parent-id shape)) (let [parent (get objects (:parent-id shape))