mirror of
https://github.com/penpot/penpot.git
synced 2025-02-13 10:38:13 -05:00
Merge pull request #2390 from penpot/hiru-delete-comp-assets
🐛 Fix delete component from assets panel in v2
This commit is contained in:
commit
5bbfe376cf
3 changed files with 166 additions and 146 deletions
|
@ -16,6 +16,7 @@
|
|||
[app.common.pages.helpers :as cph]
|
||||
[app.common.spec :as us]
|
||||
[app.common.types.color :as ctc]
|
||||
[app.common.types.components-list :as ctkl]
|
||||
[app.common.types.container :as ctn]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.common.types.pages-list :as ctpl]
|
||||
|
@ -29,6 +30,7 @@
|
|||
[app.main.data.workspace.groups :as dwg]
|
||||
[app.main.data.workspace.libraries-helpers :as dwlh]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.features :as features]
|
||||
|
@ -402,13 +404,16 @@
|
|||
(ptk/reify ::delete-component
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [data (get state :workspace-data)
|
||||
components-v2 (features/active-feature? state :components-v2)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data data)
|
||||
(pcb/delete-component id components-v2))]
|
||||
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
(let [data (get state :workspace-data)]
|
||||
(if (features/active-feature? state :components-v2)
|
||||
(let [component (ctkl/get-component data id)
|
||||
page (ctpl/get-page data (:main-instance-page component))
|
||||
shape (ctn/get-shape page (:main-instance-id component))]
|
||||
(rx/of (dwsh/delete-shapes (:id page) #{(:id shape)})))
|
||||
(let [changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data data)
|
||||
(pcb/delete-component id false))]
|
||||
(rx/of (dch/commit-changes changes))))))))
|
||||
|
||||
(defn restore-component
|
||||
"Restore a deleted component, with the given id, on the current file library."
|
||||
|
@ -554,11 +559,14 @@
|
|||
page-id (:current-page-id state)
|
||||
container (cph/get-container file :page page-id)
|
||||
|
||||
components-v2
|
||||
(features/active-feature? state :components-v2)
|
||||
|
||||
changes
|
||||
(-> (pcb/empty-changes it)
|
||||
(pcb/with-container container)
|
||||
(pcb/with-objects (:objects container))
|
||||
(dwlh/generate-sync-shape-direct libraries container id true))]
|
||||
(dwlh/generate-sync-shape-direct libraries container id true components-v2))]
|
||||
|
||||
(log/debug :msg "RESET-COMPONENT finished" :js/rchanges (log-changes
|
||||
(:redo-changes changes)
|
||||
|
|
|
@ -177,7 +177,8 @@
|
|||
:file (pretty-file file-id state)
|
||||
:library (pretty-file library-id state))
|
||||
|
||||
(let [file (wsh/get-file state file-id)]
|
||||
(let [file (wsh/get-file state file-id)
|
||||
components-v2 (get-in file [:options :components-v2])]
|
||||
(loop [pages (vals (get file :pages-index))
|
||||
changes (pcb/empty-changes it)]
|
||||
(if-let [page (first pages)]
|
||||
|
@ -189,7 +190,8 @@
|
|||
asset-id
|
||||
library-id
|
||||
state
|
||||
(cph/make-container page :page))))
|
||||
(cph/make-container page :page)
|
||||
components-v2)))
|
||||
changes))))
|
||||
|
||||
(defn generate-sync-library
|
||||
|
@ -211,7 +213,8 @@
|
|||
:file (pretty-file file-id state)
|
||||
:library (pretty-file library-id state))
|
||||
|
||||
(let [file (wsh/get-file state file-id)]
|
||||
(let [file (wsh/get-file state file-id)
|
||||
components-v2 (get-in file [:options :components-v2])]
|
||||
(loop [local-components (vals (get file :components))
|
||||
changes (pcb/empty-changes it)]
|
||||
(if-let [local-component (first local-components)]
|
||||
|
@ -223,13 +226,14 @@
|
|||
asset-id
|
||||
library-id
|
||||
state
|
||||
(cph/make-container local-component :component))))
|
||||
(cph/make-container local-component :component)
|
||||
components-v2)))
|
||||
changes))))
|
||||
|
||||
(defn- generate-sync-container
|
||||
"Generate changes to synchronize all shapes in a particular container (a page
|
||||
or a component) that use assets of the given type in the given library."
|
||||
[it asset-type asset-id library-id state container]
|
||||
[it asset-type asset-id library-id state container components-v2]
|
||||
|
||||
(if (cph/page? container)
|
||||
(log/debug :msg "Sync page in local file" :page-id (:id container))
|
||||
|
@ -248,7 +252,8 @@
|
|||
library-id
|
||||
state
|
||||
container
|
||||
shape))
|
||||
shape
|
||||
components-v2))
|
||||
changes))))
|
||||
|
||||
(defmulti uses-assets?
|
||||
|
@ -276,16 +281,16 @@
|
|||
(defmulti generate-sync-shape
|
||||
"Generate changes to synchronize one shape from all assets of the given type
|
||||
that is using, in the given library."
|
||||
(fn [asset-type _changes _library-id _state _container _shape] asset-type))
|
||||
(fn [asset-type _changes _library-id _state _container _shape _components-v2] asset-type))
|
||||
|
||||
(defmethod generate-sync-shape :components
|
||||
[_ changes _library-id state container shape]
|
||||
[_ changes _library-id state container shape components-v2]
|
||||
(let [shape-id (:id shape)
|
||||
libraries (wsh/get-libraries state)]
|
||||
(generate-sync-shape-direct changes libraries container shape-id false)))
|
||||
(generate-sync-shape-direct changes libraries container shape-id false components-v2)))
|
||||
|
||||
(defmethod generate-sync-shape :colors
|
||||
[_ changes library-id state _ shape]
|
||||
[_ changes library-id state _ shape _]
|
||||
(log/debug :msg "Sync colors of shape" :shape (:name shape))
|
||||
|
||||
;; Synchronize a shape that uses some colors of the library. The value of the
|
||||
|
@ -296,7 +301,7 @@
|
|||
#(ctc/sync-shape-colors % library-id library-colors))))
|
||||
|
||||
(defmethod generate-sync-shape :typographies
|
||||
[_ changes library-id state container shape]
|
||||
[_ changes library-id state container shape _]
|
||||
(log/debug :msg "Sync typographies of shape" :shape (:name shape))
|
||||
|
||||
;; Synchronize a shape that uses some typographies of the library. The attributes
|
||||
|
@ -442,7 +447,7 @@
|
|||
(defn generate-sync-shape-direct
|
||||
"Generate changes to synchronize one shape that the root of a component
|
||||
instance, and all its children, from the given component."
|
||||
[changes libraries container shape-id reset?]
|
||||
[changes libraries container shape-id reset? components-v2]
|
||||
(log/debug :msg "Sync shape direct" :shape (str shape-id) :reset? reset?)
|
||||
(let [shape-inst (ctn/get-shape container shape-id)
|
||||
component (cph/get-component libraries
|
||||
|
@ -466,20 +471,25 @@
|
|||
root-inst
|
||||
root-main
|
||||
reset?
|
||||
initial-root?)
|
||||
initial-root?
|
||||
components-v2)
|
||||
; If the component is not found, because the master component has been
|
||||
; deleted or the library unlinked, detach the instance.
|
||||
(generate-detach-instance changes container shape-id))))
|
||||
; deleted or the library unlinked, do nothing in v2 or detach in v1.
|
||||
(if components-v2
|
||||
changes
|
||||
(generate-detach-instance changes container shape-id)))))
|
||||
|
||||
(defn- generate-sync-shape-direct-recursive
|
||||
[changes container shape-inst component shape-main root-inst root-main reset? initial-root?]
|
||||
[changes container shape-inst component shape-main root-inst root-main reset? initial-root? components-v2]
|
||||
(log/debug :msg "Sync shape direct recursive"
|
||||
:shape (str (:name shape-inst))
|
||||
:component (:name component))
|
||||
|
||||
(if (nil? shape-main)
|
||||
;; This should not occur, but protect against it in any case
|
||||
(generate-detach-instance changes container (:id shape-inst))
|
||||
(if components-v2
|
||||
changes
|
||||
(generate-detach-instance changes container (:id shape-inst)))
|
||||
(let [omit-touched? (not reset?)
|
||||
clear-remote-synced? (and initial-root? reset?)
|
||||
set-remote-synced? (and (not initial-root?) reset?)
|
||||
|
@ -545,7 +555,8 @@
|
|||
root-inst
|
||||
root-main
|
||||
reset?
|
||||
initial-root?))
|
||||
initial-root?
|
||||
components-v2))
|
||||
|
||||
moved (fn [changes child-inst child-main]
|
||||
(move-shape
|
||||
|
|
|
@ -131,141 +131,142 @@
|
|||
(rx/empty))))))
|
||||
|
||||
(defn delete-shapes
|
||||
[ids]
|
||||
(us/assert ::us/set-of-uuid ids)
|
||||
(ptk/reify ::delete-shapes
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [file-id (:current-file-id state)
|
||||
page-id (:current-page-id state)
|
||||
file (wsh/get-file state file-id)
|
||||
page (wsh/lookup-page state page-id)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
([ids] (delete-shapes nil ids))
|
||||
([page-id ids]
|
||||
(us/assert ::us/set-of-uuid ids)
|
||||
(ptk/reify ::delete-shapes
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [file-id (:current-file-id state)
|
||||
page-id (or page-id (:current-page-id state))
|
||||
file (wsh/get-file state file-id)
|
||||
page (wsh/lookup-page state page-id)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
|
||||
ids (cph/clean-loops objects ids)
|
||||
lookup (d/getf objects)
|
||||
ids (cph/clean-loops objects ids)
|
||||
lookup (d/getf objects)
|
||||
|
||||
components-v2 (features/active-feature? state :components-v2)
|
||||
components-v2 (features/active-feature? state :components-v2)
|
||||
|
||||
groups-to-unmask
|
||||
(reduce (fn [group-ids id]
|
||||
;; When the shape to delete is the mask of a masked group,
|
||||
;; the mask condition must be removed, and it must be
|
||||
;; converted to a normal group.
|
||||
(let [obj (lookup id)
|
||||
parent (lookup (:parent-id obj))]
|
||||
(if (and (:masked-group? parent)
|
||||
(= id (first (:shapes parent))))
|
||||
(conj group-ids (:id parent))
|
||||
group-ids)))
|
||||
#{}
|
||||
ids)
|
||||
groups-to-unmask
|
||||
(reduce (fn [group-ids id]
|
||||
;; When the shape to delete is the mask of a masked group,
|
||||
;; the mask condition must be removed, and it must be
|
||||
;; converted to a normal group.
|
||||
(let [obj (lookup id)
|
||||
parent (lookup (:parent-id obj))]
|
||||
(if (and (:masked-group? parent)
|
||||
(= id (first (:shapes parent))))
|
||||
(conj group-ids (:id parent))
|
||||
group-ids)))
|
||||
#{}
|
||||
ids)
|
||||
|
||||
interacting-shapes
|
||||
(filter (fn [shape]
|
||||
;; If any of the deleted shapes is the destination of
|
||||
;; some interaction, this must be deleted, too.
|
||||
(let [interactions (:interactions shape)]
|
||||
(some #(and (ctsi/has-destination %)
|
||||
(contains? ids (:destination %)))
|
||||
interactions)))
|
||||
(vals objects))
|
||||
interacting-shapes
|
||||
(filter (fn [shape]
|
||||
;; If any of the deleted shapes is the destination of
|
||||
;; some interaction, this must be deleted, too.
|
||||
(let [interactions (:interactions shape)]
|
||||
(some #(and (ctsi/has-destination %)
|
||||
(contains? ids (:destination %)))
|
||||
interactions)))
|
||||
(vals objects))
|
||||
|
||||
;; If any of the deleted shapes is a frame with guides
|
||||
guides (into {}
|
||||
(comp (map second)
|
||||
(remove #(contains? ids (:frame-id %)))
|
||||
(map (juxt :id identity)))
|
||||
(dm/get-in page [:options :guides]))
|
||||
;; If any of the deleted shapes is a frame with guides
|
||||
guides (into {}
|
||||
(comp (map second)
|
||||
(remove #(contains? ids (:frame-id %)))
|
||||
(map (juxt :id identity)))
|
||||
(dm/get-in page [:options :guides]))
|
||||
|
||||
starting-flows
|
||||
(filter (fn [flow]
|
||||
;; If any of the deleted is a frame that starts a flow,
|
||||
;; this must be deleted, too.
|
||||
(contains? ids (:starting-frame flow)))
|
||||
(-> page :options :flows))
|
||||
starting-flows
|
||||
(filter (fn [flow]
|
||||
;; If any of the deleted is a frame that starts a flow,
|
||||
;; this must be deleted, too.
|
||||
(contains? ids (:starting-frame flow)))
|
||||
(-> page :options :flows))
|
||||
|
||||
all-parents
|
||||
(reduce (fn [res id]
|
||||
;; All parents of any deleted shape must be resized.
|
||||
(into res (cph/get-parent-ids objects id)))
|
||||
(d/ordered-set)
|
||||
ids)
|
||||
all-parents
|
||||
(reduce (fn [res id]
|
||||
;; All parents of any deleted shape must be resized.
|
||||
(into res (cph/get-parent-ids objects id)))
|
||||
(d/ordered-set)
|
||||
ids)
|
||||
|
||||
all-children
|
||||
(->> ids ;; Children of deleted shapes must be also deleted.
|
||||
(reduce (fn [res id]
|
||||
(into res (cph/get-children-ids objects id)))
|
||||
[])
|
||||
(reverse)
|
||||
(into (d/ordered-set)))
|
||||
all-children
|
||||
(->> ids ;; Children of deleted shapes must be also deleted.
|
||||
(reduce (fn [res id]
|
||||
(into res (cph/get-children-ids objects id)))
|
||||
[])
|
||||
(reverse)
|
||||
(into (d/ordered-set)))
|
||||
|
||||
find-all-empty-parents
|
||||
(fn recursive-find-empty-parents [empty-parents]
|
||||
(let [all-ids (into empty-parents ids)
|
||||
contains? (partial contains? all-ids)
|
||||
xform (comp (map lookup)
|
||||
(filter cph/group-shape?)
|
||||
(remove #(->> (:shapes %) (remove contains?) seq))
|
||||
(map :id))
|
||||
parents (into #{} xform all-parents)]
|
||||
(if (= empty-parents parents)
|
||||
empty-parents
|
||||
(recursive-find-empty-parents parents))))
|
||||
find-all-empty-parents
|
||||
(fn recursive-find-empty-parents [empty-parents]
|
||||
(let [all-ids (into empty-parents ids)
|
||||
contains? (partial contains? all-ids)
|
||||
xform (comp (map lookup)
|
||||
(filter cph/group-shape?)
|
||||
(remove #(->> (:shapes %) (remove contains?) seq))
|
||||
(map :id))
|
||||
parents (into #{} xform all-parents)]
|
||||
(if (= empty-parents parents)
|
||||
empty-parents
|
||||
(recursive-find-empty-parents parents))))
|
||||
|
||||
empty-parents
|
||||
;; Any parent whose children are all deleted, must be deleted too.
|
||||
(into (d/ordered-set) (find-all-empty-parents #{}))
|
||||
empty-parents
|
||||
;; Any parent whose children are all deleted, must be deleted too.
|
||||
(into (d/ordered-set) (find-all-empty-parents #{}))
|
||||
|
||||
components-to-delete
|
||||
(if components-v2
|
||||
(reduce (fn [components id]
|
||||
(let [shape (get objects id)]
|
||||
(if (and (= (:component-file shape) file-id) ;; Main instances should exist only in local file
|
||||
(:main-instance? shape)) ;; but check anyway
|
||||
(conj components (:component-id shape))
|
||||
components)))
|
||||
[]
|
||||
(into ids all-children))
|
||||
[])
|
||||
components-to-delete
|
||||
(if components-v2
|
||||
(reduce (fn [components id]
|
||||
(let [shape (get objects id)]
|
||||
(if (and (= (:component-file shape) file-id) ;; Main instances should exist only in local file
|
||||
(:main-instance? shape)) ;; but check anyway
|
||||
(conj components (:component-id shape))
|
||||
components)))
|
||||
[]
|
||||
(into ids all-children))
|
||||
[])
|
||||
|
||||
changes (-> (pcb/empty-changes it page-id)
|
||||
(pcb/with-page page)
|
||||
(pcb/with-objects objects)
|
||||
(pcb/with-library-data file)
|
||||
(pcb/set-page-option :guides guides))
|
||||
changes (-> (pcb/empty-changes it page-id)
|
||||
(pcb/with-page page)
|
||||
(pcb/with-objects objects)
|
||||
(pcb/with-library-data file)
|
||||
(pcb/set-page-option :guides guides))
|
||||
|
||||
changes (reduce (fn [changes component-id]
|
||||
;; It's important to delete the component before the main instance, because we
|
||||
;; need to store the instance position if we want to restore it later.
|
||||
(pcb/delete-component changes component-id components-v2))
|
||||
changes
|
||||
components-to-delete)
|
||||
changes (reduce (fn [changes component-id]
|
||||
;; It's important to delete the component before the main instance, because we
|
||||
;; need to store the instance position if we want to restore it later.
|
||||
(pcb/delete-component changes component-id components-v2))
|
||||
changes
|
||||
components-to-delete)
|
||||
|
||||
changes (-> changes
|
||||
(pcb/remove-objects all-children)
|
||||
(pcb/remove-objects ids)
|
||||
(pcb/remove-objects empty-parents)
|
||||
(pcb/resize-parents all-parents)
|
||||
(pcb/update-shapes groups-to-unmask
|
||||
(fn [shape]
|
||||
(assoc shape :masked-group? false)))
|
||||
(pcb/update-shapes (map :id interacting-shapes)
|
||||
(fn [shape]
|
||||
(d/update-when shape :interactions
|
||||
(fn [interactions]
|
||||
(into []
|
||||
(remove #(and (ctsi/has-destination %)
|
||||
(contains? ids (:destination %))))
|
||||
interactions)))))
|
||||
(cond-> (seq starting-flows)
|
||||
(pcb/update-page-option :flows (fn [flows]
|
||||
(->> (map :id starting-flows)
|
||||
(reduce ctp/remove-flow flows))))))]
|
||||
changes (-> changes
|
||||
(pcb/remove-objects all-children)
|
||||
(pcb/remove-objects ids)
|
||||
(pcb/remove-objects empty-parents)
|
||||
(pcb/resize-parents all-parents)
|
||||
(pcb/update-shapes groups-to-unmask
|
||||
(fn [shape]
|
||||
(assoc shape :masked-group? false)))
|
||||
(pcb/update-shapes (map :id interacting-shapes)
|
||||
(fn [shape]
|
||||
(d/update-when shape :interactions
|
||||
(fn [interactions]
|
||||
(into []
|
||||
(remove #(and (ctsi/has-destination %)
|
||||
(contains? ids (:destination %))))
|
||||
interactions)))))
|
||||
(cond-> (seq starting-flows)
|
||||
(pcb/update-page-option :flows (fn [flows]
|
||||
(->> (map :id starting-flows)
|
||||
(reduce ctp/remove-flow flows))))))]
|
||||
|
||||
(rx/of (dc/detach-comment-thread ids)
|
||||
(dwsl/update-layout-positions all-parents)
|
||||
(dch/commit-changes changes))))))
|
||||
(rx/of (dc/detach-comment-thread ids)
|
||||
(dwsl/update-layout-positions all-parents)
|
||||
(dch/commit-changes changes)))))))
|
||||
|
||||
(defn- viewport-center
|
||||
[state]
|
||||
|
|
Loading…
Add table
Reference in a new issue