mirror of
https://github.com/penpot/penpot.git
synced 2025-05-20 13:46:11 +02:00
🐛 Protect against broken component refs #1114
This commit is contained in:
parent
9d545004cb
commit
c6fe19c321
1 changed files with 155 additions and 148 deletions
|
@ -204,6 +204,7 @@
|
||||||
"Generate changes to remove the links between a shape and all its children
|
"Generate changes to remove the links between a shape and all its children
|
||||||
with a component."
|
with a component."
|
||||||
[shape-id container]
|
[shape-id container]
|
||||||
|
(log/debug :msg "Detach instance" :shape-id shape-id :container (:id container))
|
||||||
(let [shapes (cp/get-object-with-children shape-id (:objects container))
|
(let [shapes (cp/get-object-with-children shape-id (:objects container))
|
||||||
rchanges (mapv (fn [obj]
|
rchanges (mapv (fn [obj]
|
||||||
(make-change
|
(make-change
|
||||||
|
@ -646,89 +647,92 @@
|
||||||
:shape (str (:name shape-inst))
|
:shape (str (:name shape-inst))
|
||||||
:component (:name component))
|
:component (:name component))
|
||||||
|
|
||||||
(let [omit-touched? (not reset?)
|
(if (nil? shape-main)
|
||||||
clear-remote-synced? (and initial-root? reset?)
|
;; This should not occur, but protect against it in any case
|
||||||
set-remote-synced? (and (not initial-root?) reset?)
|
(generate-detach-instance (:id shape-inst) container)
|
||||||
|
(let [omit-touched? (not reset?)
|
||||||
|
clear-remote-synced? (and initial-root? reset?)
|
||||||
|
set-remote-synced? (and (not initial-root?) reset?)
|
||||||
|
|
||||||
[rchanges uchanges]
|
[rchanges uchanges]
|
||||||
(concat-changes
|
|
||||||
(update-attrs shape-inst
|
|
||||||
shape-main
|
|
||||||
root-inst
|
|
||||||
root-main
|
|
||||||
container
|
|
||||||
omit-touched?)
|
|
||||||
(concat-changes
|
(concat-changes
|
||||||
(if reset?
|
(update-attrs shape-inst
|
||||||
(change-touched shape-inst
|
shape-main
|
||||||
shape-main
|
root-inst
|
||||||
container
|
root-main
|
||||||
{:reset-touched? true})
|
container
|
||||||
empty-changes)
|
omit-touched?)
|
||||||
(concat-changes
|
(concat-changes
|
||||||
(if clear-remote-synced?
|
(if reset?
|
||||||
(change-remote-synced shape-inst container nil)
|
(change-touched shape-inst
|
||||||
|
shape-main
|
||||||
|
container
|
||||||
|
{:reset-touched? true})
|
||||||
empty-changes)
|
empty-changes)
|
||||||
(if set-remote-synced?
|
(concat-changes
|
||||||
(change-remote-synced shape-inst container true)
|
(if clear-remote-synced?
|
||||||
empty-changes))))
|
(change-remote-synced shape-inst container nil)
|
||||||
|
empty-changes)
|
||||||
|
(if set-remote-synced?
|
||||||
|
(change-remote-synced shape-inst container true)
|
||||||
|
empty-changes))))
|
||||||
|
|
||||||
children-inst (mapv #(cp/get-shape container %)
|
children-inst (mapv #(cp/get-shape container %)
|
||||||
(:shapes shape-inst))
|
(:shapes shape-inst))
|
||||||
children-main (mapv #(cp/get-shape component %)
|
children-main (mapv #(cp/get-shape component %)
|
||||||
(:shapes shape-main))
|
(:shapes shape-main))
|
||||||
|
|
||||||
only-inst (fn [child-inst]
|
only-inst (fn [child-inst]
|
||||||
(when-not (and omit-touched?
|
(when-not (and omit-touched?
|
||||||
(contains? (:touched shape-inst)
|
(contains? (:touched shape-inst)
|
||||||
:shapes-group))
|
:shapes-group))
|
||||||
(remove-shape child-inst
|
(remove-shape child-inst
|
||||||
container
|
container
|
||||||
omit-touched?)))
|
omit-touched?)))
|
||||||
|
|
||||||
only-main (fn [child-main]
|
only-main (fn [child-main]
|
||||||
(when-not (and omit-touched?
|
(when-not (and omit-touched?
|
||||||
(contains? (:touched shape-inst)
|
(contains? (:touched shape-inst)
|
||||||
:shapes-group))
|
:shapes-group))
|
||||||
(add-shape-to-instance child-main
|
(add-shape-to-instance child-main
|
||||||
(d/index-of children-main
|
(d/index-of children-main
|
||||||
child-main)
|
child-main)
|
||||||
component
|
component
|
||||||
container
|
container
|
||||||
root-inst
|
root-inst
|
||||||
root-main
|
root-main
|
||||||
omit-touched?
|
omit-touched?
|
||||||
set-remote-synced?)))
|
set-remote-synced?)))
|
||||||
|
|
||||||
both (fn [child-inst child-main]
|
both (fn [child-inst child-main]
|
||||||
(generate-sync-shape-direct-recursive container
|
(generate-sync-shape-direct-recursive container
|
||||||
child-inst
|
child-inst
|
||||||
component
|
component
|
||||||
child-main
|
child-main
|
||||||
root-inst
|
root-inst
|
||||||
root-main
|
root-main
|
||||||
reset?
|
reset?
|
||||||
initial-root?))
|
initial-root?))
|
||||||
|
|
||||||
moved (fn [child-inst child-main]
|
moved (fn [child-inst child-main]
|
||||||
(move-shape
|
(move-shape
|
||||||
child-inst
|
child-inst
|
||||||
(d/index-of children-inst child-inst)
|
(d/index-of children-inst child-inst)
|
||||||
(d/index-of children-main child-main)
|
(d/index-of children-main child-main)
|
||||||
container
|
container
|
||||||
omit-touched?))
|
omit-touched?))
|
||||||
|
|
||||||
[child-rchanges child-uchanges]
|
[child-rchanges child-uchanges]
|
||||||
(compare-children children-inst
|
(compare-children children-inst
|
||||||
children-main
|
children-main
|
||||||
only-inst
|
only-inst
|
||||||
only-main
|
only-main
|
||||||
both
|
both
|
||||||
moved
|
moved
|
||||||
false)]
|
false)]
|
||||||
|
|
||||||
[(d/concat rchanges child-rchanges)
|
[(d/concat rchanges child-rchanges)
|
||||||
(d/concat uchanges child-uchanges)]))
|
(d/concat uchanges child-uchanges)])))
|
||||||
|
|
||||||
(defn generate-sync-shape-inverse
|
(defn generate-sync-shape-inverse
|
||||||
"Generate changes to update the component a shape is linked to, from
|
"Generate changes to update the component a shape is linked to, from
|
||||||
|
@ -764,96 +768,99 @@
|
||||||
:shape (str (:name shape-inst))
|
:shape (str (:name shape-inst))
|
||||||
:component (:name component))
|
:component (:name component))
|
||||||
|
|
||||||
(let [component-container (cp/make-container component :component)
|
(if (nil? shape-main)
|
||||||
|
;; This should not occur, but protect against it in any case
|
||||||
|
empty-changes
|
||||||
|
(let [component-container (cp/make-container component :component)
|
||||||
|
|
||||||
omit-touched? false
|
omit-touched? false
|
||||||
set-remote-synced? (not initial-root?)
|
set-remote-synced? (not initial-root?)
|
||||||
clear-remote-synced? initial-root?
|
clear-remote-synced? initial-root?
|
||||||
|
|
||||||
[rchanges uchanges]
|
[rchanges uchanges]
|
||||||
(concat-changes
|
|
||||||
(update-attrs shape-main
|
|
||||||
shape-inst
|
|
||||||
root-main
|
|
||||||
root-inst
|
|
||||||
component-container
|
|
||||||
omit-touched?)
|
|
||||||
(concat-changes
|
(concat-changes
|
||||||
(change-touched shape-inst
|
(update-attrs shape-main
|
||||||
shape-main
|
shape-inst
|
||||||
container
|
root-main
|
||||||
{:reset-touched? true})
|
root-inst
|
||||||
|
component-container
|
||||||
|
omit-touched?)
|
||||||
(concat-changes
|
(concat-changes
|
||||||
(change-touched shape-main
|
(change-touched shape-inst
|
||||||
shape-inst
|
shape-main
|
||||||
component-container
|
container
|
||||||
{:copy-touched? true})
|
{:reset-touched? true})
|
||||||
(concat-changes
|
(concat-changes
|
||||||
(if clear-remote-synced?
|
(change-touched shape-main
|
||||||
(change-remote-synced shape-inst container nil)
|
shape-inst
|
||||||
empty-changes)
|
component-container
|
||||||
(if set-remote-synced?
|
{:copy-touched? true})
|
||||||
(change-remote-synced shape-inst container true)
|
(concat-changes
|
||||||
empty-changes)))))
|
(if clear-remote-synced?
|
||||||
|
(change-remote-synced shape-inst container nil)
|
||||||
|
empty-changes)
|
||||||
|
(if set-remote-synced?
|
||||||
|
(change-remote-synced shape-inst container true)
|
||||||
|
empty-changes)))))
|
||||||
|
|
||||||
children-inst (mapv #(cp/get-shape container %)
|
children-inst (mapv #(cp/get-shape container %)
|
||||||
(:shapes shape-inst))
|
(:shapes shape-inst))
|
||||||
children-main (mapv #(cp/get-shape component %)
|
children-main (mapv #(cp/get-shape component %)
|
||||||
(:shapes shape-main))
|
(:shapes shape-main))
|
||||||
|
|
||||||
only-inst (fn [child-inst]
|
only-inst (fn [child-inst]
|
||||||
(add-shape-to-main child-inst
|
(add-shape-to-main child-inst
|
||||||
(d/index-of children-inst
|
(d/index-of children-inst
|
||||||
child-inst)
|
child-inst)
|
||||||
component
|
component
|
||||||
container
|
container
|
||||||
root-inst
|
root-inst
|
||||||
root-main))
|
root-main))
|
||||||
|
|
||||||
only-main (fn [child-main]
|
only-main (fn [child-main]
|
||||||
(remove-shape child-main
|
(remove-shape child-main
|
||||||
component-container
|
component-container
|
||||||
false))
|
false))
|
||||||
|
|
||||||
both (fn [child-inst child-main]
|
both (fn [child-inst child-main]
|
||||||
(generate-sync-shape-inverse-recursive container
|
(generate-sync-shape-inverse-recursive container
|
||||||
child-inst
|
child-inst
|
||||||
component
|
component
|
||||||
child-main
|
child-main
|
||||||
root-inst
|
root-inst
|
||||||
root-main
|
root-main
|
||||||
initial-root?))
|
initial-root?))
|
||||||
|
|
||||||
moved (fn [child-inst child-main]
|
moved (fn [child-inst child-main]
|
||||||
(move-shape
|
(move-shape
|
||||||
child-main
|
child-main
|
||||||
(d/index-of children-main child-main)
|
(d/index-of children-main child-main)
|
||||||
(d/index-of children-inst child-inst)
|
(d/index-of children-inst child-inst)
|
||||||
component-container
|
component-container
|
||||||
false))
|
false))
|
||||||
|
|
||||||
[child-rchanges child-uchanges]
|
[child-rchanges child-uchanges]
|
||||||
(compare-children children-inst
|
(compare-children children-inst
|
||||||
children-main
|
children-main
|
||||||
only-inst
|
only-inst
|
||||||
only-main
|
only-main
|
||||||
both
|
both
|
||||||
moved
|
moved
|
||||||
true)
|
true)
|
||||||
|
|
||||||
;; The inverse sync may be made on a component that is inside a
|
;; The inverse sync may be made on a component that is inside a
|
||||||
;; remote library. We need to separate changes that are from
|
;; remote library. We need to separate changes that are from
|
||||||
;; local and remote files.
|
;; local and remote files.
|
||||||
check-local (fn [change]
|
check-local (fn [change]
|
||||||
(cond-> change
|
(cond-> change
|
||||||
(= (:id change) (:id shape-inst))
|
(= (:id change) (:id shape-inst))
|
||||||
(assoc :local-change? true)))
|
(assoc :local-change? true)))
|
||||||
|
|
||||||
rchanges (mapv check-local rchanges)
|
rchanges (mapv check-local rchanges)
|
||||||
uchanges (mapv check-local uchanges)]
|
uchanges (mapv check-local uchanges)]
|
||||||
|
|
||||||
[(d/concat rchanges child-rchanges)
|
[(d/concat rchanges child-rchanges)
|
||||||
(d/concat uchanges child-uchanges)]))
|
(d/concat uchanges child-uchanges)])))
|
||||||
|
|
||||||
|
|
||||||
; ---- Operation generation helpers ----
|
; ---- Operation generation helpers ----
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue