0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-04-01 01:21:21 -05:00

🎉 Duplicate shapes must create new flows if needed

This commit is contained in:
Andrés Moya 2022-02-18 14:31:55 +01:00
parent c626b1d106
commit 0035827209
3 changed files with 65 additions and 38 deletions

View file

@ -5,6 +5,9 @@
### :boom: Breaking changes ### :boom: Breaking changes
### :sparkles: New features ### :sparkles: New features
### :bug: Bugs fixed ### :bug: Bugs fixed
- Duplicate artboards create new flows if needed [Taiga #2221](https://tree.taiga.io/project/penpot/issue/2221)
### :arrow_up: Deps updates ### :arrow_up: Deps updates
### :heart: Community contributions by (Thank you!) ### :heart: Community contributions by (Thank you!)

View file

@ -1813,8 +1813,8 @@
;; Proceed with the standard shape paste process. ;; Proceed with the standard shape paste process.
(do-paste [it state mouse-pos media] (do-paste [it state mouse-pos media]
(let [page-objects (wsh/lookup-page-objects state) (let [page (wsh/lookup-page state)
media-idx (d/index-by :prev-id media) media-idx (d/index-by :prev-id media)
;; Calculate position for the pasted elements ;; Calculate position for the pasted elements
[frame-id parent-id delta index] (calculate-paste-position state mouse-pos in-viewport?) [frame-id parent-id delta index] (calculate-paste-position state mouse-pos in-viewport?)
@ -1835,10 +1835,9 @@
:shape-ref :shape-ref
:touched)))))) :touched))))))
all-objects (merge page-objects paste-objects) all-objects (merge (:objects page) paste-objects)
page-id (:current-page-id state) changes (-> (dws/prepare-duplicate-changes all-objects page selected delta it)
changes (-> (dws/prepare-duplicate-changes page-objects all-objects page-id selected delta it)
(pcb/amend-changes (partial process-rchange media-idx)) (pcb/amend-changes (partial process-rchange media-idx))
(pcb/amend-changes (partial change-add-obj-index paste-objects selected index))) (pcb/amend-changes (partial change-add-obj-index paste-objects selected index)))

View file

@ -14,6 +14,7 @@
[app.common.pages.helpers :as cph] [app.common.pages.helpers :as cph]
[app.common.spec :as us] [app.common.spec :as us]
[app.common.spec.interactions :as cti] [app.common.spec.interactions :as cti]
[app.common.spec.page :as ctp]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.main.data.modal :as md] [app.main.data.modal :as md]
[app.main.data.workspace.changes :as dch] [app.main.data.workspace.changes :as dch]
@ -264,31 +265,34 @@
(declare prepare-duplicate-change) (declare prepare-duplicate-change)
(declare prepare-duplicate-frame-change) (declare prepare-duplicate-frame-change)
(declare prepare-duplicate-shape-change) (declare prepare-duplicate-shape-change)
(declare prepare-duplicate-flows)
(defn prepare-duplicate-changes (defn prepare-duplicate-changes
"Prepare objects to duplicate: generate new id, give them unique names, "Prepare objects to duplicate: generate new id, give them unique names,
move to the desired position, and recalculate parents and frames as needed." move to the desired position, and recalculate parents and frames as needed."
[page-objects all-objects page-id ids delta it] [all-objects page ids delta it]
(let [unames (volatile! (dwc/retrieve-used-names page-objects)) (let [shapes (map (d/getf all-objects) ids)
unames (volatile! (dwc/retrieve-used-names (:objects page)))
update-unames! (fn [new-name] (vswap! unames conj new-name)) update-unames! (fn [new-name] (vswap! unames conj new-name))
all-ids (reduce #(into %1 (cons %2 (cph/get-children-ids all-objects %2))) #{} ids) all-ids (reduce #(into %1 (cons %2 (cph/get-children-ids all-objects %2))) #{} ids)
ids-map (into {} (map #(vector % (uuid/next))) all-ids)] ids-map (into {} (map #(vector % (uuid/next))) all-ids)]
(reduce (fn [changes id] (-> (reduce (fn [changes shape]
(prepare-duplicate-change changes all-objects page-id unames update-unames! ids-map id delta)) (prepare-duplicate-change changes all-objects page unames update-unames! ids-map shape delta))
(-> (pcb/empty-changes it page-id) (-> (pcb/empty-changes it)
(pcb/with-objects all-objects)) (pcb/with-page page)
ids))) (pcb/with-objects all-objects))
shapes)
(prepare-duplicate-flows shapes page ids-map))))
(defn- prepare-duplicate-change (defn- prepare-duplicate-change
[changes objects page-id unames update-unames! ids-map id delta] [changes objects page unames update-unames! ids-map shape delta]
(let [obj (get objects id)] (if (cph/frame-shape? shape)
(if (cph/frame-shape? obj) (prepare-duplicate-frame-change changes objects page unames update-unames! ids-map shape delta)
(prepare-duplicate-frame-change changes objects page-id unames update-unames! ids-map obj delta) (prepare-duplicate-shape-change changes objects page unames update-unames! ids-map shape delta (:frame-id shape) (:parent-id shape))))
(prepare-duplicate-shape-change changes objects page-id unames update-unames! ids-map obj delta (:frame-id obj) (:parent-id obj)))))
(defn- prepare-duplicate-frame-change (defn- prepare-duplicate-frame-change
[changes objects page-id unames update-unames! ids-map obj delta] [changes objects page unames update-unames! ids-map obj delta]
(let [new-id (ids-map (:id obj)) (let [new-id (ids-map (:id obj))
frame-name (dwc/generate-unique-name @unames (:name obj)) frame-name (dwc/generate-unique-name @unames (:name obj))
_ (update-unames! frame-name) _ (update-unames! frame-name)
@ -306,7 +310,7 @@
changes (reduce (fn [changes child] changes (reduce (fn [changes child]
(prepare-duplicate-shape-change changes (prepare-duplicate-shape-change changes
objects objects
page-id page
unames unames
update-unames! update-unames!
ids-map ids-map
@ -319,7 +323,7 @@
changes)) changes))
(defn- prepare-duplicate-shape-change (defn- prepare-duplicate-shape-change
[changes objects page-id unames update-unames! ids-map obj delta frame-id parent-id] [changes objects page unames update-unames! ids-map obj delta frame-id parent-id]
(if (some? obj) (if (some? obj)
(let [new-id (ids-map (:id obj)) (let [new-id (ids-map (:id obj))
parent-id (or parent-id frame-id) parent-id (or parent-id frame-id)
@ -337,21 +341,42 @@
changes (pcb/add-obj changes new-obj {:ignore-touched true}) changes (pcb/add-obj changes new-obj {:ignore-touched true})
changes (-> (pcb/add-obj changes new-obj {:ignore-touched true}) changes (-> (pcb/add-obj changes new-obj {:ignore-touched true})
(pcb/amend-last-change #(assoc % :old-id (:id obj)))) (pcb/amend-last-change #(assoc % :old-id (:id obj))))]
changes (reduce (fn [changes child] (reduce (fn [changes child]
(prepare-duplicate-shape-change changes (prepare-duplicate-shape-change changes
objects objects
page-id page
unames unames
update-unames! update-unames!
ids-map ids-map
child child
delta delta
frame-id frame-id
new-id)) new-id))
changes changes
(map (d/getf objects) (:shapes obj)))] (map (d/getf objects) (:shapes obj))))
changes))
(defn- prepare-duplicate-flows
[changes shapes page ids-map]
(let [flows (-> page :options :flows)
unames (volatile! (into #{} (map :name flows)))
frames-with-flow (->> shapes
(filter #(= (:type %) :frame))
(filter #(some? (ctp/get-frame-flow flows (:id %)))))]
(if-not (empty? frames-with-flow)
(let [new-flows (reduce
(fn [flows frame]
(let [name (dwc/generate-unique-name @unames "Flow-1")
_ (vswap! unames conj name)
new-flow {:id (uuid/next)
:name name
:starting-frame (get ids-map (:id frame))}]
(ctp/add-flow flows new-flow)))
flows
frames-with-flow)]
(pcb/set-page-option changes :flows new-flows))
changes))) changes)))
(defn duplicate-changes-update-indices (defn duplicate-changes-update-indices
@ -437,15 +462,15 @@
ptk/WatchEvent ptk/WatchEvent
(watch [it state _] (watch [it state _]
(when (or (not move-delta?) (nil? (get-in state [:workspace-local :transform]))) (when (or (not move-delta?) (nil? (get-in state [:workspace-local :transform])))
(let [page-id (:current-page-id state) (let [page (wsh/lookup-page state)
objects (wsh/lookup-page-objects state page-id) objects (:objects page)
selected (wsh/lookup-selected state) selected (wsh/lookup-selected state)
delta (if (and move-delta? (= (count selected) 1)) delta (if (and move-delta? (= (count selected) 1))
(let [obj (get objects (first selected))] (let [obj (get objects (first selected))]
(calc-duplicate-delta obj state objects)) (calc-duplicate-delta obj state objects))
(gpt/point 0 0)) (gpt/point 0 0))
changes (->> (prepare-duplicate-changes objects objects page-id selected delta it) changes (->> (prepare-duplicate-changes objects page selected delta it)
(duplicate-changes-update-indices objects selected)) (duplicate-changes-update-indices objects selected))
id-original (when (= (count selected) 1) (first selected)) id-original (when (= (count selected) 1) (first selected))