From c459c56f37e642edf93eba8fa63c214c96bc1a73 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 5 Jan 2023 15:43:27 +0100 Subject: [PATCH 1/6] :zap: Improved performance of snap to distances --- common/src/app/common/geom/shapes.cljc | 23 ++--- common/src/app/common/geom/shapes/rect.cljc | 16 ++-- frontend/src/app/main/snap.cljs | 83 +++++++++++-------- .../ui/workspace/viewport/snap_distances.cljs | 22 ++--- 4 files changed, 73 insertions(+), 71 deletions(-) diff --git a/common/src/app/common/geom/shapes.cljc b/common/src/app/common/geom/shapes.cljc index 0c2e9043a..732c2798c 100644 --- a/common/src/app/common/geom/shapes.cljc +++ b/common/src/app/common/geom/shapes.cljc @@ -82,24 +82,12 @@ (update :height (comp inc inc)))))) (defn selrect->areas [bounds selrect] - (let [make-selrect - (fn [x1 y1 x2 y2] - (let [x1 (min x1 x2) - x2 (max x1 x2) - y1 (min y1 y2) - y2 (max y1 y2)] - {:x1 x1 :y1 y1 - :x2 x2 :y2 y2 - :x x1 :y y1 - :width (- x2 x1) - :height (- y2 y1) - :type :rect})) - {bound-x1 :x1 bound-x2 :x2 bound-y1 :y1 bound-y2 :y2} bounds + (let [{bound-x1 :x1 bound-x2 :x2 bound-y1 :y1 bound-y2 :y2} bounds {sr-x1 :x1 sr-x2 :x2 sr-y1 :y1 sr-y2 :y2} selrect] - {:left (make-selrect bound-x1 sr-y1 sr-x1 sr-y2) - :top (make-selrect sr-x1 bound-y1 sr-x2 sr-y1) - :right (make-selrect sr-x2 sr-y1 bound-x2 sr-y2) - :bottom (make-selrect sr-x1 sr-y2 sr-x2 bound-y2)})) + {:left (gpr/corners->selrect bound-x1 sr-y1 sr-x1 sr-y2) + :top (gpr/corners->selrect sr-x1 bound-y1 sr-x2 sr-y1) + :right (gpr/corners->selrect sr-x2 sr-y1 bound-x2 sr-y2) + :bottom (gpr/corners->selrect sr-x1 sr-y2 sr-x2 bound-y2)})) (defn distance-selrect [selrect other] (let [{:keys [x1 y1]} other @@ -161,6 +149,7 @@ (dm/export gpr/contains-selrect?) (dm/export gpr/contains-point?) (dm/export gpr/close-selrect?) +(dm/export gpr/clip-selrect) (dm/export gtr/move) (dm/export gtr/absolute-move) diff --git a/common/src/app/common/geom/shapes/rect.cljc b/common/src/app/common/geom/shapes/rect.cljc index ca400800e..258ed0cd3 100644 --- a/common/src/app/common/geom/shapes/rect.cljc +++ b/common/src/app/common/geom/shapes/rect.cljc @@ -212,9 +212,13 @@ (<= (:y2 sr2) (:y2 sr1)))) (defn corners->selrect - [p1 p2] - (let [xp1 (:x p1) - xp2 (:x p2) - yp1 (:y p1) - yp2 (:y p2)] - (make-selrect (min xp1 xp2) (min yp1 yp2) (abs (- xp1 xp2)) (abs (- yp1 yp2))))) + ([p1 p2] + (corners->selrect (:x p1) (:y p1) (:x p2) (:y p2))) + ([xp1 yp1 xp2 yp2] + (make-selrect (min xp1 xp2) (min yp1 yp2) (abs (- xp1 xp2)) (abs (- yp1 yp2))))) + +(defn clip-selrect + [{:keys [x1 y1 x2 y2] :as sr} bounds] + (when (some? sr) + (let [{bx1 :x1 by1 :y1 bx2 :x2 by2 :y2} (rect->selrect bounds)] + (corners->selrect (max bx1 x1) (max by1 y1) (min bx2 x2) (min by2 y2))))) diff --git a/frontend/src/app/main/snap.cljs b/frontend/src/app/main/snap.cljs index 3a602ebf7..27480b0e8 100644 --- a/frontend/src/app/main/snap.cljs +++ b/frontend/src/app/main/snap.cljs @@ -144,17 +144,6 @@ dist-lt (fn [other] (sr-distance coord (:selrect other) selrect)) dist-gt (fn [other] (sr-distance coord selrect (:selrect other))) - ;; Calculates the snap distance when in the middle of two shapes - between-snap - (fn [[sh-lt sh-gt]] - ;; To calculate the middle snap. - ;; Given x, the distance to a left shape and y to a right shape - ;; x - v = y + v => v = (x - y)/2 - ;; v will be the vector that we need to move the shape so it "snaps" - ;; in the middle - (/ (- (dist-gt sh-gt) - (dist-lt sh-lt)) 2)) - ;; Calculates the distance between all the shapes given as argument inner-distance (fn [selrects] @@ -164,14 +153,6 @@ #(overlap? coord %1 %2) #{}))) - best-snap - (fn [acc val] - ;; Using a number is faster than accessing the variable. - ;; Keep up to date with `snap-distance-accuracy` - (if (and (<= val snap-distance-accuracy) (>= val (- snap-distance-accuracy))) - (min acc val) - acc)) - ;; Distance between the elements in an area, these are the snap ;; candidates to either side lt-cand (inner-distance (mapv :selrect shapes-lt)) @@ -182,17 +163,46 @@ lt-dist (into #{} (map dist-lt) shapes-lt) gt-dist (into #{} (map dist-gt) shapes-gt) - ;; Calculate the snaps, we need to reverse depending on area - lt-snap (d/join lt-cand lt-dist -) - gt-snap (d/join gt-dist gt-cand -) + get-side-snaps + (fn [candidates distances] + ;; We add to the range tree the distrances between elements + ;; then, for each distance from the selection we query the tree + ;; to find a snap + (let [range-tree (rt/make-tree) + range-tree + (->> candidates + (reduce #(rt/insert %1 %2 %2) range-tree))] + (->> distances + (mapcat + (fn [cd] + (->> (rt/range-query + range-tree + (- cd snap-distance-accuracy) + (+ cd snap-distance-accuracy)) + (map #(- (first %) cd )))))))) - ;; Calculate snap-between - between-snap (->> (d/join shapes-lt shapes-gt) - (map between-snap)) + get-middle-snaps + (fn [lt-dist gt-dist] + (let [range-tree (rt/make-tree) + range-tree (->> lt-dist + (reduce #(rt/insert %1 %2 %2) range-tree))] + (->> gt-dist + (mapcat (fn [cd] + (->> (rt/range-query + range-tree + (- cd (* snap-distance-accuracy 2)) + (+ cd (* snap-distance-accuracy 2))) + (map #(/ (- cd (first %)) 2)))))))) + + ;; Calculate the snaps, we need to reverse depending on area + lt-snap (get-side-snaps lt-cand lt-dist) + gt-snap (get-side-snaps gt-dist gt-cand) + md-snap (get-middle-snaps lt-dist gt-dist) ;; Search the minimum snap - snap-list (d/concat-vec lt-snap gt-snap between-snap) - min-snap (reduce best-snap ##Inf snap-list)] + snap-list (d/concat-vec lt-snap gt-snap md-snap) + + min-snap (reduce min ##Inf snap-list)] (if (d/num? min-snap) [0 min-snap] nil))) @@ -202,14 +212,14 @@ (calculate-snap coord selrect shapes-lt shapes-gt zoom))))) (defn select-shapes-area - [page-id shapes objects area-selrect] + [page-id frame-id selected objects area] (->> (uw/ask! {:cmd :selection/query :page-id page-id - :frame-id (->> shapes first :frame-id) + :frame-id frame-id :include-frames? true - :rect area-selrect}) + :rect area}) (rx/map #(cph/clean-loops objects %)) - (rx/map #(set/difference % (into #{} (map :id shapes)))) + (rx/map #(set/difference % selected)) (rx/map #(map (d/getf objects) %)))) (defn closest-distance-snap @@ -220,9 +230,14 @@ (->> (rx/of (vector frame selrect)) (rx/merge-map (fn [[frame selrect]] - (let [areas (->> (gsh/selrect->areas (or (:selrect frame) - (gsh/rect->selrect @refs/vbox)) selrect) - (d/mapm #(select-shapes-area page-id shapes objects %2))) + (let [vbox (gsh/rect->selrect @refs/vbox) + frame-id (->> shapes first :frame-id) + selected (into #{} (map :id shapes)) + areas (->> (gsh/selrect->areas + (or (gsh/clip-selrect (:selrect frame) vbox) + vbox) + selrect) + (d/mapm #(select-shapes-area page-id frame-id selected objects %2))) snap-x (search-snap-distance selrect :x (:left areas) (:right areas) zoom) snap-y (search-snap-distance selrect :y (:top areas) (:bottom areas) zoom)] (rx/combine-latest snap-x snap-y)))) diff --git a/frontend/src/app/main/ui/workspace/viewport/snap_distances.cljs b/frontend/src/app/main/ui/workspace/viewport/snap_distances.cljs index 7854fd8c8..9ae906cc5 100644 --- a/frontend/src/app/main/ui/workspace/viewport/snap_distances.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/snap_distances.cljs @@ -9,11 +9,10 @@ [app.common.data :as d] [app.common.geom.shapes :as gsh] [app.common.math :as mth] - [app.common.pages.helpers :as cph] [app.common.types.shape.layout :as ctl] [app.main.refs :as refs] + [app.main.snap :as ams] [app.main.ui.formats :as fmt] - [app.main.worker :as uw] [beicon.core :as rx] [clojure.set :as set] [cuerdas.core :as str] @@ -152,7 +151,7 @@ check-in-set (fn [value number-set] (->> number-set - (some #(<= (mth/abs (- value %)) 0.01)))) + (some #(<= (mth/abs (- value %)) 1.5)))) ;; Left/Top shapes and right/bottom shapes (depends on `coord` parameter) @@ -218,21 +217,16 @@ (fn [[selrect selected frame]] (let [lt-side (if (= coord :x) :left :top) gt-side (if (= coord :x) :right :bottom) - container-selrec (or (:selrect frame) - (gsh/rect->selrect @refs/vbox)) - areas (gsh/selrect->areas container-selrec selrect) + + vbox (gsh/rect->selrect @refs/vbox) + areas (gsh/selrect->areas + (or (gsh/clip-selrect (:selrect frame) vbox) vbox) + selrect) query-side (fn [side] (let [rect (get areas side)] (if (and (> (:width rect) 0) (> (:height rect) 0)) - (->> (uw/ask! {:cmd :selection/query - :page-id page-id - :frame-id (:id frame) - :include-frames? true - :rect rect}) - (rx/map #(cph/clean-loops @refs/workspace-page-objects %)) - (rx/map #(set/difference % selected)) - (rx/map #(->> % (map (partial get @refs/workspace-page-objects))))) + (ams/select-shapes-area page-id (:id frame) selected @refs/workspace-page-objects rect) (rx/of nil))))] (rx/combine-latest (query-side lt-side) (query-side gt-side)))) From 672cfa4eccf50f034ebfe72cba2a5be3eb24706f Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 5 Jan 2023 16:18:48 +0100 Subject: [PATCH 2/6] :bug: Fix problem when forcing persistence on screen change --- .../app/main/data/workspace/persistence.cljs | 105 +++++++++--------- 1 file changed, 53 insertions(+), 52 deletions(-) diff --git a/frontend/src/app/main/data/workspace/persistence.cljs b/frontend/src/app/main/data/workspace/persistence.cljs index c6f7d4479..e2f79a913 100644 --- a/frontend/src/app/main/data/workspace/persistence.cljs +++ b/frontend/src/app/main/data/workspace/persistence.cljs @@ -93,29 +93,32 @@ (->> (rx/from-atom commits) (rx/filter (complement empty?)) (rx/sample-when - (->> (rx/merge - (rx/interval 5000) - (rx/filter #(= ::force-persist %) stream) - (->> (rx/from-atom commits) - (rx/filter (complement empty?)) - (rx/debounce 2000))) - ;; Not sample while saving so there are no race conditions - (rx/filter #(not @saving?)))) + (rx/merge + (rx/filter #(= ::force-persist %) stream) + (->> (rx/merge + (rx/interval 5000) + (->> (rx/from-atom commits) + (rx/filter (complement empty?)) + (rx/debounce 2000))) + ;; Not sample while saving so there are no race conditions + (rx/filter #(not @saving?))))) (rx/tap #(reset! commits [])) (rx/tap on-saving) (rx/mapcat (fn [changes] ;; NOTE: this is needed for don't start the ;; next persistence before this one is ;; finished. - (rx/merge - (->> (rx/of (persist-changes file-id changes commits)) - (rx/observe-on :async)) - (->> stream - ;; We wait for every change to be persisted - (rx/filter (ptk/type? ::shapes-changes-persisted-finished)) - (rx/take 1) - (rx/tap on-saved) - (rx/ignore))))) + (if-let [file-revn (dm/get-in @st/state [:workspace-file :revn])] + (rx/merge + (->> (rx/of (persist-changes file-id file-revn changes commits)) + (rx/observe-on :async)) + (->> stream + ;; We wait for every change to be persisted + (rx/filter (ptk/type? ::shapes-changes-persisted-finished)) + (rx/take 1) + (rx/tap on-saved) + (rx/ignore))) + (rx/empty)))) (rx/take-until (rx/delay 100 stoper)) (rx/finalize (fn [] (log/debug :hint "finalize persistence: save loop")))) @@ -132,7 +135,7 @@ (log/debug :hint "finalize persistence: synchronous save loop"))))))))) (defn persist-changes - [file-id changes pending-commits] + [file-id file-revn changes pending-commits] (log/debug :hint "persist changes" :changes (count changes)) (us/verify ::us/uuid file-id) (ptk/reify ::persist-changes @@ -146,48 +149,46 @@ (features/active-feature? state :components-v2) (conj "components/v2")) sid (:session-id state) - file (get state :workspace-file) - params {:id (:id file) - :revn (:revn file) + params {:id file-id + :revn file-revn :session-id sid :changes-with-metadata (into [] changes) :features features}] - (when (= file-id (:id params)) - (->> (rp/cmd! :update-file params) - (rx/mapcat (fn [lagged] - (log/debug :hint "changes persisted" :lagged (count lagged)) - (let [frame-updates - (-> (group-by :page-id changes) - (update-vals #(into #{} (mapcat :frames) %))) + (->> (rp/cmd! :update-file params) + (rx/mapcat (fn [lagged] + (log/debug :hint "changes persisted" :lagged (count lagged)) + (let [frame-updates + (-> (group-by :page-id changes) + (update-vals #(into #{} (mapcat :frames) %))) - commits - (->> @pending-commits - (map #(assoc % :revn (:revn file))))] + commits + (->> @pending-commits + (map #(assoc % :revn file-revn)))] - (rx/concat - (rx/merge - (->> (rx/from frame-updates) - (rx/mapcat (fn [[page-id frames]] - (->> frames (map #(vector page-id %))))) - (rx/map (fn [[page-id frame-id]] (dwt/update-thumbnail (:id file) page-id frame-id)))) + (rx/concat + (rx/merge + (->> (rx/from frame-updates) + (rx/mapcat (fn [[page-id frames]] + (->> frames (map #(vector page-id %))))) + (rx/map (fn [[page-id frame-id]] (dwt/update-thumbnail file-id page-id frame-id)))) - (->> (rx/from (concat lagged commits)) - (rx/merge-map - (fn [{:keys [changes] :as entry}] - (rx/merge - (rx/from - (for [[page-id changes] (group-by :page-id changes)] - (dch/update-indices page-id changes))) - (rx/of (shapes-changes-persisted file-id entry))))))) + (->> (rx/from (concat lagged commits)) + (rx/merge-map + (fn [{:keys [changes] :as entry}] + (rx/merge + (rx/from + (for [[page-id changes] (group-by :page-id changes)] + (dch/update-indices page-id changes))) + (rx/of (shapes-changes-persisted file-id entry))))))) - (rx/of (shapes-changes-persisted-finished)))))) - (rx/catch (fn [cause] - (rx/concat - (if (= :authentication (:type cause)) - (rx/empty) - (rx/of (rt/assign-exception cause))) - (rx/throw cause)))))))))) + (rx/of (shapes-changes-persisted-finished)))))) + (rx/catch (fn [cause] + (rx/concat + (if (= :authentication (:type cause)) + (rx/empty) + (rx/of (rt/assign-exception cause))) + (rx/throw cause))))))))) ;; Event to be thrown after the changes have been persisted (defn shapes-changes-persisted-finished From c2e0b18f26cea5aa8bad3a7494e63eaf5ac46b87 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 9 Jan 2023 11:05:31 +0100 Subject: [PATCH 3/6] :bug: Fix problem with thumbnails uploading --- frontend/src/app/worker/thumbnails.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/worker/thumbnails.cljs b/frontend/src/app/worker/thumbnails.cljs index 4bb06f6c1..0ab917984 100644 --- a/frontend/src/app/worker/thumbnails.cljs +++ b/frontend/src/app/worker/thumbnails.cljs @@ -107,7 +107,7 @@ (->> (http/send! request) (rx/map http/conditional-decode-transit) (rx/mapcat handle-response) - (rx/catch body-too-large? (constantly nil)) + (rx/catch body-too-large? (constantly (rx/of nil))) (rx/map (constantly params))))) (defmethod impl/handler :thumbnails/generate From 1fdf09a692f2b52126d8692cc3646b99548421a4 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 9 Jan 2023 11:06:09 +0100 Subject: [PATCH 4/6] :bug: Fix problem with snap-pixel for very big shapes --- .../common/geom/shapes/pixel_precision.cljc | 3 +- common/src/app/common/types/modifiers.cljc | 28 +++++++++++-------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/common/src/app/common/geom/shapes/pixel_precision.cljc b/common/src/app/common/geom/shapes/pixel_precision.cljc index 211c26fd0..c1236046f 100644 --- a/common/src/app/common/geom/shapes/pixel_precision.cljc +++ b/common/src/app/common/geom/shapes/pixel_precision.cljc @@ -35,9 +35,8 @@ ratio-width (/ target-width curr-width) ratio-height (/ target-height curr-height) scalev (gpt/point ratio-width ratio-height)] - (-> modifiers - (ctm/resize scalev origin transform transform-inverse)))) + (ctm/resize scalev origin transform transform-inverse {:precise? true})))) (defn position-pixel-precision [modifiers _ points] diff --git a/common/src/app/common/types/modifiers.cljc b/common/src/app/common/types/modifiers.cljc index 72daab891..5d2764bb7 100644 --- a/common/src/app/common/types/modifiers.cljc +++ b/common/src/app/common/types/modifiers.cljc @@ -177,17 +177,19 @@ (defn- maybe-add-resize "Check the last operation to check if we can stack it over the last one" - [operations op] + ([operations op] + (maybe-add-resize operations op nil)) - (if (c/empty? operations) - [op] - (let [head (peek operations)] - (if (mergeable-resize? head op) - (let [item (merge-resize head op)] - (cond-> (pop operations) - (resize-vec? (dm/get-prop item :vector)) - (conj item))) - (conj operations op))))) + ([operations op {:keys [precise?]}] + (if (c/empty? operations) + [op] + (let [head (peek operations)] + (if (mergeable-resize? head op) + (let [item (merge-resize head op)] + (cond-> (pop operations) + (or precise? (resize-vec? (dm/get-prop item :vector))) + (conj item))) + (conj operations op)))))) (defn valid-vector? [vector] @@ -259,12 +261,16 @@ (update :geometry-child maybe-add-resize (resize-op order vector origin))))) ([modifiers vector origin transform transform-inverse] + (resize modifiers vector origin transform transform-inverse nil)) + + ;; `precise?` works so we don't remove almost empty resizes. This will be used in the pixel-precision + ([modifiers vector origin transform transform-inverse {:keys [precise?]}] (assert (valid-vector? vector) (dm/str "Invalid move vector: " (:x vector) "," (:y vector))) (let [modifiers (or modifiers (empty)) order (inc (dm/get-prop modifiers :last-order)) modifiers (assoc modifiers :last-order order)] (cond-> modifiers - (resize-vec? vector) + (or precise? (resize-vec? vector)) (update :geometry-child maybe-add-resize (resize-op order vector origin transform transform-inverse)))))) (defn rotation From c42ef7c5b0d43a940e0ee5fe0f8a806e015f5614 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 9 Jan 2023 11:54:50 +0100 Subject: [PATCH 5/6] :bug: Fix problem uploading svg with style tag --- CHANGES.md | 1 + frontend/src/app/main/ui/shapes/svg_raw.cljs | 2 +- frontend/src/app/main/ui/workspace/shapes.cljs | 12 ++++++++++-- frontend/src/app/util/svg.cljs | 2 +- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index dad802389..b05b7c1a6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -38,6 +38,7 @@ - Fix confirm group name with enter doesn't work in assets modal [Taiga #4506](https://tree.taiga.io/project/penpot/issue/4506) - Fix group/ungroup shapes inside a component [Taiga #4052](https://tree.taiga.io/project/penpot/issue/4052) - Fix wrong update of text in components [Taiga #4646](https://tree.taiga.io/project/penpot/issue/4646) +- Fix problem with SVG imports with style [#2605](https://github.com/penpot/penpot/issues/2605) ## 1.16.2-beta diff --git a/frontend/src/app/main/ui/shapes/svg_raw.cljs b/frontend/src/app/main/ui/shapes/svg_raw.cljs index 3c71526af..6a744745b 100644 --- a/frontend/src/app/main/ui/shapes/svg_raw.cljs +++ b/frontend/src/app/main/ui/shapes/svg_raw.cljs @@ -110,7 +110,7 @@ (for [item childs] [:& shape-wrapper {:shape item :key (dm/str (:id item))}])] - (and svg-leaf? valid-tag?) + svg-leaf? content :else nil)))) diff --git a/frontend/src/app/main/ui/workspace/shapes.cljs b/frontend/src/app/main/ui/workspace/shapes.cljs index 35148dc16..1bc7e29d0 100644 --- a/frontend/src/app/main/ui/workspace/shapes.cljs +++ b/frontend/src/app/main/ui/workspace/shapes.cljs @@ -98,9 +98,17 @@ (and (some? active-frames) (not (contains? active-frames (:id shape)))) - opts #js {:shape shape :thumbnail? thumbnail?}] + opts #js {:shape shape :thumbnail? thumbnail?} + + svg-leaf? (and (= :svg-raw (:type shape)) (string? (:content shape))) + + [wrapper wrapper-props] + (if svg-leaf? + [mf/Fragment nil] + ["g" #js {:className "workspace-shape-wrapper"}])] + (when (and (some? shape) (not (:hidden shape))) - [:g.workspace-shape-wrapper + [:> wrapper wrapper-props (case (:type shape) :path [:> path/path-wrapper opts] :text [:> text/text-wrapper opts] diff --git a/frontend/src/app/util/svg.cljs b/frontend/src/app/util/svg.cljs index 04b23ebf0..8a44d6450 100644 --- a/frontend/src/app/util/svg.cljs +++ b/frontend/src/app/util/svg.cljs @@ -21,7 +21,7 @@ (defonce matrices-regex #"(matrix|translate|scale|rotate|skewX|skewY)\(([^\)]*)\)") (defonce number-regex #"[+-]?\d*(\.\d+)?(e[+-]?\d+)?") -(defonce tags-to-remove #{:defs :linearGradient :radialGradient :metadata :mask :clipPath :filter :title}) +(defonce tags-to-remove #{:linearGradient :radialGradient :metadata :mask :clipPath :filter :title}) ;; https://www.w3.org/TR/SVG11/eltindex.html (defonce svg-tags-list From bedaef961b271bb68170592c77c35b6e0475614e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Mon, 9 Jan 2023 14:21:29 +0100 Subject: [PATCH 6/6] :bug: Fix ghost shapes after sync groups in components --- CHANGES.md | 1 + .../data/workspace/libraries_helpers.cljs | 42 ++++++++++--------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index b05b7c1a6..003089362 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -39,6 +39,7 @@ - Fix group/ungroup shapes inside a component [Taiga #4052](https://tree.taiga.io/project/penpot/issue/4052) - Fix wrong update of text in components [Taiga #4646](https://tree.taiga.io/project/penpot/issue/4646) - Fix problem with SVG imports with style [#2605](https://github.com/penpot/penpot/issues/2605) +- Fix ghost shapes after sync groups in components [Taiga #4649](https://tree.taiga.io/project/penpot/issue/4649) ## 1.16.2-beta diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index be91726d2..78c80455a 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -915,32 +915,36 @@ parents (cph/get-parent-ids objects (:id shape)) parent (first parents) children (cph/get-children-ids objects (:id shape)) + ids (into [(:id shape)] children) + + add-redo-change (fn [changes id] + (update changes :redo-changes conj + (make-change + container + {:type :del-obj + :id id + :ignore-touched true}))) add-undo-change (fn [changes id] (let [shape' (get objects id)] (update changes :undo-changes d/preconj (make-change - container - (as-> {:type :add-obj - :id id - :index (cph/get-position-on-parent objects id) - :parent-id (:parent-id shape') - :ignore-touched true - :obj shape'} $ - (cond-> $ - (:frame-id shape') - (assoc :frame-id (:frame-id shape')))))))) + container + (as-> {:type :add-obj + :id id + :index (cph/get-position-on-parent objects id) + :parent-id (:parent-id shape') + :ignore-touched true + :obj shape'} $ + (cond-> $ + (:frame-id shape') + (assoc :frame-id (:frame-id shape')))))))) - changes' (-> changes + changes' (-> (reduce add-redo-change changes ids) (update :redo-changes conj (make-change - container - {:type :del-obj - :id (:id shape) - :ignore-touched true})) - (update :redo-changes conj (make-change - container - {:type :reg-objects - :shapes (vec parents)})) + container + {:type :reg-objects + :shapes (vec parents)})) (add-undo-change (:id shape))) changes' (reduce add-undo-change