0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-12 18:18:24 -05:00

Merge pull request #4214 from penpot/hiru-review-override-status-of-swapped-copies

🎉 Improve sync algorithm when swapped copies
This commit is contained in:
Alejandro 2024-03-08 12:10:13 +01:00 committed by GitHub
commit 3e9b2ec5c8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 287 additions and 128 deletions

View file

@ -507,8 +507,7 @@
(and (:shape-ref parent)
(#{:group :frame} (:type parent))
(not ignore-touched))
(-> (update :touched cfh/set-touched-group :shapes-group)
(dissoc :remote-synced)))))
(dissoc :remote-synced))))
(remove-from-old-parent [old-objects objects shape-id]
(let [prev-parent-id (dm/get-in old-objects [shape-id :parent-id])]
@ -525,9 +524,7 @@
(-> objects
(d/update-in-when [pid :shapes] d/without-obj sid)
(d/update-in-when [pid :shapes] d/vec-without-nils)
(cond-> component? (d/update-when pid #(-> %
(update :touched cfh/set-touched-group :shapes-group)
(dissoc :remote-synced)))))))))
(cond-> component? (d/update-when pid #(dissoc % :remote-synced))))))))
(update-parent-id [objects id]
(-> objects
(d/update-when id assoc :parent-id parent-id)))

View file

@ -360,7 +360,8 @@
(defn set-touched-group
[touched group]
(conj (or touched #{}) group))
(when group
(conj (or touched #{}) group)))
(defn touched-group?
[shape group]

View file

@ -4,7 +4,11 @@
;;
;; Copyright (c) KALEIDOS INC
(ns app.common.types.component)
(ns app.common.types.component
(:require
[app.common.data :as d]
[app.common.uuid :as uuid]
[cuerdas.core :as str]))
;; Attributes that may be synced in components, and the group they belong to.
;; When one attribute is modified in a shape inside a component, the corresponding
@ -170,6 +174,29 @@
(and (= shape-id (:main-instance-id component))
(= page-id (:main-instance-page component))))
(defn build-swap-slot-group
"Convert a swap-slot into a :touched group"
[swap-slot]
(when swap-slot
(keyword (str "swap-slot-" swap-slot))))
(defn get-swap-slot
"If the shape has a :touched group in the form :swap-slot-<uuid>, get the id."
[shape]
(let [group (->> (:touched shape)
(map name)
(d/seek #(str/starts-with? % "swap-slot-")))]
(when group
(uuid/uuid (subs group 10)))))
(defn match-swap-slot?
[shape-main shape-inst]
(let [slot-main (get-swap-slot shape-main)
slot-inst (get-swap-slot shape-inst)]
(when (some? slot-inst)
(or (= slot-main slot-inst)
(= (:id shape-main) slot-inst)))))
(defn get-component-root
[component]
(if (true? (:main-instance-id component))

View file

@ -166,22 +166,33 @@
(ctk/get-component-root component))))
(defn get-component-shape
"Retrieve one shape in the component by id."
[file-data component shape-id]
"Retrieve one shape in the component by id. If with-context? is true, add the
file and container where the shape resides in its metadata."
[file-data component shape-id & {:keys [with-context?] :or {with-context? false}}]
(let [components-v2 (dm/get-in file-data [:options :components-v2])]
(if (and components-v2 (not (:deleted component)))
(let [component-page (get-component-page file-data component)]
(when component-page
(cfh/get-child (:objects component-page)
(:main-instance-id component)
shape-id)))
(dm/get-in component [:objects shape-id]))))
(let [child (cfh/get-child (:objects component-page)
(:main-instance-id component)
shape-id)]
(cond-> child
(and child with-context?)
(with-meta {:file {:id (:id file-data)
:data file-data}
:container (ctn/make-container component-page :page)})))))
(cond-> (dm/get-in component [:objects shape-id])
with-context?
(with-meta {:file {:id (:id file-data)
:data file-data}
:container (ctn/make-container component :component)})))))
(defn get-ref-shape
"Retrieve the shape in the component that is referenced by the instance shape."
[file-data component shape]
[file-data component shape & {:keys [with-context?] :or {with-context? false}}]
(when (:shape-ref shape)
(get-component-shape file-data component (:shape-ref shape))))
(get-component-shape file-data component (:shape-ref shape) :with-context? with-context?)))
(defn get-shape-in-copy
"Given a shape in the main component and the root of the copy component returns the equivalent
@ -193,16 +204,16 @@
(defn find-ref-shape
"Locate the nearest component in the local file or libraries, and retrieve the shape
referenced by the instance shape."
[file page libraries shape & {:keys [include-deleted?] :or {include-deleted? false}}]
[file container libraries shape & {:keys [include-deleted? with-context?] :or {include-deleted? false with-context? false}}]
(let [find-ref-shape-in-head
(fn [head-shape]
(let [head-file (find-component-file file libraries (:component-file head-shape))
head-component (when (some? head-file)
(ctkl/get-component (:data head-file) (:component-id head-shape) include-deleted?))]
(when (some? head-component)
(get-ref-shape (:data head-file) head-component shape))))]
(let [component-file (find-component-file file libraries (:component-file head-shape))
component (when (some? component-file)
(ctkl/get-component (:data component-file) (:component-id head-shape) include-deleted?))]
(when (some? component)
(get-ref-shape (:data component-file) component shape :with-context? with-context?))))]
(some find-ref-shape-in-head (ctn/get-parent-heads (:objects page) shape))))
(some find-ref-shape-in-head (ctn/get-parent-heads (:objects container) shape))))
(defn find-ref-component
"Locate the nearest component in the local file or libraries that is referenced by the
@ -210,12 +221,14 @@
[file page libraries shape & {:keys [include-deleted?] :or {include-deleted? false}}]
(let [find-ref-component-in-head
(fn [head-shape]
(let [head-file (find-component-file file libraries (:component-file head-shape))
head-component (when (some? head-file)
(ctkl/get-component (:data head-file) (:component-id head-shape) include-deleted?))]
(when (some? head-component)
(when (get-ref-shape (:data head-file) head-component shape)
head-component))))]
(let [component-file (find-component-file file libraries (:component-file head-shape))
component (when (some? component-file)
(ctkl/get-component (:data component-file)
(:component-id head-shape)
include-deleted?))]
(when (some? component)
(when (get-ref-shape (:data component-file) component shape)
component))))]
(some find-ref-component-in-head (ctn/get-parent-copy-heads (:objects page) shape))))
@ -251,6 +264,34 @@
(let [ref-component (find-ref-component file page libraries shape :include-deleted? true)]
(true? (= (:id component) (:id ref-component)))))
(defn find-swap-slot
[shape container file libraries]
(if-let [swap-slot (ctk/get-swap-slot shape)]
swap-slot
(let [ref-shape (find-ref-shape file
container
libraries
shape
:include-deleted? true
:with-context? true)
shape-meta (meta ref-shape)
ref-file (:file shape-meta)
ref-container (:container shape-meta)]
(when ref-shape
(if-let [swap-slot (ctk/get-swap-slot ref-shape)]
swap-slot
(if (ctk/main-instance? ref-shape)
(:id shape)
(find-swap-slot ref-shape ref-container ref-file libraries)))))))
(defn match-swap-slot?
[shape-main shape-inst container-inst container-main file libraries]
(let [slot-main (find-swap-slot shape-main container-main file libraries)
slot-inst (find-swap-slot shape-inst container-inst file libraries)]
(when (some? slot-inst)
(or (= slot-main slot-inst)
(= (:id shape-main) slot-inst)))))
(defn get-component-shapes
"Retrieve all shapes of the component"
[file-data component]

View file

@ -40,8 +40,7 @@
(update :shapes update-parent-shapes)
(update :shapes d/vec-without-nils)
(cond-> (and (ctk/in-component-copy? parent) (not ignore-touched))
(-> (update :touched cfh/set-touched-group :shapes-group)
(dissoc :remote-synced)))))
(dissoc :remote-synced))))
update-objects
(fn [objects parent-id]
@ -85,8 +84,7 @@
(let [parent (update parent :shapes d/without-obj shape-id)]
(cond-> parent
(and (:shape-ref parent) (not ignore-touched))
(-> (update :touched cfh/set-touched-group :shapes-group)
(dissoc :remote-synced)))))
(dissoc :remote-synced))))
(delete-from-objects [objects]
(if-let [target (get objects shape-id)]

View file

@ -777,7 +777,7 @@
(rx/of (dwu/start-undo-transaction undo-id)
(dch/commit-changes changes)
(ptk/data-event :layout/update selected-ids)
(ptk/data-event :layout/update {:ids selected-ids})
(dwu/commit-undo-transaction undo-id))))))
;; --- Change Shape Order (D&D Ordering)
@ -987,7 +987,7 @@
(rx/of (dwu/start-undo-transaction undo-id)
(dch/commit-changes changes)
(dwco/expand-collapse parent-id)
(ptk/data-event :layout/update (concat all-parents ids))
(ptk/data-event :layout/update {:ids (concat all-parents ids)})
(dwu/commit-undo-transaction undo-id))))))
(defn relocate-selected-shapes
@ -1105,7 +1105,7 @@
(when (can-align? selected objects)
(rx/of (dwu/start-undo-transaction undo-id)
(dwt/position-shapes moved)
(ptk/data-event :layout/update selected)
(ptk/data-event :layout/update {:ids selected})
(dwu/commit-undo-transaction undo-id)))))))
(defn can-distribute? [selected]
@ -1132,7 +1132,7 @@
(when (can-distribute? selected)
(rx/of (dwu/start-undo-transaction undo-id)
(dwt/position-shapes moved)
(ptk/data-event :layout/update selected)
(ptk/data-event :layout/update {:ids selected})
(dwu/commit-undo-transaction undo-id)))))))
;; --- Shape Proportions
@ -2016,7 +2016,7 @@
(rx/of (dwu/start-undo-transaction undo-id)
(dch/commit-changes changes)
(dws/select-shapes selected)
(ptk/data-event :layout/update [frame-id])
(ptk/data-event :layout/update {:ids [frame-id]})
(dwu/commit-undo-transaction undo-id)))))))
(defn as-content [text]

View file

@ -101,7 +101,7 @@
;; Update layouts for properties marked
(if (d/not-empty? update-layout-ids)
(rx/of (ptk/data-event :layout/update update-layout-ids))
(rx/of (ptk/data-event :layout/update {:ids update-layout-ids}))
(rx/empty))))))))
(defn send-update-indices

View file

@ -194,7 +194,7 @@
(prepare-create-group it objects page-id shapes "Group" false)]
(rx/of (dch/commit-changes changes)
(dws/select-shapes (d/ordered-set (:id group)))
(ptk/data-event :layout/update parents))))))))
(ptk/data-event :layout/update {:ids parents}))))))))
(def ungroup-selected
(ptk/reify ::ungroup-selected
@ -244,7 +244,7 @@
(when-not (empty? selected)
(rx/of (dwu/start-undo-transaction undo-id)
(dch/commit-changes changes)
(ptk/data-event :layout/update parents)
(ptk/data-event :layout/update {:ids parents})
(dwu/commit-undo-transaction undo-id)
(dws/select-shapes child-ids)))))))
@ -289,7 +289,7 @@
(rx/of (dwu/start-undo-transaction undo-id)
(dch/commit-changes changes)
(dws/select-shapes (d/ordered-set (:id group)))
(ptk/data-event :layout/update [(:id group)])
(ptk/data-event :layout/update {:ids [(:id group)]})
(dwu/commit-undo-transaction undo-id))))))))
(def unmask-group

View file

@ -334,7 +334,7 @@
(when-not (empty? (:redo-changes changes))
(rx/of (dch/commit-changes changes)
(dws/select-shapes (d/ordered-set (:id root)))
(ptk/data-event :layout/update parents)))))))))
(ptk/data-event :layout/update {:ids parents})))))))))
(defn add-component
"Add a new component to current file library, from the currently selected shapes.
@ -566,7 +566,7 @@
undo-id (js/Symbol)]
(rx/of (dwu/start-undo-transaction undo-id)
(dch/commit-changes changes)
(ptk/data-event :layout/update [(:id new-shape)])
(ptk/data-event :layout/update {:ids [(:id new-shape)]})
(dws/select-shapes (d/ordered-set (:id new-shape)))
(when start-move?
(dwtr/start-move initial-point #{(:id new-shape)}))
@ -699,6 +699,7 @@
(watch [it state _]
(log/info :msg "RESET-COMPONENT of shape" :id (str id))
(let [file (wsh/get-local-file state)
file-full (wsh/get-local-file-full state)
libraries (wsh/get-libraries state)
page-id (:current-page-id state)
@ -711,7 +712,7 @@
(-> (pcb/empty-changes it)
(pcb/with-container container)
(pcb/with-objects (:objects container))
(dwlh/generate-sync-shape-direct libraries container id true components-v2))]
(dwlh/generate-sync-shape-direct file-full libraries container id true components-v2))]
(log/debug :msg "RESET-COMPONENT finished" :js/rchanges (log-changes
(:redo-changes changes)
@ -750,6 +751,7 @@
(log/info :msg "UPDATE-COMPONENT of shape" :id (str id) :undo-group undo-group)
(let [page-id (get state :current-page-id)
local-file (wsh/get-local-file state)
full-file (wsh/get-local-file-full state)
container (cfh/get-container local-file :page page-id)
shape (ctn/get-shape container id)
components-v2 (features/active-feature? state "components/v2")]
@ -761,7 +763,7 @@
(-> (pcb/empty-changes it)
(pcb/set-undo-group undo-group)
(pcb/with-container container)
(dwlh/generate-sync-shape-inverse libraries container id components-v2))
(dwlh/generate-sync-shape-inverse full-file libraries container id components-v2))
file-id (:component-file shape)
file (wsh/get-file state file-id)
@ -870,16 +872,12 @@
0)))))
(defn- add-component-for-swap
[shape file-id id-new-component index target-cell keep-props-values {:keys [undo-group]}]
[shape file page libraries id-new-component index target-cell keep-props-values {:keys [undo-group]}]
(dm/assert! (uuid? id-new-component))
(dm/assert! (uuid? file-id))
(ptk/reify ::add-component-for-swap
ptk/WatchEvent
(watch [it state _]
(let [page (wsh/lookup-page state)
libraries (wsh/get-libraries state)
objects (:objects page)
(watch [it _ _]
(let [objects (:objects page)
position (gpt/point (:x shape) (:y shape))
changes (-> (pcb/empty-changes it (:id page))
(pcb/set-undo-group undo-group)
@ -889,7 +887,7 @@
[new-shape changes]
(dwlh/generate-instantiate-component changes
objects
file-id
(:id file)
id-new-component
position
page
@ -898,6 +896,15 @@
(:parent-id shape)
(:frame-id shape))
new-shape (cond-> new-shape
(nil? (ctk/get-swap-slot new-shape))
(update :touched cfh/set-touched-group (-> (ctf/find-swap-slot shape
page
{:id (:id file)
:data file}
libraries)
(ctk/build-swap-slot-group))))
changes
(-> changes
;; Restore the properties
@ -905,7 +912,11 @@
;; We need to set the same index as the original shape
(pcb/change-parent (:parent-id shape) [new-shape] index {:component-swap true
:ignore-touched true}))]
:ignore-touched true})
(dwlh/change-touched new-shape
shape
(ctn/make-container page :page)
{}))]
;; First delete so we don't break the grid layout cells
(rx/of (dch/commit-changes changes)
@ -921,7 +932,10 @@
(watch [_ state _]
;; First delete shapes so we have space in the layout otherwise we can have problems
;; in the grid creating new rows/columns to make space
(let [objects (wsh/lookup-page-objects state)
(let [file (wsh/get-file state file-id)
libraries (wsh/get-libraries state)
page (wsh/lookup-page state)
objects (wsh/lookup-page-objects state)
parent (get objects (:parent-id shape))
;; If the target parent is a grid layout we need to pass the target cell
@ -935,15 +949,14 @@
undo-id (js/Symbol)
undo-group (uuid/next)]
(rx/of
(dwu/start-undo-transaction undo-id)
(dwsh/delete-shapes nil (d/ordered-set (:id shape)) {:component-swap true
:undo-id undo-id
:undo-group undo-group})
(add-component-for-swap shape file-id id-new-component index target-cell keep-props-values
(add-component-for-swap shape file page libraries id-new-component index target-cell keep-props-values
{:undo-group undo-group})
(ptk/data-event :layout/update [(:parent-id shape)])
(ptk/data-event :layout/update {:ids [(:parent-id shape)] :undo-group undo-group})
(dwu/commit-undo-transaction undo-id))))))
(defn component-multi-swap
@ -958,8 +971,12 @@
{::ev/name "component-swap"})
ptk/WatchEvent
(watch [_ _ _]
(watch [_ state _]
(let [undo-id (js/Symbol)]
(log/info :msg "COMPONENT-SWAP"
:file (dwlh/pretty-file file-id state)
:id-new-component id-new-component
:undo-id undo-id)
(rx/concat
(rx/of (dwu/start-undo-transaction undo-id))
(rx/map #(component-swap % file-id id-new-component) (rx/from shapes))
@ -1065,7 +1082,7 @@
:file-id file-id))))
(when-not (empty? updated-frames)
(rx/merge
(rx/of (ptk/data-event :layout/update (map :id updated-frames)))
(rx/of (ptk/data-event :layout/update {:ids (map :id updated-frames) :undo-group undo-group}))
(->> (rx/from updated-frames)
(rx/mapcat
(fn [shape]

View file

@ -320,16 +320,17 @@
(loop [containers (ctf/object-containers-seq file)
changes (pcb/empty-changes it)]
(if-let [container (first containers)]
(recur (next containers)
(pcb/concat-changes
changes
(generate-sync-container it
asset-type
asset-id
library-id
state
container
components-v2)))
(do
(recur (next containers)
(pcb/concat-changes
changes
(generate-sync-container it
asset-type
asset-id
library-id
state
container
components-v2))))
changes))))
(defn generate-sync-library
@ -424,8 +425,9 @@
(defmethod generate-sync-shape :components
[_ changes _library-id state container shape components-v2]
(let [shape-id (:id shape)
file (wsh/get-local-file-full state)
libraries (wsh/get-libraries state)]
(generate-sync-shape-direct changes libraries container shape-id false components-v2)))
(generate-sync-shape-direct changes file libraries container shape-id false components-v2)))
(defmethod generate-sync-shape :colors
[_ changes library-id state _ shape _]
@ -593,8 +595,8 @@
(defn generate-sync-shape-direct
"Generate changes to synchronize one shape that is the root of a component
instance, and all its children, from the given component."
[changes libraries container shape-id reset? components-v2]
(log/debug :msg "Sync shape direct" :shape (str shape-id) :reset? reset?)
[changes file libraries container shape-id reset? components-v2]
(log/debug :msg "Sync shape direct" :shape-inst (str shape-id) :reset? reset?)
(let [shape-inst (ctn/get-shape container shape-id)
library (dm/get-in libraries [(:component-file shape-inst) :data])
component (ctkl/get-component library (:component-id shape-inst) true)]
@ -622,6 +624,8 @@
shape-inst
component
library
file
libraries
shape-main
root-inst
root-main
@ -654,9 +658,9 @@
nil))))))
(defn- generate-sync-shape-direct-recursive
[changes container shape-inst component library shape-main root-inst root-main reset? initial-root? redirect-shaperef components-v2]
[changes container shape-inst component library file libraries shape-main root-inst root-main reset? initial-root? redirect-shaperef components-v2]
(log/debug :msg "Sync shape direct recursive"
:shape (str (:name shape-inst))
:shape-inst (str (:name shape-inst) " " (pretty-uuid (:id shape-inst)))
:component (:name component))
(if (nil? shape-main)
@ -713,6 +717,8 @@
(map #(redirect-shaperef %) children-inst) children-inst)
only-inst (fn [changes child-inst]
(log/trace :msg "Only inst"
:child-inst (str (:name child-inst) " " (pretty-uuid (:id child-inst))))
(if-not (and omit-touched?
(contains? (:touched shape-inst)
:shapes-group))
@ -723,6 +729,8 @@
changes))
only-main (fn [changes child-main]
(log/trace :msg "Only main"
:child-main (str (:name child-main) " " (pretty-uuid (:id child-main))))
(if-not (and omit-touched?
(contains? (:touched shape-inst)
:shapes-group))
@ -739,11 +747,16 @@
changes))
both (fn [changes child-inst child-main]
(log/trace :msg "Both"
:child-inst (str (:name child-inst) " " (pretty-uuid (:id child-inst)))
:child-main (str (:name child-main) " " (pretty-uuid (:id child-main))))
(generate-sync-shape-direct-recursive changes
container
child-inst
component
library
file
libraries
child-main
root-inst
root-main
@ -752,7 +765,17 @@
redirect-shaperef
components-v2))
swapped (fn [changes child-inst child-main]
(log/trace :msg "Match slot"
:child-inst (str (:name child-inst) " " (pretty-uuid (:id child-inst)))
:child-main (str (:name child-main) " " (pretty-uuid (:id child-main))))
;; For now we don't make any sync here.
changes)
moved (fn [changes child-inst child-main]
(log/trace :msg "Move"
:child-inst (str (:name child-inst) " " (pretty-uuid (:id child-inst)))
:child-main (str (:name child-main) " " (pretty-uuid (:id child-main))))
(move-shape
changes
child-inst
@ -764,11 +787,17 @@
(compare-children changes
children-inst
children-main
container
component-container
file
libraries
only-inst
only-main
both
swapped
moved
false))))
false
reset?))))
(defn- generate-rename-component
@ -792,7 +821,7 @@
(defn generate-sync-shape-inverse
"Generate changes to update the component a shape is linked to, from
the values in the shape and all its children."
[changes libraries container shape-id components-v2]
[changes file libraries container shape-id components-v2]
(log/debug :msg "Sync shape inverse" :shape (str shape-id))
(let [redirect-shaperef (partial redirect-shaperef container libraries)
shape-inst (ctn/get-shape container shape-id)
@ -823,6 +852,8 @@
shape-inst
component
library
file
libraries
shape-main
root-inst
root-main
@ -832,7 +863,7 @@
changes)))
(defn- generate-sync-shape-inverse-recursive
[changes container shape-inst component library shape-main root-inst root-main initial-root? redirect-shaperef components-v2]
[changes container shape-inst component library file libraries shape-main root-inst root-main initial-root? redirect-shaperef components-v2]
(log/trace :msg "Sync shape inverse recursive"
:shape (str (:name shape-inst))
:component (:name component))
@ -915,6 +946,8 @@
child-inst
component
library
file
libraries
child-main
root-inst
root-main
@ -922,6 +955,13 @@
redirect-shaperef
components-v2))
swapped (fn [changes child-inst child-main]
(log/trace :msg "Match slot"
:child-inst (str (:name child-inst) " " (pretty-uuid (:id child-inst)))
:child-main (str (:name child-main) " " (pretty-uuid (:id child-main))))
;; For now we don't make any sync here.
changes)
moved (fn [changes child-inst child-main]
(move-shape
changes
@ -935,10 +975,16 @@
(compare-children changes
children-inst
children-main
container
component-container
file
libraries
only-inst
only-main
both
swapped
moved
true
true)
;; The inverse sync may be made on a component that is inside a
@ -957,12 +1003,15 @@
;; ---- Operation generation helpers ----
(defn- compare-children
[changes children-inst children-main only-inst-cb only-main-cb both-cb moved-cb inverse?]
[changes children-inst children-main container-inst container-main file libraries only-inst-cb only-main-cb both-cb swapped-cb moved-cb inverse? reset?]
(log/trace :msg "Compare children")
(loop [children-inst (seq (or children-inst []))
children-main (seq (or children-main []))
changes changes]
(let [child-inst (first children-inst)
child-main (first children-main)]
(log/trace :main (str (:name child-main) " " (pretty-uuid (:id child-main)))
:inst (str (:name child-inst) " " (pretty-uuid (:id child-inst))))
(cond
(and (nil? child-inst) (nil? child-main))
changes
@ -974,13 +1023,20 @@
(reduce only-inst-cb changes children-inst)
:else
(if (ctk/is-main-of? child-main child-inst)
(if (or (ctk/is-main-of? child-main child-inst)
(and (ctf/match-swap-slot? child-main child-inst container-inst container-main file libraries) (not reset?)))
(recur (next children-inst)
(next children-main)
(both-cb changes child-inst child-main))
(if (ctk/is-main-of? child-main child-inst)
(both-cb changes child-inst child-main)
(swapped-cb changes child-inst child-main)))
(let [child-inst' (d/seek #(ctk/is-main-of? child-main %) children-inst)
child-main' (d/seek #(ctk/is-main-of? % child-inst) children-main)]
(let [child-inst' (d/seek #(or (ctk/is-main-of? child-main %)
(and (ctf/match-swap-slot? child-main % container-inst container-main file libraries) (not reset?)))
children-inst)
child-main' (d/seek #(or (ctk/is-main-of? % child-inst)
(and (ctf/match-swap-slot? % child-inst container-inst container-main file libraries) (not reset?)))
children-main)]
(cond
(nil? child-inst')
(recur children-inst
@ -994,16 +1050,26 @@
:else
(if inverse?
(recur (next children-inst)
(remove #(= (:id %) (:id child-main')) children-main)
(-> changes
(let [is-main? (ctk/is-main-of? child-inst child-main')]
(recur (next children-inst)
(remove #(= (:id %) (:id child-main')) children-main)
(cond-> changes
is-main?
(both-cb child-inst child-main')
(moved-cb child-inst child-main')))
(recur (remove #(= (:id %) (:id child-inst')) children-inst)
(next children-main)
(-> changes
(not is-main?)
(swapped-cb child-inst child-main')
:always
(moved-cb child-inst child-main'))))
(let [is-main? (ctk/is-main-of? child-inst' child-main)]
(recur (remove #(= (:id %) (:id child-inst')) children-inst)
(next children-main)
(cond-> changes
is-main?
(both-cb child-inst' child-main)
(moved-cb child-inst' child-main)))))))))))
(not is-main?)
(swapped-cb child-inst' child-main)
:always
(moved-cb child-inst' child-main))))))))))))
(defn- add-shape-to-instance
[changes component-shape index component-page container root-instance root-main omit-touched? set-remote-synced?]
@ -1033,7 +1099,8 @@
(assoc :remote-synced true)
:always
(assoc :shape-ref (:id original-shape)))))
(-> (assoc :shape-ref (:id original-shape))
(dissoc :touched))))) ; New shape, by definition, is synced to the main shape
update-original-shape (fn [original-shape _new-shape]
original-shape)
@ -1270,11 +1337,10 @@
changes
changes')))
(defn- change-touched
(defn change-touched
[changes dest-shape origin-shape container
{:keys [reset-touched? copy-touched?] :as options}]
(if (or (nil? (:shape-ref dest-shape))
(not (or reset-touched? copy-touched?)))
(if (nil? (:shape-ref dest-shape))
changes
(do
(log/info :msg (str "CHANGE-TOUCHED "
@ -1287,12 +1353,16 @@
(let [new-touched (cond
reset-touched?
nil
copy-touched?
(if (:remote-synced origin-shape)
nil
(set/union
(:touched dest-shape)
(:touched origin-shape))))]
(:touched origin-shape)))
:else
(:touched dest-shape))]
(-> changes
(update :redo-changes conj (make-change

View file

@ -458,7 +458,7 @@
([]
(apply-modifiers nil))
([{:keys [modifiers undo-transation? stack-undo? ignore-constraints ignore-snap-pixel]
([{:keys [modifiers undo-transation? stack-undo? ignore-constraints ignore-snap-pixel undo-group]
:or {undo-transation? true stack-undo? false ignore-constraints false ignore-snap-pixel false}}]
(ptk/reify ::apply-modifiers
ptk/WatchEvent
@ -508,6 +508,7 @@
{:reg-objects? true
:stack-undo? stack-undo?
:ignore-tree ignore-tree
:undo-group undo-group
;; Attributes that can change in the transform. This way we don't have to check
;; all the attributes
:attrs [:selrect

View file

@ -332,7 +332,7 @@
ptk/WatchEvent
(watch [_ _ _]
(rx/of (ptk/data-event :layout/update [id])))))
(rx/of (ptk/data-event :layout/update {:ids [id]})))))
(defn split-segments
[{:keys [from-p to-p t]}]

View file

@ -751,7 +751,7 @@
(dwu/start-undo-transaction undo-id)
(dch/commit-changes changes)
(select-shapes new-selected)
(ptk/data-event :layout/update frames)
(ptk/data-event :layout/update {:ids frames})
(memorize-duplicated id-original id-duplicated)
(dwu/commit-undo-transaction undo-id))))))))))

View file

@ -94,7 +94,7 @@
;; Never call this directly but through the data-event `:layout/update`
;; Otherwise a lot of cycle dependencies could be generated
(defn- update-layout-positions
[ids]
[{:keys [ids undo-group]}]
(ptk/reify ::update-layout-positions
ptk/WatchEvent
(watch [_ state _]
@ -103,7 +103,8 @@
(if (d/not-empty? ids)
(let [modif-tree (dwm/create-modif-tree ids (ctm/reflow-modifiers))]
(rx/of (dwm/apply-modifiers {:modifiers modif-tree
:stack-undo? true})))
:stack-undo? true
:undo-group undo-group})))
(rx/empty))))))
(defn initialize
@ -139,7 +140,7 @@
(rx/of (dwu/start-undo-transaction undo-id)
(dch/update-shapes [id] layout-initializer {:with-objects? true})
(dch/update-shapes (dm/get-prop parent :shapes) #(dissoc % :constraints-h :constraints-v))
(ptk/data-event :layout/update [id])
(ptk/data-event :layout/update {:ids [id]})
(dwu/commit-undo-transaction undo-id))))))
(defn create-layout-from-selection
@ -180,7 +181,7 @@
(dch/update-shapes [new-shape-id] #(assoc % :layout-item-h-sizing :auto :layout-item-v-sizing :auto))
(dch/update-shapes selected #(assoc % :layout-item-h-sizing :fix :layout-item-v-sizing :fix))
(dwsh/delete-shapes page-id selected)
(ptk/data-event :layout/update [new-shape-id])
(ptk/data-event :layout/update {:ids [new-shape-id]})
(dwu/commit-undo-transaction undo-id)))
;; Create Layout from selection
@ -191,7 +192,7 @@
(dch/update-shapes [new-shape-id] #(assoc % :layout-item-h-sizing :auto :layout-item-v-sizing :auto))
(dch/update-shapes selected #(assoc % :layout-item-h-sizing :fix :layout-item-v-sizing :fix))))
(rx/of (ptk/data-event :layout/update [new-shape-id])
(rx/of (ptk/data-event :layout/update {:ids [new-shape-id]})
(dwu/commit-undo-transaction undo-id)))))))
(defn remove-layout
@ -203,7 +204,7 @@
(rx/of
(dwu/start-undo-transaction undo-id)
(dch/update-shapes ids #(apply dissoc % layout-keys))
(ptk/data-event :layout/update ids)
(ptk/data-event :layout/update {:ids ids})
(dwu/commit-undo-transaction undo-id))))))
(defn create-layout
@ -256,7 +257,7 @@
(let [undo-id (js/Symbol)]
(rx/of (dwu/start-undo-transaction undo-id)
(dch/update-shapes ids (d/patch-object changes))
(ptk/data-event :layout/update ids)
(ptk/data-event :layout/update {:ids ids})
(dwu/commit-undo-transaction undo-id))))))
(defn add-layout-track
@ -275,7 +276,7 @@
(case type
:row (ctl/add-grid-row shape value index)
:column (ctl/add-grid-column shape value index))))
(ptk/data-event :layout/update ids)
(ptk/data-event :layout/update {:ids ids})
(dwu/commit-undo-transaction undo-id)))))))
(defn remove-layout-track
@ -309,7 +310,7 @@
:row (ctl/remove-grid-row shape index objects)
:column (ctl/remove-grid-column shape index objects)))
{:with-objects? true})
(ptk/data-event :layout/update ids)
(ptk/data-event :layout/update {:ids ids})
(dwu/commit-undo-transaction undo-id)))))))
(defn duplicate-layout-track
@ -363,7 +364,7 @@
undo-id (js/Symbol)]
(rx/of (dwu/start-undo-transaction undo-id)
(dch/commit-changes changes)
(ptk/data-event :layout/update ids)
(ptk/data-event :layout/update {:ids ids})
(dwu/commit-undo-transaction undo-id))))))
(defn reorder-layout-track
@ -381,7 +382,7 @@
(case type
:row (ctl/reorder-grid-row shape from-index to-index move-content?)
:column (ctl/reorder-grid-column shape from-index to-index move-content?))))
(ptk/data-event :layout/update ids)
(ptk/data-event :layout/update {:ids ids})
(dwu/commit-undo-transaction undo-id))))))
(defn hover-layout-track
@ -426,7 +427,7 @@
(fn [shape]
(-> shape
(update-in [property index] merge props))))
(ptk/data-event :layout/update ids)
(ptk/data-event :layout/update {:ids ids})
(dwu/commit-undo-transaction undo-id))))))
(defn fix-child-sizing
@ -523,7 +524,7 @@
(cond-> (ctl/grid-layout? parent)
(ctl/assign-cells objects))))
{:with-objects? true})
(ptk/data-event :layout/update ids)
(ptk/data-event :layout/update {:ids ids})
(dwu/commit-undo-transaction undo-id))))))
(defn update-grid-cells
@ -546,7 +547,7 @@
[:layout-grid-cells cell-id]
d/patch-object props))
shape))))
(ptk/data-event :layout/update [layout-id])
(ptk/data-event :layout/update {:ids [layout-id]})
(dwu/commit-undo-transaction undo-id))))))
(defn change-cells-mode
@ -612,7 +613,7 @@
(d/update-in-when [:layout-grid-cells (:id target-cell)] assoc :position :area)))))
{:with-objects? true})
(dwge/clean-selection layout-id)
(ptk/data-event :layout/update [layout-id])
(ptk/data-event :layout/update {:ids [layout-id]})
(dwu/commit-undo-transaction undo-id))))))
(defn merge-cells
@ -644,7 +645,7 @@
(ctl/assign-cells objects))))
{:with-objects? true})
(dwge/clean-selection layout-id)
(ptk/data-event :layout/update [layout-id])
(ptk/data-event :layout/update {:ids [layout-id]})
(dwu/commit-undo-transaction undo-id))))))
(defn update-grid-cell-position
@ -669,7 +670,7 @@
(:row-span new-data) (:column-span new-data))
(ctl/assign-cells objects))))
{:with-objects? true})
(ptk/data-event :layout/update [layout-id])
(ptk/data-event :layout/update {:ids [layout-id]})
(dwu/commit-undo-transaction undo-id))))))
@ -724,5 +725,5 @@
(rx/of
(dwu/start-undo-transaction undo-id)
(dch/commit-changes changes)
(ptk/data-event :layout/update [layout-id])
(ptk/data-event :layout/update {:ids [layout-id]})
(dwu/commit-undo-transaction undo-id))))))

View file

@ -57,7 +57,7 @@
(rx/of (dwu/start-undo-transaction undo-id)
(dch/commit-changes changes)
(when-not no-update-layout?
(ptk/data-event :layout/update [(:parent-id shape)]))
(ptk/data-event :layout/update {:ids [(:parent-id shape)]}))
(when-not no-select?
(dws/select-shapes (d/ordered-set (:id shape))))
(dwu/commit-undo-transaction undo-id))
@ -141,10 +141,11 @@
(rx/concat
(rx/of (dwu/start-undo-transaction undo-id)
(update-shape-flags ids-to-hide {:hidden true}))
(update-shape-flags ids-to-hide {:hidden true :undo-group (:undo-group options)}))
(real-delete-shapes file page objects ids-to-delete it {:components-v2 components-v2
:ignore-touched (:component-swap options)
:undo-group (:undo-group options)})
:undo-group (:undo-group options)
:undo-id undo-id})
(rx/of (dwu/commit-undo-transaction undo-id))))))))
(defn- real-delete-shapes-changes
@ -291,11 +292,11 @@
(defn- real-delete-shapes
[file page objects ids it options]
(let [[changes all-parents] (real-delete-shapes-changes file page objects ids it options)
undo-id (js/Symbol)]
undo-id (or (:undo-id options) (js/Symbol))]
(rx/of (dwu/start-undo-transaction undo-id)
(dc/detach-comment-thread ids)
(dch/commit-changes changes)
(ptk/data-event :layout/update all-parents)
(ptk/data-event :layout/update {:ids all-parents :undo-group (:undo-group options)})
(dwu/commit-undo-transaction undo-id))))
(defn create-and-add-shape
@ -377,7 +378,7 @@
(dwu/start-undo-transaction undo-id)
(dch/commit-changes changes)
(dws/select-shapes (d/ordered-set (:id frame-shape)))
(ptk/data-event :layout/update [(:id frame-shape)])
(ptk/data-event :layout/update {:ids [(:id frame-shape)]})
(dwu/commit-undo-transaction undo-id))))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -385,7 +386,7 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn update-shape-flags
[ids {:keys [blocked hidden transforming] :as flags}]
[ids {:keys [blocked hidden transforming undo-group] :as flags}]
(dm/assert!
"expected valid coll of uuids"
(every? uuid? ids))
@ -409,7 +410,7 @@
ids (if (boolean? blocked)
(into ids (->> ids (mapcat #(cfh/get-children-ids objects %))))
ids)]
(rx/of (dch/update-shapes ids update-fn {:attrs #{:blocked :hidden :transforming}}))))))
(rx/of (dch/update-shapes ids update-fn {:attrs #{:blocked :hidden :transforming} :undo-group undo-group}))))))
(defn toggle-visibility-selected
[]

View file

@ -110,6 +110,11 @@
[state]
(get state :workspace-data))
(defn get-local-file-full
[state]
(-> (get state :workspace-file)
(assoc :data (get state :workspace-data))))
(defn get-file
"Get the data content of the given file (it may be the current file
or one library)."

View file

@ -102,7 +102,7 @@
(rx/of (dwu/start-undo-transaction undo-id)
(dch/commit-changes changes)
(dws/select-shapes (d/ordered-set (:id new-shape)))
(ptk/data-event :layout/update [(:id new-shape)])
(ptk/data-event :layout/update {:ids [(:id new-shape)]})
(dwu/commit-undo-transaction undo-id)))
(catch :default cause

View file

@ -382,7 +382,7 @@
:stack-undo? true
:ignore-remote? true
:ignore-touched true})
(ptk/data-event :layout/update ids)
(ptk/data-event :layout/update {:ids ids})
(dwu/commit-undo-transaction undo-id))))))))
(defn resize-text

View file

@ -719,7 +719,7 @@
(rx/of
(dwu/start-undo-transaction undo-id)
(dch/commit-changes changes)
(ptk/data-event :layout/update selected)
(ptk/data-event :layout/update {:ids selected})
(dwu/commit-undo-transaction undo-id))))))
(defn nudge-selected-shapes