From 7efeeec9b16f2f51c62b937bef1afcae075e5279 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 1 Aug 2023 17:37:55 +0200 Subject: [PATCH 1/2] :sparkles: Add workspace initialization fix for broken shape references Is the code that executes at workspace initialization that checks all the shape children for broken references and proceed to emit a special event that fixes the shape children references. --- common/src/app/common/pages/changes.cljc | 15 +++++++- common/src/app/common/types/shape_tree.cljc | 19 +++++++--- frontend/src/app/main/data/workspace.cljs | 7 +++- .../workspace/fix_broken_shape_links.cljs | 38 +++++++++++++++++++ 4 files changed, 71 insertions(+), 8 deletions(-) create mode 100644 frontend/src/app/main/data/workspace/fix_broken_shape_links.cljs diff --git a/common/src/app/common/pages/changes.cljc b/common/src/app/common/pages/changes.cljc index 97be5e91b..c11649854 100644 --- a/common/src/app/common/pages/changes.cljc +++ b/common/src/app/common/pages/changes.cljc @@ -93,6 +93,13 @@ [:component-id {:optional true} ::sm/uuid] [:ignore-touched {:optional true} :boolean]]] + [:fix-obj + [:map {:title "FixObjChange"} + [:type [:= :fix-obj]] + [:id ::sm/uuid] + [:page-id {:optional true} ::sm/uuid] + [:component-id {:optional true} ::sm/uuid]]] + [:mov-objects [:map {:title "MovObjectsChange"} [:type [:= :mov-objects]] @@ -218,7 +225,7 @@ (sm/def! ::changes [:sequential {:gen/max 2} ::change]) - + (def change? (sm/pred-fn ::change)) @@ -337,6 +344,12 @@ (d/update-in-when data [:pages-index page-id] ctst/delete-shape id ignore-touched) (d/update-in-when data [:components component-id] ctst/delete-shape id ignore-touched))) +(defmethod process-change :fix-obj + [data {:keys [page-id component-id] :as params}] + (if page-id + (d/update-in-when data [:pages-index page-id] ctst/fix-shape-children params) + (d/update-in-when data [:components component-id] ctst/fix-shape-children params))) + ;; FIXME: remove, seems like this method is already unused ;; reg-objects operation "regenerates" the geometry and selrect of the parent groups (defmethod process-change :reg-objects diff --git a/common/src/app/common/types/shape_tree.cljc b/common/src/app/common/types/shape_tree.cljc index f84db3e4d..b872bd73c 100644 --- a/common/src/app/common/types/shape_tree.cljc +++ b/common/src/app/common/types/shape_tree.cljc @@ -90,16 +90,24 @@ (delete-from-objects [objects] (if-let [target (get objects shape-id)] - (let [parent-id (or (:parent-id target) - (:frame-id target)) - children-ids (cph/get-children-ids objects shape-id)] - (-> (reduce dissoc objects children-ids) - (dissoc shape-id) + (let [parent-id (or (:parent-id target) + (:frame-id target)) + children-ids (cph/get-children-ids objects shape-id)] + (-> (reduce dissoc objects (cons shape-id children-ids)) (d/update-when parent-id delete-from-parent))) objects))] (update container :objects delete-from-objects)))) +(defn fix-shape-children + "Checks and fix the children relations of the shape. If a children does not + exists on the objects tree, it will be removed from shape." + [{:keys [objects] :as container} {:keys [id] :as params}] + (let [contains? (partial contains? objects)] + (d/update-in-when container [:objects id :shapes] + (fn [shapes] + (into [] (filter contains?) shapes))))) + (defn get-frames "Retrieves all frame objects as vector" ([objects] (get-frames objects nil)) @@ -350,6 +358,7 @@ (some? force-id) force-id keep-ids? (:id object) :else (uuid/next))] + (loop [child-ids (seq (:shapes object)) new-direct-children [] new-children [] diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 95a975fb3..7d744a65b 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -44,6 +44,7 @@ [app.main.data.workspace.drawing.common :as dwdc] [app.main.data.workspace.edition :as dwe] [app.main.data.workspace.fix-bool-contents :as fbc] + [app.main.data.workspace.fix-broken-shape-links :as fbs] [app.main.data.workspace.fix-deleted-fonts :as fdf] [app.main.data.workspace.groups :as dwg] [app.main.data.workspace.guides :as dwgu] @@ -130,8 +131,10 @@ has-graphics? (-> file :media seq) components-v2 (features/active-feature? state :components-v2)] (rx/merge - (rx/of (fbc/fix-bool-contents)) - (rx/of (fdf/fix-deleted-fonts)) + (rx/of (fbc/fix-bool-contents) + (fdf/fix-deleted-fonts) + (fbs/fix-broken-shapes)) + (if (and has-graphics? components-v2) (rx/of (remove-graphics (:id file) (:name file))) (rx/empty))))))) diff --git a/frontend/src/app/main/data/workspace/fix_broken_shape_links.cljs b/frontend/src/app/main/data/workspace/fix_broken_shape_links.cljs new file mode 100644 index 000000000..2866d9741 --- /dev/null +++ b/frontend/src/app/main/data/workspace/fix_broken_shape_links.cljs @@ -0,0 +1,38 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) KALEIDOS INC + +(ns app.main.data.workspace.fix-broken-shape-links + (:require + [app.main.data.workspace.changes :as dch] + [beicon.core :as rx] + [potok.core :as ptk])) + +(defn- generate-changes + [attr {:keys [objects id]}] + (let [base {:type :fix-obj attr id} + contains? (partial contains? objects) + xform (comp + (remove #(every? contains? (:shapes %))) + (map #(assoc base :id (:id %))))] + (sequence xform (vals objects)))) + +(defn fix-broken-shapes + [] + (ptk/reify ::fix-broken-shape-links + ptk/WatchEvent + (watch [it state _] + (let [data (get state :workspace-data) + changes (concat + (mapcat (partial generate-changes :page-id) + (vals (:pages-index data))) + (mapcat (partial generate-changes :component-id) + (vals (:components data))))] + + (rx/of (dch/commit-changes + {:origin it + :redo-changes (vec changes) + :undo-changes [] + :save-undo? false})))))) From 3eb25694652d2fb8e73240327e65a43f76fac400 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 1 Aug 2023 17:40:23 +0200 Subject: [PATCH 2/2] :sparkles: Add better exception reporting on commit-changes --- frontend/src/app/main/data/workspace/changes.cljs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/main/data/workspace/changes.cljs b/frontend/src/app/main/data/workspace/changes.cljs index 166538860..ceaef9e4b 100644 --- a/frontend/src/app/main/data/workspace/changes.cljs +++ b/frontend/src/app/main/data/workspace/changes.cljs @@ -8,6 +8,7 @@ (:require [app.common.data :as d] [app.common.data.macros :as dm] + [app.common.exceptions :as ex] [app.common.logging :as log] [app.common.pages :as cp] [app.common.pages.changes :as cpc] @@ -205,6 +206,7 @@ path (if (= file-id current-file-id) [:workspace-data] [:workspace-libraries file-id :data])] + (try (dm/assert! "expect valid vector of changes" @@ -217,7 +219,11 @@ (ctst/update-object-indices page-id)))) (catch :default err - (log/error :js/error err) + (when-let [data (ex-data err)] + (js/console.log (ex/explain data))) + + (when (ex/error? err) + (js/console.log (.-stack ^js err))) (vreset! error err) state))))