0
Fork 0
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:
Pablo Alba 2022-10-04 11:47:28 +02:00 committed by GitHub
commit 5bbfe376cf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 166 additions and 146 deletions

View file

@ -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)

View file

@ -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

View file

@ -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]