From 798970a9239d9accc8010a6bb47b1627e93dc1ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Fri, 21 Jun 2024 18:45:00 +0200 Subject: [PATCH] :bug: Rework svg import of deleted components --- common/src/app/common/files/builder.cljc | 85 +++++++++++++----------- frontend/src/app/main/render.cljs | 15 +++-- frontend/src/app/worker/import.cljs | 53 +++++++++------ 3 files changed, 88 insertions(+), 65 deletions(-) diff --git a/common/src/app/common/files/builder.cljc b/common/src/app/common/files/builder.cljc index 8605a5e1f..988164c20 100644 --- a/common/src/app/common/files/builder.cljc +++ b/common/src/app/common/files/builder.cljc @@ -41,16 +41,19 @@ (let [components-v2 (dm/get-in file [:data :options :components-v2]) component-id (:current-component-id file) change (cond-> change - (and add-container? (some? component-id)) + (and add-container? (some? component-id) (not components-v2)) (-> (assoc :component-id component-id) (cond-> (some? (:current-frame-id file)) (assoc :frame-id (:current-frame-id file)))) - (and add-container? (nil? component-id)) + (and add-container? (or (nil? component-id) components-v2)) (assoc :page-id (:current-page-id file) :frame-id (:current-frame-id file))) - valid? (ch/check-change! change)] + valid? (or (and components-v2 + (nil? (:component-id change)) + (nil? (:page-id change))) + (ch/check-change! change))] (when-not valid? (let [explain (sm/explain ::ch/change change)] @@ -62,7 +65,7 @@ ::sm/explain explain)))) (cond-> file - (and valid? (not (and components-v2 add-container? (some? component-id)))) + (and valid? (or (not add-container?) (some? (:component-id change)) (some? (:page-id change)))) (-> (update :changes conjv change) ;; In components-v2 we do not add shapes (update :data ch/process-changes [change] false)) ;; inside a component @@ -524,6 +527,11 @@ path (:path data) main-instance-id (:main-instance-id data) main-instance-page (:main-instance-page data) + + ;; In components v1 we must create the root shape and set it inside + ;; the :objects attribute of the component. When in components-v2, + ;; this will be ignored as the root shape has already been created + ;; in its page, by the normal page import. attrs (-> data (assoc :type root-type) (assoc :x (:x selrect)) @@ -559,6 +567,29 @@ (assoc :current-component-id (:id obj)) (assoc :current-frame-id (if (= (:type obj) :frame) (:id obj) uuid/zero)))))) +(defn start-deleted-component + [file data] + (let [attrs (-> data + (assoc :id (:main-instance-id data)) + (assoc :component-file (:id file)) + (assoc :component-id (:id data)) + (assoc :x (:main-instance-x data)) + (assoc :y (:main-instance-y data)) + (dissoc :path) + (dissoc :main-instance-id) + (dissoc :main-instance-page) + (dissoc :main-instance-x) + (dissoc :main-instance-y) + (dissoc :main-instance-parent) + (dissoc :main-instance-frame))] + ;; To create a deleted component, first we add all shapes of the main instance + ;; in the main instance page, and in the finish event we delete it. + (-> file + (update :parent-stack conjv (:main-instance-parent data)) + (assoc :current-page-id (:main-instance-page data)) + (assoc :current-frame-id (:main-instance-frame data)) + (add-artboard attrs)))) + (defn finish-component [file] (let [component-id (:current-component-id file) @@ -623,43 +654,18 @@ (update :parent-stack pop)))) (defn finish-deleted-component - [component-id page-id main-instance-x main-instance-y file] + [component-id file] (let [file (assoc file :current-component-id component-id) - page (ctpl/get-page (:data file) page-id) - component (ctkl/get-component (:data file) component-id) - main-instance-id (:main-instance-id component) - - ; To obtain a deleted component, we first create the component - ; and the main instance in the workspace, and then delete them. - [_ shapes] - (ctn/make-component-instance page - component - (:data file) - (gpt/point main-instance-x - main-instance-y) - true - {:main-instance true - :force-id main-instance-id})] - (as-> file $ - (reduce #(commit-change %1 - {:type :add-obj - :id (:id %2) - :page-id (:id page) - :parent-id (:parent-id %2) - :frame-id (:frame-id %2) - :ignore-touched true - :obj %2}) - $ - shapes) - (commit-change $ {:type :del-component + component (ctkl/get-component (:data file) component-id)] + (-> file + (close-artboard) + (commit-change {:type :del-component :id component-id}) - (reduce #(commit-change %1 {:type :del-obj - :page-id page-id - :ignore-touched true - :id (:id %2)}) - $ - shapes) - (dissoc $ :current-component-id)))) + (commit-change {:type :del-obj + :page-id (:main-instance-page component) + :id (:main-instance-id component) + :ignore-touched true}) + (dissoc :current-page-id)))) (defn create-component-instance [file data] @@ -670,7 +676,6 @@ page-id (:current-page-id file) page (ctpl/get-page (:data file) page-id) component (ctkl/get-component (:data file) component-id) - ;; main-instance-id (:main-instance-id component) components-v2 (dm/get-in file [:options :components-v2]) diff --git a/frontend/src/app/main/render.cljs b/frontend/src/app/main/render.cljs index 4cec0c71c..a371a67d3 100644 --- a/frontend/src/app/main/render.cljs +++ b/frontend/src/app/main/render.cljs @@ -485,15 +485,18 @@ path (:path component) root-id (or (:main-instance-id component) (:id component)) + orig-root (get (:objects component) root-id) objects (adapt-objects-for-shape (:objects component) root-id) root-shape (get objects root-id) selrect (:selrect root-shape) - main-instance-id (:main-instance-id component) - main-instance-page (:main-instance-page component) - main-instance-x (:main-instance-x component) - main-instance-y (:main-instance-y component) + main-instance-id (:main-instance-id component) + main-instance-page (:main-instance-page component) + main-instance-x (when (:deleted component) (:x orig-root)) + main-instance-y (when (:deleted component) (:y orig-root)) + main-instance-parent (when (:deleted component) (:parent-id orig-root)) + main-instance-frame (when (:deleted component) (:frame-id orig-root)) vbox (format-viewbox @@ -517,7 +520,9 @@ "penpot:main-instance-id" main-instance-id "penpot:main-instance-page" main-instance-page "penpot:main-instance-x" main-instance-x - "penpot:main-instance-y" main-instance-y} + "penpot:main-instance-y" main-instance-y + "penpot:main-instance-parent" main-instance-parent + "penpot:main-instance-frame" main-instance-frame} [:title name] [:> shape-container {:shape root-shape} (case (:type root-shape) diff --git a/frontend/src/app/worker/import.cljs b/frontend/src/app/worker/import.cljs index 901b3edcd..186de184d 100644 --- a/frontend/src/app/worker/import.cljs +++ b/frontend/src/app/worker/import.cljs @@ -253,6 +253,7 @@ frame (when (and (some? frame-id) (not= frame-id uuid/zero)) (fb/lookup-shape file frame-id))] + (js/console.log " translate-frame" (clj->js frame)) (if (some? frame) (-> data (d/update-when :x + (:x frame)) @@ -283,7 +284,13 @@ (cond-> (some? old-id) (assoc :id (resolve old-id))) (cond-> (< (:version context 1) 2) - (translate-frame type file)))] + (translate-frame type file)) + ;; Shapes inside the deleted component should be stored with absolute coordinates + ;; so we calculate that with the x and y stored in the context + (cond-> (:x context) + (assoc :x (:x context))) + (cond-> (:y context) + (assoc :y (:y context))))] (try (let [file (case type :frame (fb/add-artboard file data) @@ -455,17 +462,19 @@ (rx/map fb/finish-component)))) (defn import-deleted-component [context file node] - (let [resolve (:resolve context) - content (parser/find-node node :g) - file-id (:id file) - old-id (parser/get-id node) - id (resolve old-id) - path (get-in node [:attrs :penpot:path] "") - main-instance-id (resolve (uuid (get-in node [:attrs :penpot:main-instance-id] ""))) - main-instance-page (resolve (uuid (get-in node [:attrs :penpot:main-instance-page] ""))) - main-instance-x (get-in node [:attrs :penpot:main-instance-x] "") - main-instance-y (get-in node [:attrs :penpot:main-instance-y] "") - type (parser/get-type content) + (let [resolve (:resolve context) + content (parser/find-node node :g) + file-id (:id file) + old-id (parser/get-id node) + id (resolve old-id) + path (get-in node [:attrs :penpot:path] "") + main-instance-id (resolve (uuid (get-in node [:attrs :penpot:main-instance-id] ""))) + main-instance-page (resolve (uuid (get-in node [:attrs :penpot:main-instance-page] ""))) + main-instance-x (-> (get-in node [:attrs :penpot:main-instance-x] "") (d/parse-double)) + main-instance-y (-> (get-in node [:attrs :penpot:main-instance-y] "") (d/parse-double)) + main-instance-parent (resolve (uuid (get-in node [:attrs :penpot:main-instance-parent] ""))) + main-instance-frame (resolve (uuid (get-in node [:attrs :penpot:main-instance-frame] ""))) + type (parser/get-type content) data (-> (parser/parse-data type content) (assoc :path path) @@ -473,12 +482,20 @@ (assoc :main-instance-id main-instance-id) (assoc :main-instance-page main-instance-page) (assoc :main-instance-x main-instance-x) - (assoc :main-instance-y main-instance-y)) + (assoc :main-instance-y main-instance-y) + (assoc :main-instance-parent main-instance-parent) + (assoc :main-instance-frame main-instance-frame)) - file (-> file (fb/start-component data)) + file (-> file + (fb/start-component data) + (fb/start-deleted-component data)) component-id (:current-component-id file) - children (parser/node-seq node)] + children (parser/node-seq node) + ;; Shapes inside the deleted component should be stored with absolute coordinates so we include this info in the context. + context (-> context + (assoc :x main-instance-x) + (assoc :y main-instance-y))] (->> (rx/from children) (rx/filter parser/shape?) (rx/skip 1) @@ -486,11 +503,7 @@ (rx/mapcat (partial resolve-media context file-id)) (rx/reduce (partial process-import-node context) file) (rx/map fb/finish-component) - (rx/map (partial fb/finish-deleted-component - component-id - main-instance-page - main-instance-x - main-instance-y))))) + (rx/map (partial fb/finish-deleted-component component-id))))) (defn process-pages [context file]