mirror of
https://github.com/penpot/penpot.git
synced 2025-03-31 00:51:19 -05:00
⚡ Add experimental equality with exceptions props checking to frames
This commit is contained in:
parent
b28cad2250
commit
58f788455f
3 changed files with 90 additions and 34 deletions
|
@ -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))
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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]
|
||||
|
|
Loading…
Add table
Reference in a new issue