diff --git a/common/src/app/common/files/repair.cljc b/common/src/app/common/files/repair.cljc index f682a4a0f..a88b33a3c 100644 --- a/common/src/app/common/files/repair.cljc +++ b/common/src/app/common/files/repair.cljc @@ -15,6 +15,7 @@ [app.common.types.container :as ctn] [app.common.types.file :as ctf] [app.common.types.pages-list :as ctpl] + [app.common.types.shape :as cts] [app.common.uuid :as uuid])) (log/set-level! :debug) @@ -22,6 +23,23 @@ (defmulti repair-error (fn [code _error _file-data _libraries] code)) +(defmethod repair-error :invalid-geometry + [_ {:keys [shape page-id] :as error} file-data _] + (let [repair-shape + (fn [shape] + ; Reset geometry to minimal + (log/debug :hint " -> Reset geometry") + (-> shape + (assoc :x 0) + (assoc :y 0) + (assoc :width 0.01) + (assoc :height 0.01) + (cts/setup-rect)))] + (log/info :hint "Repairing shape :invalid-geometry" :id (:id shape) :name (:name shape) :page-id page-id) + (-> (pcb/empty-changes nil page-id) + (pcb/with-file-data file-data) + (pcb/update-shapes [(:id shape)] repair-shape)))) + (defmethod repair-error :parent-not-found [_ {:keys [shape page-id] :as error} file-data _] (let [repair-shape @@ -140,15 +158,28 @@ (defmethod repair-error :invalid-main-instance-id [_ {:keys [shape page-id] :as error} file-data _] - (let [repair-component + (let [component (ctkl/get-component file-data (:component-id shape)) + + repair-component (fn [component] ; Assign main instance in the component to current shape (log/debug :hint " -> Assign main-instance-id" :component-id (:id component)) - (assoc component :main-instance-id (:id shape)))] + (assoc component :main-instance-id (:id shape))) + + detach-shape + (fn [shape] + (log/debug :hint " -> Detach shape" :shape-id (:id shape)) + (ctk/detach-shape shape))] + (log/info :hint "Repairing shape :invalid-main-instance-id" :id (:id shape) :name (:name shape) :page-id page-id) - (-> (pcb/empty-changes nil page-id) - (pcb/with-library-data file-data) - (pcb/update-component [(:component-id shape)] repair-component)))) + (if (and (some? component) (not (:deleted component))) + (-> (pcb/empty-changes nil page-id) + (pcb/with-library-data file-data) + (pcb/update-component (:component-id shape) repair-component)) + + (-> (pcb/empty-changes nil page-id) + (pcb/with-file-data file-data) + (pcb/update-shapes [(:id shape)] detach-shape))))) (defmethod repair-error :invalid-main-instance-page [_ {:keys [shape page-id] :as error} file-data _] diff --git a/common/src/app/common/files/validate.cljc b/common/src/app/common/files/validate.cljc index fd5f7db27..4200a30a9 100644 --- a/common/src/app/common/files/validate.cljc +++ b/common/src/app/common/files/validate.cljc @@ -23,7 +23,8 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (def error-codes - #{:parent-not-found + #{:invalid-geometry + :parent-not-found :child-not-in-parent :child-not-found :frame-not-found @@ -87,6 +88,20 @@ (declare validate-shape) +(defn validate-geometry + "Validate that the shape has valid coordinates, selrect and points." + [shape file page] + (when (and (not= (:type shape) :path) + (or (nil? (:x shape)) ; This may occur in root shape (uuid/zero) in old files + (nil? (:y shape)) + (nil? (:width shape)) + (nil? (:height shape)) + (nil? (:selrect shape)) + (nil? (:points shape)))) + (report-error :invalid-geometry + (str/format "Shape greometry is invalid") + shape file page))) + (defn validate-parent-children "Validate parent and children exists, and the link is bidirectional." [shape file page] @@ -314,6 +329,7 @@ ; If this happens it's a bug in this validate functions (dm/verify! (str/format "Shape %s not found" shape-id) (some? shape)) + (validate-geometry shape file page) (validate-parent-children shape file page) (validate-frame shape file page) diff --git a/common/src/app/common/pages/changes_builder.cljc b/common/src/app/common/pages/changes_builder.cljc index ba4f9aecd..a40dc9a4d 100644 --- a/common/src/app/common/pages/changes_builder.cljc +++ b/common/src/app/common/pages/changes_builder.cljc @@ -714,7 +714,7 @@ (let [library-data (::library-data (meta changes)) prev-component (get-in library-data [:components id]) new-component (update-fn prev-component)] - (if new-component + (if prev-component (-> changes (update :redo-changes conj {:type :mod-component :id id