From 0b4fbc184deb1ba7afc5ddb689acbb08c6a87202 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Mon, 6 May 2024 16:45:43 +0200 Subject: [PATCH] :recycle: Move generate-xx methods to logic module --- backend/src/app/features/components_v2.clj | 18 +- .../libraries.cljc} | 514 +---------------- common/src/app/common/logic/shapes.cljc | 519 ++++++++++++++++++ common/test/common_tests/helpers/files.cljc | 4 +- .../logic/comp_remove_swap_slots_test.cljc | 170 +++--- .../logic/component_creation_test.cljc | 18 +- .../logic/components_touched_test.cljc | 53 +- .../logic/swap_and_reset_test.cljc | 76 ++- frontend/src/app/main/data/workspace.cljs | 16 +- .../src/app/main/data/workspace/changes.cljs | 16 +- .../app/main/data/workspace/libraries.cljs | 47 +- .../app/main/data/workspace/selection.cljs | 28 +- .../src/app/main/data/workspace/shapes.cljs | 10 +- .../app/main/data/workspace/transforms.cljs | 4 +- .../test/frontend_tests/helpers/pages.cljs | 32 +- 15 files changed, 769 insertions(+), 756 deletions(-) rename common/src/app/common/{files/libraries_helpers.cljc => logic/libraries.cljc} (79%) create mode 100644 common/src/app/common/logic/shapes.cljc diff --git a/backend/src/app/features/components_v2.clj b/backend/src/app/features/components_v2.clj index 452b83bc5..47dc3fad0 100644 --- a/backend/src/app/features/components_v2.clj +++ b/backend/src/app/features/components_v2.clj @@ -12,7 +12,6 @@ [app.common.files.changes :as cp] [app.common.files.changes-builder :as fcb] [app.common.files.helpers :as cfh] - [app.common.files.libraries-helpers :as cflh] [app.common.files.migrations :as fmg] [app.common.files.shapes-helpers :as cfsh] [app.common.files.validate :as cfv] @@ -23,6 +22,7 @@ [app.common.geom.shapes :as gsh] [app.common.geom.shapes.path :as gshp] [app.common.logging :as l] + [app.common.logic.libraries :as cll] [app.common.math :as mth] [app.common.schema :as sm] [app.common.svg :as csvg] @@ -1451,14 +1451,14 @@ (cons shape children)) [_ _ changes] - (cflh/generate-add-component changes - [shape] - (:objects page) - (:id page) - file-id - true - nil - cfsh/prepare-create-artboard-from-selection)] + (cll/generate-add-component changes + [shape] + (:objects page) + (:id page) + file-id + true + nil + cfsh/prepare-create-artboard-from-selection)] (shape-cb shape) (:redo-changes changes))) diff --git a/common/src/app/common/files/libraries_helpers.cljc b/common/src/app/common/logic/libraries.cljc similarity index 79% rename from common/src/app/common/files/libraries_helpers.cljc rename to common/src/app/common/logic/libraries.cljc index 6df368eb6..458bcb2ec 100644 --- a/common/src/app/common/files/libraries_helpers.cljc +++ b/common/src/app/common/logic/libraries.cljc @@ -4,7 +4,7 @@ ;; ;; Copyright (c) KALEIDOS INC -(ns app.common.files.libraries-helpers +(ns app.common.logic.libraries (:require [app.common.data :as d] [app.common.data.macros :as dm] @@ -14,6 +14,7 @@ [app.common.geom.shapes :as gsh] [app.common.geom.shapes.grid-layout :as gslg] [app.common.logging :as log] + [app.common.logic.shapes :as cls] [app.common.spec :as us] [app.common.text :as txt] [app.common.types.color :as ctc] @@ -21,10 +22,8 @@ [app.common.types.components-list :as ctkl] [app.common.types.container :as ctn] [app.common.types.file :as ctf] - [app.common.types.page :as ctp] [app.common.types.pages-list :as ctpl] [app.common.types.shape-tree :as ctst] - [app.common.types.shape.interactions :as ctsi] [app.common.types.shape.layout :as ctl] [app.common.types.typography :as cty] [app.common.uuid :as uuid] @@ -34,23 +33,6 @@ ;; Change this to :info :debug or :trace to debug this module, or :warn to reset to default (log/set-level! :warn) -(defn generate-update-shapes - [changes ids update-fn objects {:keys [attrs ignore-tree ignore-touched with-objects?]}] - (let [changes (reduce - (fn [changes id] - (let [opts {:attrs attrs - :ignore-geometry? (get ignore-tree id) - :ignore-touched ignore-touched - :with-objects? with-objects?}] - (pcb/update-shapes changes [id] update-fn (d/without-nils opts)))) - (-> changes - (pcb/with-objects objects)) - ids) - grid-ids (->> ids (filter (partial ctl/grid-layout? objects))) - changes (pcb/update-shapes changes grid-ids ctl/assign-cell-positions {:with-objects? true}) - changes (pcb/reorder-grid-children changes ids)] - changes)) - (declare generate-sync-container) (declare generate-sync-shape) (declare generate-sync-text-shape) @@ -58,7 +40,6 @@ (declare generate-sync-shape-direct) (declare generate-sync-shape-direct-recursive) -(declare generate-sync-shape-inverse) (declare generate-sync-shape-inverse-recursive) (declare compare-children) @@ -864,7 +845,6 @@ reset? components-v2)))) - (defn generate-rename-component "Generate the changes for rename the component with the given id, in the current file library." [changes id new-name library-data components-v2] @@ -884,9 +864,6 @@ (pcb/with-library-data library-data) (pcb/update-component id update-fn)))) - - - (defn generate-sync-shape-inverse "Generate changes to update the component a shape is linked to, from the values in the shape and all its children." @@ -1838,175 +1815,6 @@ (pcb/with-objects (:objects container)) (generate-detach-instance container libraries id)))) -(defn generate-update-shape-flags - [changes ids objects {:keys [blocked hidden] :as flags}] - (let [update-fn - (fn [obj] - (cond-> obj - (boolean? blocked) (assoc :blocked blocked) - (boolean? hidden) (assoc :hidden hidden))) - - ids (if (boolean? blocked) - (into ids (->> ids (mapcat #(cfh/get-children-ids objects %)))) - ids)] - (-> changes - (pcb/update-shapes ids update-fn {:attrs #{:blocked :hidden}})))) - -(defn generate-delete-shapes - [changes file page objects ids {:keys [components-v2 ignore-touched component-swap]}] - (let [ids (cfh/clean-loops objects ids) - - in-component-copy? - (fn [shape-id] - ;; Look for shapes that are inside a component copy, but are - ;; not the root. In this case, they must not be deleted, - ;; but hidden (to be able to recover them more easily). - ;; Unless we are doing a component swap, in which case we want - ;; to delete the old shape - (let [shape (get objects shape-id)] - (and (ctn/has-any-copy-parent? objects shape) - (not component-swap)))) - - [ids-to-delete ids-to-hide] - (if components-v2 - (loop [ids-seq (seq ids) - ids-to-delete [] - ids-to-hide []] - (let [id (first ids-seq)] - (if (nil? id) - [ids-to-delete ids-to-hide] - (if (in-component-copy? id) - (recur (rest ids-seq) - ids-to-delete - (conj ids-to-hide id)) - (recur (rest ids-seq) - (conj ids-to-delete id) - ids-to-hide))))) - [ids []]) - - changes (-> changes - (pcb/with-page page) - (pcb/with-objects objects) - (pcb/with-library-data file)) - lookup (d/getf objects) - groups-to-unmask - (reduce (fn [group-ids id] - ;; When the shape to delete is the mask of a masked group, - ;; the mask condition must be removed, and it must be - ;; converted to a normal group. - (let [obj (lookup id) - parent (lookup (:parent-id obj))] - (if (and (:masked-group parent) - (= id (first (:shapes parent)))) - (conj group-ids (:id parent)) - group-ids))) - #{} - ids-to-delete) - - interacting-shapes - (filter (fn [shape] - ;; If any of the deleted shapes is the destination of - ;; some interaction, this must be deleted, too. - (let [interactions (:interactions shape)] - (some #(and (ctsi/has-destination %) - (contains? ids-to-delete (:destination %))) - interactions))) - (vals objects)) - - ids-set (set ids-to-delete) - guides-to-remove - (->> (dm/get-in page [:options :guides]) - (vals) - (filter #(contains? ids-set (:frame-id %))) - (map :id)) - - guides - (->> guides-to-remove - (reduce dissoc (dm/get-in page [:options :guides]))) - - starting-flows - (filter (fn [flow] - ;; If any of the deleted is a frame that starts a flow, - ;; this must be deleted, too. - (contains? ids-to-delete (:starting-frame flow))) - (-> page :options :flows)) - - all-parents - (reduce (fn [res id] - ;; All parents of any deleted shape must be resized. - (into res (cfh/get-parent-ids objects id))) - (d/ordered-set) - ids-to-delete) - - all-children - (->> ids-to-delete ;; Children of deleted shapes must be also deleted. - (reduce (fn [res id] - (into res (cfh/get-children-ids objects id))) - []) - (reverse) - (into (d/ordered-set))) - - find-all-empty-parents - (fn recursive-find-empty-parents [empty-parents] - (let [all-ids (into empty-parents ids-to-delete) - contains? (partial contains? all-ids) - xform (comp (map lookup) - (filter #(or (cfh/group-shape? %) (cfh/bool-shape? %))) - (remove #(->> (:shapes %) (remove contains?) seq)) - (map :id)) - parents (into #{} xform all-parents)] - (if (= empty-parents parents) - empty-parents - (recursive-find-empty-parents parents)))) - - empty-parents - ;; Any parent whose children are all deleted, must be deleted too. - (into (d/ordered-set) (find-all-empty-parents #{})) - - components-to-delete - (if components-v2 - (reduce (fn [components id] - (let [shape (get objects id)] - (if (and (= (:component-file shape) (:id file)) ;; Main instances should exist only in local file - (:main-instance shape)) ;; but check anyway - (conj components (:component-id shape)) - components))) - [] - (into ids-to-delete all-children)) - []) - - changes (-> changes - (pcb/set-page-option :guides guides)) - - changes (reduce (fn [changes component-id] - ;; It's important to delete the component before the main instance, because we - ;; need to store the instance position if we want to restore it later. - (pcb/delete-component changes component-id (:id page))) - changes - components-to-delete) - changes (-> changes - (generate-update-shape-flags ids-to-hide objects {:hidden true}) - (pcb/remove-objects all-children {:ignore-touched true}) - (pcb/remove-objects ids-to-delete {:ignore-touched ignore-touched}) - (pcb/remove-objects empty-parents) - (pcb/resize-parents all-parents) - (pcb/update-shapes groups-to-unmask - (fn [shape] - (assoc shape :masked-group false))) - (pcb/update-shapes (map :id interacting-shapes) - (fn [shape] - (d/update-when shape :interactions - (fn [interactions] - (into [] - (remove #(and (ctsi/has-destination %) - (contains? ids-to-delete (:destination %)))) - interactions))))) - (cond-> (seq starting-flows) - (pcb/update-page-option :flows (fn [flows] - (->> (map :id starting-flows) - (reduce ctp/remove-flow flows))))))] - [all-parents changes])) - (defn generate-new-shape-for-swap [changes shape file page libraries id-new-component index target-cell keep-props-values] (let [objects (:objects page) @@ -2057,8 +1865,8 @@ [changes objects shape file page libraries id-new-component index target-cell keep-props-values] (let [[all-parents changes] (-> changes - (generate-delete-shapes file page objects (d/ordered-set (:id shape)) {:components-v2 true - :component-swap true})) + (cls/generate-delete-shapes file page objects (d/ordered-set (:id shape)) {:components-v2 true + :component-swap true})) [new-shape changes] (-> changes (generate-new-shape-for-swap shape file page libraries id-new-component index target-cell keep-props-values))] @@ -2115,317 +1923,3 @@ (cond-> changes (some? swap-slot) (generate-sync-head file-full libraries container id components-v2 true)))) - -(defn generate-relocate-shapes [changes objects parents parent-id page-id to-index ids] - (let [groups-to-delete - (loop [current-id (first parents) - to-check (rest parents) - removed-id? (set ids) - result #{}] - - (if-not current-id - ;; Base case, no next element - result - - (let [group (get objects current-id)] - (if (and (not= :frame (:type group)) - (not= current-id parent-id) - (empty? (remove removed-id? (:shapes group)))) - - ;; Adds group to the remove and check its parent - (let [to-check (concat to-check [(cfh/get-parent-id objects current-id)])] - (recur (first to-check) - (rest to-check) - (conj removed-id? current-id) - (conj result current-id))) - - ;; otherwise recur - (recur (first to-check) - (rest to-check) - removed-id? - result))))) - - groups-to-unmask - (reduce (fn [group-ids id] - ;; When a masked group loses its mask shape, because it's - ;; moved outside the group, the mask condition must be - ;; removed, and it must be converted to a normal group. - (let [obj (get objects id) - parent (get objects (:parent-id obj))] - (if (and (:masked-group parent) - (= id (first (:shapes parent))) - (not= (:id parent) parent-id)) - (conj group-ids (:id parent)) - group-ids))) - #{} - ids) - - - ;; TODO: Probably implementing this using loop/recur will - ;; be more efficient than using reduce and continuous data - ;; desturcturing. - - ;; Sets the correct components metadata for the moved shapes - ;; `shapes-to-detach` Detach from a component instance a shape that was inside a component and is moved outside - ;; `shapes-to-deroot` Removes the root flag from a component instance moved inside another component - ;; `shapes-to-reroot` Adds a root flag when a nested component instance is moved outside - [shapes-to-detach shapes-to-deroot shapes-to-reroot] - (reduce (fn [[shapes-to-detach shapes-to-deroot shapes-to-reroot] id] - (let [shape (get objects id) - parent (get objects parent-id) - component-shape (ctn/get-component-shape objects shape) - component-shape-parent (ctn/get-component-shape objects parent {:allow-main? true}) - root-parent (ctn/get-instance-root objects parent) - - detach? (and (ctk/in-component-copy-not-head? shape) - (not= (:id component-shape) - (:id component-shape-parent))) - deroot? (and (ctk/instance-root? shape) - root-parent) - reroot? (and (ctk/subinstance-head? shape) - (not component-shape-parent)) - - ids-to-detach (when detach? - (cons id (cfh/get-children-ids objects id)))] - - [(cond-> shapes-to-detach detach? (into ids-to-detach)) - (cond-> shapes-to-deroot deroot? (conj id)) - (cond-> shapes-to-reroot reroot? (conj id))])) - [[] [] []] - (->> ids - (mapcat #(ctn/get-child-heads objects %)) - (map :id))) - - shapes-to-unconstraint ids - - ordered-indexes (cfh/order-by-indexed-shapes objects ids) - shapes (map (d/getf objects) ordered-indexes) - parent (get objects parent-id) - component-main-parent (ctn/find-component-main objects parent false) - child-heads - (->> ordered-indexes - (mapcat #(ctn/get-child-heads objects %)) - (map :id))] - - (-> changes - (pcb/with-page-id page-id) - (pcb/with-objects objects) - - ;; Remove layout-item properties when moving a shape outside a layout - (cond-> (not (ctl/any-layout? parent)) - (pcb/update-shapes ordered-indexes ctl/remove-layout-item-data)) - - ;; Remove the hide in viewer flag - (cond-> (and (not= uuid/zero parent-id) (cfh/frame-shape? parent)) - (pcb/update-shapes ordered-indexes #(cond-> % (cfh/frame-shape? %) (assoc :hide-in-viewer true)))) - - ;; Remove the swap slots if it is moving to a different component - (pcb/update-shapes child-heads - (fn [shape] - (cond-> shape - (not= component-main-parent (ctn/find-component-main objects shape false)) - (ctk/remove-swap-slot)))) - - ;; Add component-root property when moving a component outside a component - (cond-> (not (ctn/get-instance-root objects parent)) - (pcb/update-shapes child-heads #(assoc % :component-root true))) - - ;; Move the shapes - (pcb/change-parent parent-id - shapes - to-index) - - ;; Remove empty groups - (pcb/remove-objects groups-to-delete) - - ;; Unmask groups whose mask have moved outside - (pcb/update-shapes groups-to-unmask - (fn [shape] - (assoc shape :masked-group false))) - - ;; Detach shapes moved out of their component - (pcb/update-shapes shapes-to-detach ctk/detach-shape) - - ;; Make non root a component moved inside another one - (pcb/update-shapes shapes-to-deroot - (fn [shape] - (assoc shape :component-root nil))) - - ;; Make root a subcomponent moved outside its parent component - (pcb/update-shapes shapes-to-reroot - (fn [shape] - (assoc shape :component-root true))) - - ;; Reset constraints depending on the new parent - (pcb/update-shapes shapes-to-unconstraint - (fn [shape] - (let [frame-id (if (= (:type parent) :frame) - (:id parent) - (:frame-id parent)) - moved-shape (assoc shape - :parent-id parent-id - :frame-id frame-id)] - (assoc shape - :constraints-h (gsh/default-constraints-h moved-shape) - :constraints-v (gsh/default-constraints-v moved-shape)))) - {:ignore-touched true}) - - ;; Fix the sizing when moving a shape - (pcb/update-shapes parents - (fn [parent] - (if (ctl/flex-layout? parent) - (cond-> parent - (ctl/change-h-sizing? (:id parent) objects (:shapes parent)) - (assoc :layout-item-h-sizing :fix) - - (ctl/change-v-sizing? (:id parent) objects (:shapes parent)) - (assoc :layout-item-v-sizing :fix)) - parent))) - - ;; Update grid layout - (cond-> (ctl/grid-layout? objects parent-id) - (pcb/update-shapes [parent-id] #(ctl/add-children-to-index % ids objects to-index))) - - (pcb/update-shapes parents - (fn [parent objects] - (cond-> parent - (ctl/grid-layout? parent) - (ctl/assign-cells objects))) - {:with-objects? true}) - - (pcb/reorder-grid-children parents) - - ;; If parent locked, lock the added shapes - (cond-> (:blocked parent) - (pcb/update-shapes ordered-indexes #(assoc % :blocked true))) - - ;; Resize parent containers that need to - (pcb/resize-parents parents)))) - - -(defn generate-move-shapes-to-frame - [changes ids frame-id page-id objects drop-index [row column :as cell]] - (let [lookup (d/getf objects) - frame (get objects frame-id) - layout? (:layout frame) - - component-main-frame (ctn/find-component-main objects frame false) - - shapes (->> ids - (cfh/clean-loops objects) - (keep lookup) - ;;remove shapes inside copies, because we can't change the structure of copies - (remove #(ctk/in-component-copy? (get objects (:parent-id %))))) - - moving-shapes - (cond->> shapes - (not layout?) - (remove #(= (:frame-id %) frame-id)) - - layout? - (remove #(and (= (:frame-id %) frame-id) - (not= (:parent-id %) frame-id)))) - - ordered-indexes (cfh/order-by-indexed-shapes objects (map :id moving-shapes)) - moving-shapes (map (d/getf objects) ordered-indexes) - - all-parents - (reduce (fn [res id] - (into res (cfh/get-parent-ids objects id))) - (d/ordered-set) - ids) - - find-all-empty-parents - (fn recursive-find-empty-parents [empty-parents] - (let [all-ids (into empty-parents ids) - contains? (partial contains? all-ids) - xform (comp (map lookup) - (filter cfh/group-shape?) - (remove #(->> (:shapes %) (remove contains?) seq)) - (map :id)) - parents (into #{} xform all-parents)] - (if (= empty-parents parents) - empty-parents - (recursive-find-empty-parents parents)))) - - empty-parents - ;; Any empty parent whose children are moved to another frame should be deleted - (if (empty? moving-shapes) - #{} - (into (d/ordered-set) (find-all-empty-parents #{}))) - - ;; Not move absolute shapes that won't change parent - moving-shapes - (->> moving-shapes - (remove (fn [shape] - (and (ctl/position-absolute? shape) - (= frame-id (:parent-id shape)))))) - - frame-component - (ctn/get-component-shape objects frame) - - shape-ids-to-detach - (reduce (fn [result shape] - (if (and (some? shape) (ctk/in-component-copy-not-head? shape)) - (let [shape-component (ctn/get-component-shape objects shape)] - (if (= (:id frame-component) (:id shape-component)) - result - (into result (cfh/get-children-ids-with-self objects (:id shape))))) - result)) - #{} - moving-shapes) - - moving-shapes-ids - (map :id moving-shapes) - - moving-shapes-children-ids - (->> moving-shapes-ids - (mapcat #(cfh/get-children-ids-with-self objects %))) - - child-heads - (->> moving-shapes-ids - (mapcat #(ctn/get-child-heads objects %)) - (map :id))] - (-> changes - (pcb/with-page-id page-id) - (pcb/with-objects objects) - - ;; Remove layout-item properties when moving a shape outside a layout - (cond-> (not (ctl/any-layout? objects frame-id)) - (pcb/update-shapes moving-shapes-ids ctl/remove-layout-item-data)) - - ;; Remove the swap slots if it is moving to a different component - (pcb/update-shapes - child-heads - (fn [shape] - (cond-> shape - (not= component-main-frame (ctn/find-component-main objects shape false)) - (ctk/remove-swap-slot)))) - - ;; Remove component-root property when moving a shape inside a component - (cond-> (ctn/get-instance-root objects frame) - (pcb/update-shapes moving-shapes-children-ids #(dissoc % :component-root))) - - ;; Add component-root property when moving a component outside a component - (cond-> (not (ctn/get-instance-root objects frame)) - (pcb/update-shapes child-heads #(assoc % :component-root true))) - - (pcb/update-shapes moving-shapes-ids #(cond-> % (cfh/frame-shape? %) (assoc :hide-in-viewer true))) - (pcb/update-shapes shape-ids-to-detach ctk/detach-shape) - (pcb/change-parent frame-id moving-shapes drop-index) - - ;; Change the grid cell in a grid layout - (cond-> (ctl/grid-layout? objects frame-id) - (-> (pcb/update-shapes - [frame-id] - (fn [frame objects] - (-> frame - ;; Assign the cell when pushing into a specific grid cell - (cond-> (some? cell) - (-> (ctl/free-cell-shapes moving-shapes-ids) - (ctl/push-into-cell moving-shapes-ids row column) - (ctl/assign-cells objects))) - (ctl/assign-cell-positions objects))) - {:with-objects? true}) - (pcb/reorder-grid-children [frame-id]))) - (pcb/remove-objects empty-parents)))) diff --git a/common/src/app/common/logic/shapes.cljc b/common/src/app/common/logic/shapes.cljc new file mode 100644 index 000000000..29d58dad6 --- /dev/null +++ b/common/src/app/common/logic/shapes.cljc @@ -0,0 +1,519 @@ +;; 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.common.logic.shapes + (:require + [app.common.data :as d] + [app.common.data.macros :as dm] + [app.common.files.changes-builder :as pcb] + [app.common.files.helpers :as cfh] + [app.common.geom.shapes :as gsh] + [app.common.types.component :as ctk] + [app.common.types.container :as ctn] + [app.common.types.page :as ctp] + [app.common.types.shape.interactions :as ctsi] + [app.common.types.shape.layout :as ctl] + [app.common.uuid :as uuid])) + +(defn generate-update-shapes + [changes ids update-fn objects {:keys [attrs ignore-tree ignore-touched with-objects?]}] + (let [changes (reduce + (fn [changes id] + (let [opts {:attrs attrs + :ignore-geometry? (get ignore-tree id) + :ignore-touched ignore-touched + :with-objects? with-objects?}] + (pcb/update-shapes changes [id] update-fn (d/without-nils opts)))) + (-> changes + (pcb/with-objects objects)) + ids) + grid-ids (->> ids (filter (partial ctl/grid-layout? objects))) + changes (pcb/update-shapes changes grid-ids ctl/assign-cell-positions {:with-objects? true}) + changes (pcb/reorder-grid-children changes ids)] + changes)) + +(defn- generate-update-shape-flags + [changes ids objects {:keys [blocked hidden] :as flags}] + (let [update-fn + (fn [obj] + (cond-> obj + (boolean? blocked) (assoc :blocked blocked) + (boolean? hidden) (assoc :hidden hidden))) + + ids (if (boolean? blocked) + (into ids (->> ids (mapcat #(cfh/get-children-ids objects %)))) + ids)] + (-> changes + (pcb/update-shapes ids update-fn {:attrs #{:blocked :hidden}})))) + +(defn generate-delete-shapes + [changes file page objects ids {:keys [components-v2 ignore-touched component-swap]}] + (let [ids (cfh/clean-loops objects ids) + + in-component-copy? + (fn [shape-id] + ;; Look for shapes that are inside a component copy, but are + ;; not the root. In this case, they must not be deleted, + ;; but hidden (to be able to recover them more easily). + ;; Unless we are doing a component swap, in which case we want + ;; to delete the old shape + (let [shape (get objects shape-id)] + (and (ctn/has-any-copy-parent? objects shape) + (not component-swap)))) + + [ids-to-delete ids-to-hide] + (if components-v2 + (loop [ids-seq (seq ids) + ids-to-delete [] + ids-to-hide []] + (let [id (first ids-seq)] + (if (nil? id) + [ids-to-delete ids-to-hide] + (if (in-component-copy? id) + (recur (rest ids-seq) + ids-to-delete + (conj ids-to-hide id)) + (recur (rest ids-seq) + (conj ids-to-delete id) + ids-to-hide))))) + [ids []]) + + changes (-> changes + (pcb/with-page page) + (pcb/with-objects objects) + (pcb/with-library-data file)) + lookup (d/getf objects) + groups-to-unmask + (reduce (fn [group-ids id] + ;; When the shape to delete is the mask of a masked group, + ;; the mask condition must be removed, and it must be + ;; converted to a normal group. + (let [obj (lookup id) + parent (lookup (:parent-id obj))] + (if (and (:masked-group parent) + (= id (first (:shapes parent)))) + (conj group-ids (:id parent)) + group-ids))) + #{} + ids-to-delete) + + interacting-shapes + (filter (fn [shape] + ;; If any of the deleted shapes is the destination of + ;; some interaction, this must be deleted, too. + (let [interactions (:interactions shape)] + (some #(and (ctsi/has-destination %) + (contains? ids-to-delete (:destination %))) + interactions))) + (vals objects)) + + ids-set (set ids-to-delete) + guides-to-remove + (->> (dm/get-in page [:options :guides]) + (vals) + (filter #(contains? ids-set (:frame-id %))) + (map :id)) + + guides + (->> guides-to-remove + (reduce dissoc (dm/get-in page [:options :guides]))) + + starting-flows + (filter (fn [flow] + ;; If any of the deleted is a frame that starts a flow, + ;; this must be deleted, too. + (contains? ids-to-delete (:starting-frame flow))) + (-> page :options :flows)) + + all-parents + (reduce (fn [res id] + ;; All parents of any deleted shape must be resized. + (into res (cfh/get-parent-ids objects id))) + (d/ordered-set) + ids-to-delete) + + all-children + (->> ids-to-delete ;; Children of deleted shapes must be also deleted. + (reduce (fn [res id] + (into res (cfh/get-children-ids objects id))) + []) + (reverse) + (into (d/ordered-set))) + + find-all-empty-parents + (fn recursive-find-empty-parents [empty-parents] + (let [all-ids (into empty-parents ids-to-delete) + contains? (partial contains? all-ids) + xform (comp (map lookup) + (filter #(or (cfh/group-shape? %) (cfh/bool-shape? %))) + (remove #(->> (:shapes %) (remove contains?) seq)) + (map :id)) + parents (into #{} xform all-parents)] + (if (= empty-parents parents) + empty-parents + (recursive-find-empty-parents parents)))) + + empty-parents + ;; Any parent whose children are all deleted, must be deleted too. + (into (d/ordered-set) (find-all-empty-parents #{})) + + components-to-delete + (if components-v2 + (reduce (fn [components id] + (let [shape (get objects id)] + (if (and (= (:component-file shape) (:id file)) ;; Main instances should exist only in local file + (:main-instance shape)) ;; but check anyway + (conj components (:component-id shape)) + components))) + [] + (into ids-to-delete all-children)) + []) + + changes (-> changes + (pcb/set-page-option :guides guides)) + + changes (reduce (fn [changes component-id] + ;; It's important to delete the component before the main instance, because we + ;; need to store the instance position if we want to restore it later. + (pcb/delete-component changes component-id (:id page))) + changes + components-to-delete) + changes (-> changes + (generate-update-shape-flags ids-to-hide objects {:hidden true}) + (pcb/remove-objects all-children {:ignore-touched true}) + (pcb/remove-objects ids-to-delete {:ignore-touched ignore-touched}) + (pcb/remove-objects empty-parents) + (pcb/resize-parents all-parents) + (pcb/update-shapes groups-to-unmask + (fn [shape] + (assoc shape :masked-group false))) + (pcb/update-shapes (map :id interacting-shapes) + (fn [shape] + (d/update-when shape :interactions + (fn [interactions] + (into [] + (remove #(and (ctsi/has-destination %) + (contains? ids-to-delete (:destination %)))) + interactions))))) + (cond-> (seq starting-flows) + (pcb/update-page-option :flows (fn [flows] + (->> (map :id starting-flows) + (reduce ctp/remove-flow flows))))))] + [all-parents changes])) + +(defn generate-relocate-shapes [changes objects parents parent-id page-id to-index ids] + (let [groups-to-delete + (loop [current-id (first parents) + to-check (rest parents) + removed-id? (set ids) + result #{}] + + (if-not current-id + ;; Base case, no next element + result + + (let [group (get objects current-id)] + (if (and (not= :frame (:type group)) + (not= current-id parent-id) + (empty? (remove removed-id? (:shapes group)))) + + ;; Adds group to the remove and check its parent + (let [to-check (concat to-check [(cfh/get-parent-id objects current-id)])] + (recur (first to-check) + (rest to-check) + (conj removed-id? current-id) + (conj result current-id))) + + ;; otherwise recur + (recur (first to-check) + (rest to-check) + removed-id? + result))))) + + groups-to-unmask + (reduce (fn [group-ids id] + ;; When a masked group loses its mask shape, because it's + ;; moved outside the group, the mask condition must be + ;; removed, and it must be converted to a normal group. + (let [obj (get objects id) + parent (get objects (:parent-id obj))] + (if (and (:masked-group parent) + (= id (first (:shapes parent))) + (not= (:id parent) parent-id)) + (conj group-ids (:id parent)) + group-ids))) + #{} + ids) + + + ;; TODO: Probably implementing this using loop/recur will + ;; be more efficient than using reduce and continuous data + ;; desturcturing. + + ;; Sets the correct components metadata for the moved shapes + ;; `shapes-to-detach` Detach from a component instance a shape that was inside a component and is moved outside + ;; `shapes-to-deroot` Removes the root flag from a component instance moved inside another component + ;; `shapes-to-reroot` Adds a root flag when a nested component instance is moved outside + [shapes-to-detach shapes-to-deroot shapes-to-reroot] + (reduce (fn [[shapes-to-detach shapes-to-deroot shapes-to-reroot] id] + (let [shape (get objects id) + parent (get objects parent-id) + component-shape (ctn/get-component-shape objects shape) + component-shape-parent (ctn/get-component-shape objects parent {:allow-main? true}) + root-parent (ctn/get-instance-root objects parent) + + detach? (and (ctk/in-component-copy-not-head? shape) + (not= (:id component-shape) + (:id component-shape-parent))) + deroot? (and (ctk/instance-root? shape) + root-parent) + reroot? (and (ctk/subinstance-head? shape) + (not component-shape-parent)) + + ids-to-detach (when detach? + (cons id (cfh/get-children-ids objects id)))] + + [(cond-> shapes-to-detach detach? (into ids-to-detach)) + (cond-> shapes-to-deroot deroot? (conj id)) + (cond-> shapes-to-reroot reroot? (conj id))])) + [[] [] []] + (->> ids + (mapcat #(ctn/get-child-heads objects %)) + (map :id))) + + shapes-to-unconstraint ids + + ordered-indexes (cfh/order-by-indexed-shapes objects ids) + shapes (map (d/getf objects) ordered-indexes) + parent (get objects parent-id) + component-main-parent (ctn/find-component-main objects parent false) + child-heads + (->> ordered-indexes + (mapcat #(ctn/get-child-heads objects %)) + (map :id))] + + (-> changes + (pcb/with-page-id page-id) + (pcb/with-objects objects) + + ;; Remove layout-item properties when moving a shape outside a layout + (cond-> (not (ctl/any-layout? parent)) + (pcb/update-shapes ordered-indexes ctl/remove-layout-item-data)) + + ;; Remove the hide in viewer flag + (cond-> (and (not= uuid/zero parent-id) (cfh/frame-shape? parent)) + (pcb/update-shapes ordered-indexes #(cond-> % (cfh/frame-shape? %) (assoc :hide-in-viewer true)))) + + ;; Remove the swap slots if it is moving to a different component + (pcb/update-shapes child-heads + (fn [shape] + (cond-> shape + (not= component-main-parent (ctn/find-component-main objects shape false)) + (ctk/remove-swap-slot)))) + + ;; Add component-root property when moving a component outside a component + (cond-> (not (ctn/get-instance-root objects parent)) + (pcb/update-shapes child-heads #(assoc % :component-root true))) + + ;; Move the shapes + (pcb/change-parent parent-id + shapes + to-index) + + ;; Remove empty groups + (pcb/remove-objects groups-to-delete) + + ;; Unmask groups whose mask have moved outside + (pcb/update-shapes groups-to-unmask + (fn [shape] + (assoc shape :masked-group false))) + + ;; Detach shapes moved out of their component + (pcb/update-shapes shapes-to-detach ctk/detach-shape) + + ;; Make non root a component moved inside another one + (pcb/update-shapes shapes-to-deroot + (fn [shape] + (assoc shape :component-root nil))) + + ;; Make root a subcomponent moved outside its parent component + (pcb/update-shapes shapes-to-reroot + (fn [shape] + (assoc shape :component-root true))) + + ;; Reset constraints depending on the new parent + (pcb/update-shapes shapes-to-unconstraint + (fn [shape] + (let [frame-id (if (= (:type parent) :frame) + (:id parent) + (:frame-id parent)) + moved-shape (assoc shape + :parent-id parent-id + :frame-id frame-id)] + (assoc shape + :constraints-h (gsh/default-constraints-h moved-shape) + :constraints-v (gsh/default-constraints-v moved-shape)))) + {:ignore-touched true}) + + ;; Fix the sizing when moving a shape + (pcb/update-shapes parents + (fn [parent] + (if (ctl/flex-layout? parent) + (cond-> parent + (ctl/change-h-sizing? (:id parent) objects (:shapes parent)) + (assoc :layout-item-h-sizing :fix) + + (ctl/change-v-sizing? (:id parent) objects (:shapes parent)) + (assoc :layout-item-v-sizing :fix)) + parent))) + + ;; Update grid layout + (cond-> (ctl/grid-layout? objects parent-id) + (pcb/update-shapes [parent-id] #(ctl/add-children-to-index % ids objects to-index))) + + (pcb/update-shapes parents + (fn [parent objects] + (cond-> parent + (ctl/grid-layout? parent) + (ctl/assign-cells objects))) + {:with-objects? true}) + + (pcb/reorder-grid-children parents) + + ;; If parent locked, lock the added shapes + (cond-> (:blocked parent) + (pcb/update-shapes ordered-indexes #(assoc % :blocked true))) + + ;; Resize parent containers that need to + (pcb/resize-parents parents)))) + + +(defn generate-move-shapes-to-frame + [changes ids frame-id page-id objects drop-index [row column :as cell]] + (let [lookup (d/getf objects) + frame (get objects frame-id) + layout? (:layout frame) + + component-main-frame (ctn/find-component-main objects frame false) + + shapes (->> ids + (cfh/clean-loops objects) + (keep lookup) + ;;remove shapes inside copies, because we can't change the structure of copies + (remove #(ctk/in-component-copy? (get objects (:parent-id %))))) + + moving-shapes + (cond->> shapes + (not layout?) + (remove #(= (:frame-id %) frame-id)) + + layout? + (remove #(and (= (:frame-id %) frame-id) + (not= (:parent-id %) frame-id)))) + + ordered-indexes (cfh/order-by-indexed-shapes objects (map :id moving-shapes)) + moving-shapes (map (d/getf objects) ordered-indexes) + + all-parents + (reduce (fn [res id] + (into res (cfh/get-parent-ids objects id))) + (d/ordered-set) + ids) + + find-all-empty-parents + (fn recursive-find-empty-parents [empty-parents] + (let [all-ids (into empty-parents ids) + contains? (partial contains? all-ids) + xform (comp (map lookup) + (filter cfh/group-shape?) + (remove #(->> (:shapes %) (remove contains?) seq)) + (map :id)) + parents (into #{} xform all-parents)] + (if (= empty-parents parents) + empty-parents + (recursive-find-empty-parents parents)))) + + empty-parents + ;; Any empty parent whose children are moved to another frame should be deleted + (if (empty? moving-shapes) + #{} + (into (d/ordered-set) (find-all-empty-parents #{}))) + + ;; Not move absolute shapes that won't change parent + moving-shapes + (->> moving-shapes + (remove (fn [shape] + (and (ctl/position-absolute? shape) + (= frame-id (:parent-id shape)))))) + + frame-component + (ctn/get-component-shape objects frame) + + shape-ids-to-detach + (reduce (fn [result shape] + (if (and (some? shape) (ctk/in-component-copy-not-head? shape)) + (let [shape-component (ctn/get-component-shape objects shape)] + (if (= (:id frame-component) (:id shape-component)) + result + (into result (cfh/get-children-ids-with-self objects (:id shape))))) + result)) + #{} + moving-shapes) + + moving-shapes-ids + (map :id moving-shapes) + + moving-shapes-children-ids + (->> moving-shapes-ids + (mapcat #(cfh/get-children-ids-with-self objects %))) + + child-heads + (->> moving-shapes-ids + (mapcat #(ctn/get-child-heads objects %)) + (map :id))] + (-> changes + (pcb/with-page-id page-id) + (pcb/with-objects objects) + + ;; Remove layout-item properties when moving a shape outside a layout + (cond-> (not (ctl/any-layout? objects frame-id)) + (pcb/update-shapes moving-shapes-ids ctl/remove-layout-item-data)) + + ;; Remove the swap slots if it is moving to a different component + (pcb/update-shapes + child-heads + (fn [shape] + (cond-> shape + (not= component-main-frame (ctn/find-component-main objects shape false)) + (ctk/remove-swap-slot)))) + + ;; Remove component-root property when moving a shape inside a component + (cond-> (ctn/get-instance-root objects frame) + (pcb/update-shapes moving-shapes-children-ids #(dissoc % :component-root))) + + ;; Add component-root property when moving a component outside a component + (cond-> (not (ctn/get-instance-root objects frame)) + (pcb/update-shapes child-heads #(assoc % :component-root true))) + + (pcb/update-shapes moving-shapes-ids #(cond-> % (cfh/frame-shape? %) (assoc :hide-in-viewer true))) + (pcb/update-shapes shape-ids-to-detach ctk/detach-shape) + (pcb/change-parent frame-id moving-shapes drop-index) + + ;; Change the grid cell in a grid layout + (cond-> (ctl/grid-layout? objects frame-id) + (-> (pcb/update-shapes + [frame-id] + (fn [frame objects] + (-> frame + ;; Assign the cell when pushing into a specific grid cell + (cond-> (some? cell) + (-> (ctl/free-cell-shapes moving-shapes-ids) + (ctl/push-into-cell moving-shapes-ids row column) + (ctl/assign-cells objects))) + (ctl/assign-cell-positions objects))) + {:with-objects? true}) + (pcb/reorder-grid-children [frame-id]))) + (pcb/remove-objects empty-parents)))) diff --git a/common/test/common_tests/helpers/files.cljc b/common/test/common_tests/helpers/files.cljc index b6349636b..c7de66880 100644 --- a/common/test/common_tests/helpers/files.cljc +++ b/common/test/common_tests/helpers/files.cljc @@ -12,9 +12,9 @@ [app.common.files.changes :as cfc] [app.common.files.changes-builder :as pcb] [app.common.files.helpers :as cfh] - [app.common.files.libraries-helpers :as cflh] [app.common.files.validate :as cfv] [app.common.geom.point :as gpt] + [app.common.logic.libraries :as cll] [app.common.pprint :refer [pprint]] [app.common.types.color :as ctc] [app.common.types.colors-list :as ctcl] @@ -297,7 +297,7 @@ [new_shape _ changes] (-> (pcb/empty-changes nil (:id page)) - (cflh/generate-component-swap objects shape (:data file) page libraries id-new-component 0 nil keep-props-values))] + (cll/generate-component-swap objects shape (:data file) page libraries id-new-component 0 nil keep-props-values))] (thi/set-id! new-shape-label (:id new_shape)) (apply-changes file changes))) diff --git a/common/test/common_tests/logic/comp_remove_swap_slots_test.cljc b/common/test/common_tests/logic/comp_remove_swap_slots_test.cljc index ede14008d..2fd559e0c 100644 --- a/common/test/common_tests/logic/comp_remove_swap_slots_test.cljc +++ b/common/test/common_tests/logic/comp_remove_swap_slots_test.cljc @@ -7,7 +7,7 @@ (ns common-tests.logic.comp-remove-swap-slots-test (:require [app.common.files.changes-builder :as pcb] - [app.common.files.libraries-helpers :as cflh] + [app.common.logic.shapes :as cls] [app.common.types.component :as ctk] [app.common.uuid :as uuid] [clojure.test :as t] @@ -57,13 +57,13 @@ blue1 (thf/get-shape file :blue1) ;; ============================== Action ============================== - changes (cflh/generate-relocate-shapes (pcb/empty-changes nil) - (:objects page) - #{(:parent-id blue1)} ;; parents - uuid/zero ;; parent-id - (:id page) ;; page-id - 0 ;; to-index - #{(:id blue1)}) ;; ids + changes (cls/generate-relocate-shapes (pcb/empty-changes nil) + (:objects page) + #{(:parent-id blue1)} ;; parents + uuid/zero ;; parent-id + (:id page) ;; page-id + 0 ;; to-index + #{(:id blue1)}) ;; ids file' (thf/apply-changes file changes) ;; ============================== Get ================================= @@ -84,13 +84,13 @@ blue1 (thf/get-shape file :blue1) ;; ============================== Action ============================== - changes (cflh/generate-move-shapes-to-frame (pcb/empty-changes nil) - #{(:id blue1)} ;; ids - uuid/zero ;; frame-id - (:id page) ;; page-id - (:objects page) ;; objects - 0 ;; drop-index - nil) ;; cell + changes (cls/generate-move-shapes-to-frame (pcb/empty-changes nil) + #{(:id blue1)} ;; ids + uuid/zero ;; frame-id + (:id page) ;; page-id + (:objects page) ;; objects + 0 ;; drop-index + nil) ;; cell file' (thf/apply-changes file changes) @@ -115,13 +115,13 @@ ;; ============================== Action ============================== - changes (cflh/generate-relocate-shapes (pcb/empty-changes nil) - (:objects page) - #{(:parent-id blue1)} ;; parents - (:id b2) ;; parent-id - (:id page) ;; page-id - 0 ;; to-index - #{(:id blue1)}) ;; ids + changes (cls/generate-relocate-shapes (pcb/empty-changes nil) + (:objects page) + #{(:parent-id blue1)} ;; parents + (:id b2) ;; parent-id + (:id page) ;; page-id + 0 ;; to-index + #{(:id blue1)}) ;; ids file' (thf/apply-changes file changes) ;; ============================== Get ================================= @@ -144,13 +144,13 @@ ;; ============================== Action ============================== - changes (cflh/generate-move-shapes-to-frame (pcb/empty-changes nil) - #{(:id blue1)} ;; ids - (:id b2) ;; frame-id - (:id page) ;; page-id - (:objects page) ;; objects - 0 ;; drop-index - nil) ;; cell + changes (cls/generate-move-shapes-to-frame (pcb/empty-changes nil) + #{(:id blue1)} ;; ids + (:id b2) ;; frame-id + (:id page) ;; page-id + (:objects page) ;; objects + 0 ;; drop-index + nil) ;; cell file' (thf/apply-changes file changes) @@ -174,26 +174,26 @@ ;; ============================== Action ============================== ;; Move blue1 into yellow - changes (cflh/generate-relocate-shapes (pcb/empty-changes nil) - (:objects page) - #{(:parent-id blue1)} ;; parents - (:id yellow) ;; parent-id - (:id page) ;; page-id - 0 ;; to-index - #{(:id blue1)}) ;; ids + changes (cls/generate-relocate-shapes (pcb/empty-changes nil) + (:objects page) + #{(:parent-id blue1)} ;; parents + (:id yellow) ;; parent-id + (:id page) ;; page-id + 0 ;; to-index + #{(:id blue1)}) ;; ids file' (thf/apply-changes file changes) page' (thf/current-page file') yellow' (thf/get-shape file' :frame-yellow) ;; Move yellow into root - changes' (cflh/generate-relocate-shapes (pcb/empty-changes nil) - (:objects page') - #{(:parent-id yellow')} ;; parents - uuid/zero ;; parent-id - (:id page') ;; page-id - 0 ;; to-index - #{(:id yellow')}) ;; ids + changes' (cls/generate-relocate-shapes (pcb/empty-changes nil) + (:objects page') + #{(:parent-id yellow')} ;; parents + uuid/zero ;; parent-id + (:id page') ;; page-id + 0 ;; to-index + #{(:id yellow')}) ;; ids file'' (thf/apply-changes file' changes') ;; ============================== Get ================================= @@ -216,26 +216,26 @@ ;; ============================== Action ============================== ;; Move blue1 into yellow - changes (cflh/generate-move-shapes-to-frame (pcb/empty-changes nil) - #{(:id blue1)} ;; ids - (:id yellow) ;; frame-id - (:id page) ;; page-id - (:objects page) ;; objects - 0 ;; drop-index - nil) ;; cell + changes (cls/generate-move-shapes-to-frame (pcb/empty-changes nil) + #{(:id blue1)} ;; ids + (:id yellow) ;; frame-id + (:id page) ;; page-id + (:objects page) ;; objects + 0 ;; drop-index + nil) ;; cell file' (thf/apply-changes file changes) page' (thf/current-page file') yellow' (thf/get-shape file' :frame-yellow) ;; Move yellow into root - changes' (cflh/generate-move-shapes-to-frame (pcb/empty-changes nil) - #{(:id yellow')} ;; ids - uuid/zero ;; frame-id - (:id page') ;; page-id - (:objects page') ;; objects - 0 ;; drop-index - nil) ;; cell + changes' (cls/generate-move-shapes-to-frame (pcb/empty-changes nil) + #{(:id yellow')} ;; ids + uuid/zero ;; frame-id + (:id page') ;; page-id + (:objects page') ;; objects + 0 ;; drop-index + nil) ;; cell file'' (thf/apply-changes file' changes') ;; ============================== Get ================================= @@ -259,13 +259,13 @@ ;; ============================== Action ============================== ;; Move blue1 into yellow - changes (cflh/generate-relocate-shapes (pcb/empty-changes nil) - (:objects page) - #{(:parent-id blue1)} ;; parents - (:id yellow) ;; parent-id - (:id page) ;; page-id - 0 ;; to-index - #{(:id blue1)}) ;; ids + changes (cls/generate-relocate-shapes (pcb/empty-changes nil) + (:objects page) + #{(:parent-id blue1)} ;; parents + (:id yellow) ;; parent-id + (:id page) ;; page-id + 0 ;; to-index + #{(:id blue1)}) ;; ids file' (thf/apply-changes file changes) page' (thf/current-page file') @@ -273,13 +273,13 @@ b2' (thf/get-shape file' :frame-b2) ;; Move yellow into b2 - changes' (cflh/generate-relocate-shapes (pcb/empty-changes nil) - (:objects page') - #{(:parent-id yellow')} ;; parents - (:id b2') ;; parent-id - (:id page') ;; page-id - 0 ;; to-index - #{(:id yellow')}) ;; ids + changes' (cls/generate-relocate-shapes (pcb/empty-changes nil) + (:objects page') + #{(:parent-id yellow')} ;; parents + (:id b2') ;; parent-id + (:id page') ;; page-id + 0 ;; to-index + #{(:id yellow')}) ;; ids file'' (thf/apply-changes file' changes') ;; ============================== Get ================================= @@ -302,13 +302,13 @@ ;; ============================== Action ============================== ;; Move blue1 into yellow - changes (cflh/generate-move-shapes-to-frame (pcb/empty-changes nil) - #{(:id blue1)} ;; ids - (:id yellow) ;; frame-id - (:id page) ;; page-id - (:objects page) ;; objects - 0 ;; drop-index - nil) ;; cell + changes (cls/generate-move-shapes-to-frame (pcb/empty-changes nil) + #{(:id blue1)} ;; ids + (:id yellow) ;; frame-id + (:id page) ;; page-id + (:objects page) ;; objects + 0 ;; drop-index + nil) ;; cell file' (thf/apply-changes file changes) page' (thf/current-page file') @@ -316,13 +316,13 @@ b2' (thf/get-shape file' :frame-b2) ;; Move yellow into b2 - changes' (cflh/generate-move-shapes-to-frame (pcb/empty-changes nil) - #{(:id yellow')} ;; ids - (:id b2') ;; frame-id - (:id page') ;; page-id - (:objects page') ;; objects - 0 ;; drop-index - nil) ;; cell + changes' (cls/generate-move-shapes-to-frame (pcb/empty-changes nil) + #{(:id yellow')} ;; ids + (:id b2') ;; frame-id + (:id page') ;; page-id + (:objects page') ;; objects + 0 ;; drop-index + nil) ;; cell file'' (thf/apply-changes file' changes') diff --git a/common/test/common_tests/logic/component_creation_test.cljc b/common/test/common_tests/logic/component_creation_test.cljc index 3e6499fb2..59ec29806 100644 --- a/common/test/common_tests/logic/component_creation_test.cljc +++ b/common/test/common_tests/logic/component_creation_test.cljc @@ -7,7 +7,7 @@ (ns common-tests.logic.component-creation-test (:require [app.common.files.changes-builder :as pcb] - [app.common.files.libraries-helpers :as cflh] + [app.common.logic.libraries :as cll] [clojure.test :as t] [common-tests.helpers.files :as thf] [common-tests.helpers.ids-map :as thi])) @@ -24,14 +24,14 @@ ;; Action [_ component-id changes] - (cflh/generate-add-component (pcb/empty-changes) - [shape1] - (:objects page) - (:id page) - (:id file) - true - nil - nil) + (cll/generate-add-component (pcb/empty-changes) + [shape1] + (:objects page) + (:id page) + (:id file) + true + nil + nil) file' (thf/apply-changes file changes) diff --git a/common/test/common_tests/logic/components_touched_test.cljc b/common/test/common_tests/logic/components_touched_test.cljc index 4d912a641..0aa14ca29 100644 --- a/common/test/common_tests/logic/components_touched_test.cljc +++ b/common/test/common_tests/logic/components_touched_test.cljc @@ -7,7 +7,8 @@ (ns common-tests.logic.components-touched-test (:require [app.common.files.changes-builder :as pcb] - [app.common.files.libraries-helpers :as cflh] + [app.common.logic.libraries :as cll] + [app.common.logic.shapes :as cls] [clojure.test :as t] [common-tests.helpers.compositions :as tho] [common-tests.helpers.files :as thf] @@ -31,11 +32,11 @@ update-fn (fn [shape] (assoc shape :fills (thf/sample-fills-color :fill-color "#fabada"))) - changes (cflh/generate-update-shapes (pcb/empty-changes nil (:id page)) - (:shapes copy-root) - update-fn - (:objects page) - {}) + changes (cls/generate-update-shapes (pcb/empty-changes nil (:id page)) + (:shapes copy-root) + update-fn + (:objects page) + {}) file' (thf/apply-changes file changes) @@ -67,13 +68,13 @@ ;; Action ;; IMPORTANT: as modifying copies structure is now forbidden, this action ;; will not have any effect, and so the parent shape won't also be touched. - changes (cflh/generate-relocate-shapes (pcb/empty-changes) - (:objects page) - #{(:parent-id copy-root)} ; parents - (thi/id :copy-root) ; parent-id - (:id page) ; page-id - 0 ; to-index - #{(thi/id :free-shape)}) ; ids + changes (cls/generate-relocate-shapes (pcb/empty-changes) + (:objects page) + #{(:parent-id copy-root)} ; parents + (thi/id :copy-root) ; parent-id + (:id page) ; page-id + 0 ; to-index + #{(thi/id :free-shape)}) ; ids file' (thf/apply-changes file changes) @@ -100,12 +101,12 @@ ;; IMPORTANT: as modifying copies structure is now forbidden, this action will not ;; delete the child shape, but hide it (thus setting the visibility group). [_all-parents changes] - (cflh/generate-delete-shapes (pcb/empty-changes) - file - page - (:objects page) - (set (:shapes copy-root)) - {:components-v2 true}) + (cls/generate-delete-shapes (pcb/empty-changes) + file + page + (:objects page) + (set (:shapes copy-root)) + {:components-v2 true}) file' (thf/apply-changes file changes) @@ -133,13 +134,13 @@ ;; Action ;; IMPORTANT: as modifying copies structure is now forbidden, this action ;; will not have any effect, and so the parent shape won't also be touched. - changes (cflh/generate-relocate-shapes (pcb/empty-changes) - (:objects page) - #{(:parent-id copy-child1)} ; parents - (thi/id :copy-root) ; parent-id - (:id page) ; page-id - 2 ; to-index - #{(:id copy-child1)}) ; ids + changes (cls/generate-relocate-shapes (pcb/empty-changes) + (:objects page) + #{(:parent-id copy-child1)} ; parents + (thi/id :copy-root) ; parent-id + (:id page) ; page-id + 2 ; to-index + #{(:id copy-child1)}) ; ids file' (thf/apply-changes file changes) diff --git a/common/test/common_tests/logic/swap_and_reset_test.cljc b/common/test/common_tests/logic/swap_and_reset_test.cljc index 1ad70d9b7..535315297 100644 --- a/common/test/common_tests/logic/swap_and_reset_test.cljc +++ b/common/test/common_tests/logic/swap_and_reset_test.cljc @@ -7,11 +7,9 @@ (ns common-tests.logic.swap-and-reset-test (:require [app.common.files.changes-builder :as pcb] - [app.common.files.libraries-helpers :as cflh] - [app.common.pprint :as pp] + [app.common.logic.libraries :as cll] [app.common.types.component :as ctk] [app.common.types.file :as ctf] - [app.common.uuid :as uuid] [clojure.test :as t] [common-tests.helpers.compositions :as thc] [common-tests.helpers.files :as thf] @@ -34,16 +32,16 @@ ;; Action [new-shape all-parents changes] - (cflh/generate-component-swap (pcb/empty-changes) - (:objects page) - component-1-copy-root - (:data file) - page - {(:id file) file} - (:id component-2) - 0 - nil - {}) + (cll/generate-component-swap (pcb/empty-changes) + (:objects page) + component-1-copy-root + (:data file) + page + {(:id file) file} + (:id component-2) + 0 + nil + {}) file' (thf/apply-changes file changes) @@ -82,16 +80,16 @@ ;; Action [new-shape all-parents changes] - (cflh/generate-component-swap (pcb/empty-changes) - (:objects page) - copy - (:data file) - page - libraries - (:id component-2) - 0 - nil - {}) + (cll/generate-component-swap (pcb/empty-changes) + (:objects page) + copy + (:data file) + page + libraries + (:id component-2) + 0 + nil + {}) file' (thf/apply-changes file changes) libraries' {(:id file') file'} @@ -137,27 +135,27 @@ ;; Action [new-shape all-parents changes-swap] - (cflh/generate-component-swap (pcb/empty-changes) - (:objects page) - copy - (:data file) - page - {(:id file) file} - (:id component-2) - 0 - nil - {}) + (cll/generate-component-swap (pcb/empty-changes) + (:objects page) + copy + (:data file) + page + {(:id file) file} + (:id component-2) + 0 + nil + {}) file-swap (thf/apply-changes file changes-swap) page-swap (thf/current-page file-swap) changes - (cflh/generate-reset-component (pcb/empty-changes) - file-swap - {(:id file-swap) file-swap} - page-swap - (:id new-shape) - true) + (cll/generate-reset-component (pcb/empty-changes) + file-swap + {(:id file-swap) file-swap} + page-swap + (:id new-shape) + true) file' (thf/apply-changes file changes) page' (thf/current-page file') diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 078f6c1a3..bb88913c4 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -13,13 +13,13 @@ [app.common.features :as cfeat] [app.common.files.changes-builder :as pcb] [app.common.files.helpers :as cfh] - [app.common.files.libraries-helpers :as cflh] [app.common.geom.align :as gal] [app.common.geom.point :as gpt] [app.common.geom.proportions :as gpp] [app.common.geom.rect :as grc] [app.common.geom.shapes :as gsh] [app.common.geom.shapes.grid-layout :as gslg] + [app.common.logic.shapes :as cls] [app.common.schema :as sm] [app.common.text :as txt] [app.common.transit :as t] @@ -809,13 +809,13 @@ all-parents (into #{parent-id} (map #(cfh/get-parent-id objects %)) ids) parents (if ignore-parents? #{parent-id} all-parents) - changes (cflh/generate-relocate-shapes (pcb/empty-changes it) - objects - parents - parent-id - page-id - to-index - ids) + changes (cls/generate-relocate-shapes (pcb/empty-changes it) + objects + parents + parent-id + page-id + to-index + ids) undo-id (js/Symbol)] (rx/of (dwu/start-undo-transaction undo-id) diff --git a/frontend/src/app/main/data/workspace/changes.cljs b/frontend/src/app/main/data/workspace/changes.cljs index 87dec4048..56fbb2411 100644 --- a/frontend/src/app/main/data/workspace/changes.cljs +++ b/frontend/src/app/main/data/workspace/changes.cljs @@ -12,8 +12,8 @@ [app.common.files.changes :as cpc] [app.common.files.changes-builder :as pcb] [app.common.files.helpers :as cph] - [app.common.files.libraries-helpers :as cflh] [app.common.logging :as log] + [app.common.logic.shapes :as cls] [app.common.schema :as sm] [app.common.types.shape-tree :as ctst] [app.common.uuid :as uuid] @@ -77,13 +77,13 @@ changes (-> (pcb/empty-changes it page-id) (pcb/set-save-undo? save-undo?) (pcb/set-stack-undo? stack-undo?) - (cflh/generate-update-shapes ids - update-fn - objects - {:attrs attrs - :ignore-tree ignore-tree - :ignore-touched ignore-touched - :with-objects? with-objects?}) + (cls/generate-update-shapes ids + update-fn + objects + {:attrs attrs + :ignore-tree ignore-tree + :ignore-touched ignore-touched + :with-objects? with-objects?}) (cond-> undo-group (pcb/set-undo-group undo-group))) diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index a542301e8..585ab58a5 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -11,10 +11,11 @@ [app.common.files.changes :as ch] [app.common.files.changes-builder :as pcb] [app.common.files.helpers :as cfh] - [app.common.files.libraries-helpers :as cflh] [app.common.files.shapes-helpers :as cfsh] [app.common.geom.point :as gpt] [app.common.logging :as log] + [app.common.logic.libraries :as cll] + [app.common.logic.shapes :as cls] [app.common.types.color :as ctc] [app.common.types.component :as ctk] [app.common.types.components-list :as ctkl] @@ -351,9 +352,9 @@ parents (into #{} (map :parent-id) shapes)] (when-not (empty? shapes) (let [[root _ changes] - (cflh/generate-add-component (pcb/empty-changes it) shapes objects page-id file-id components-v2 - dwg/prepare-create-group - cfsh/prepare-create-artboard-from-selection)] + (cll/generate-add-component (pcb/empty-changes it) shapes objects page-id file-id components-v2 + dwg/prepare-create-group + cfsh/prepare-create-artboard-from-selection)] (when-not (empty? (:redo-changes changes)) (rx/of (dch/commit-changes changes) (dws/select-shapes (d/ordered-set (:id root))) @@ -417,7 +418,7 @@ (let [library-data (get state :workspace-data) components-v2 (features/active-feature? state "components/v2") changes (-> (pcb/empty-changes it) - (cflh/generate-rename-component id new-name library-data components-v2))] + (cll/generate-rename-component id new-name library-data components-v2))] (rx/of (dch/commit-changes changes)))))))) @@ -452,7 +453,7 @@ library (get libraries library-id) components-v2 (features/active-feature? state "components/v2") changes (-> (pcb/empty-changes it nil) - (cflh/generate-duplicate-component library component-id components-v2))] + (cll/generate-duplicate-component library component-id components-v2))] (rx/of (dch/commit-changes changes)))))) @@ -478,9 +479,9 @@ [all-parents changes] (-> (pcb/empty-changes it page-id) ;; Deleting main root triggers component delete - (cflh/generate-delete-shapes file page objects #{root-id} {:components-v2 components-v2 - :undo-group undo-group - :undo-id undo-id}))] + (cls/generate-delete-shapes file page objects #{root-id} {:components-v2 components-v2 + :undo-group undo-group + :undo-id undo-id}))] (rx/of (dwu/start-undo-transaction undo-id) (dwt/clear-thumbnail (:current-file-id state) page-id root-id "component") @@ -508,7 +509,7 @@ library-data (wsh/get-file state library-id) objects (wsh/lookup-page-objects state page-id) changes (-> (pcb/empty-changes it) - (cflh/generate-restore-component library-data component-id library-id current-page objects))] + (cll/generate-restore-component library-data component-id library-id current-page objects))] (rx/of (dch/commit-changes changes)))))) @@ -545,13 +546,13 @@ (pcb/with-objects objects)) [new-shape changes] - (cflh/generate-instantiate-component changes - objects - file-id - component-id - position - page - libraries) + (cll/generate-instantiate-component changes + objects + file-id + component-id + position + page + libraries) undo-id (js/Symbol)] (rx/of (dwu/start-undo-transaction undo-id) (dch/commit-changes changes) @@ -574,7 +575,7 @@ libraries (wsh/get-libraries state) changes (-> (pcb/empty-changes it) - (cflh/generate-detach-component id file page-id libraries))] + (cll/generate-detach-component id file page-id libraries))] (rx/of (dch/commit-changes changes)))))) @@ -610,7 +611,7 @@ changes (when can-detach? (reduce (fn [changes id] - (cflh/generate-detach-instance changes container libraries id)) + (cll/generate-detach-instance changes container libraries id)) (pcb/empty-changes it) selected))] @@ -696,7 +697,7 @@ changes (-> (pcb/empty-changes it) - (cflh/generate-reset-component file-full libraries container id components-v2))] + (cll/generate-reset-component file-full libraries container id components-v2))] (log/debug :msg "RESET-COMPONENT finished" :js/rchanges (log-changes (:redo-changes changes) @@ -751,7 +752,7 @@ (-> (pcb/empty-changes it) (pcb/set-undo-group undo-group) (pcb/with-container container) - (cflh/generate-sync-shape-inverse full-file libraries container id components-v2)) + (cll/generate-sync-shape-inverse full-file libraries container id components-v2)) file-id (:component-file shape) file (wsh/get-file state file-id) @@ -890,7 +891,7 @@ [new-shape all-parents changes] (-> (pcb/empty-changes it (:id page)) (pcb/set-undo-group undo-group) - (cflh/generate-component-swap objects shape file page libraries id-new-component index target-cell keep-props-values))] + (cll/generate-component-swap objects shape file page libraries id-new-component index target-cell keep-props-values))] (rx/of (dwu/start-undo-transaction undo-id) @@ -976,7 +977,7 @@ libraries (wsh/get-libraries state) current-file-id (:current-file-id state) - changes (cflh/generate-sync-file-changes + changes (cll/generate-sync-file-changes (pcb/empty-changes it) undo-group asset-type diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index b271f1ae6..e0dee732f 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -11,10 +11,10 @@ [app.common.files.changes-builder :as pcb] [app.common.files.focus :as cpf] [app.common.files.helpers :as cfh] - [app.common.files.libraries-helpers :as cflh] [app.common.geom.point :as gpt] [app.common.geom.rect :as grc] [app.common.geom.shapes :as gsh] + [app.common.logic.libraries :as cll] [app.common.record :as cr] [app.common.types.component :as ctk] [app.common.types.container :as ctn] @@ -434,20 +434,20 @@ (gpt/subtract (-> origin-frame :selrect gpt/point))) instantiate-component - #(cflh/generate-instantiate-component changes - objects - file-id - (:component-id component-root) - pos - page - libraries - (:id component-root) - parent-id - frame-id - {}) + #(cll/generate-instantiate-component changes + objects + file-id + (:component-id component-root) + pos + page + libraries + (:id component-root) + parent-id + frame-id + {}) restore-component - #(let [restore (cflh/prepare-restore-component changes library-data (:component-id component-root) page delta (:id component-root) parent-id frame-id)] + #(let [restore (cll/prepare-restore-component changes library-data (:component-id component-root) page delta (:id component-root) parent-id frame-id)] [(:shape restore) (:changes restore)]) [_shape changes] @@ -498,7 +498,7 @@ regenerate-component (fn [changes shape] (let [components-v2 (dm/get-in library-data [:options :components-v2]) - [_ changes] (cflh/generate-add-component-changes changes shape objects file-id (:id page) components-v2)] + [_ changes] (cll/generate-add-component-changes changes shape objects file-id (:id page) components-v2)] changes)) new-obj diff --git a/frontend/src/app/main/data/workspace/shapes.cljs b/frontend/src/app/main/data/workspace/shapes.cljs index 692ff9317..1918aa0f3 100644 --- a/frontend/src/app/main/data/workspace/shapes.cljs +++ b/frontend/src/app/main/data/workspace/shapes.cljs @@ -10,8 +10,8 @@ [app.common.data.macros :as dm] [app.common.files.changes-builder :as pcb] [app.common.files.helpers :as cfh] - [app.common.files.libraries-helpers :as cflh] [app.common.files.shapes-helpers :as cfsh] + [app.common.logic.shapes :as cls] [app.common.schema :as sm] [app.common.types.container :as ctn] [app.common.types.shape :as cts] @@ -105,10 +105,10 @@ components-v2 (features/active-feature? state "components/v2") undo-id (or (:undo-id options) (js/Symbol)) [all-parents changes] (-> (pcb/empty-changes it (:id page)) - (cflh/generate-delete-shapes file page objects ids {:components-v2 components-v2 - :ignore-touched (:component-swap options) - :undo-group (:undo-group options) - :undo-id undo-id}))] + (cls/generate-delete-shapes file page objects ids {:components-v2 components-v2 + :ignore-touched (:component-swap options) + :undo-group (:undo-group options) + :undo-id undo-id}))] (rx/of (dwu/start-undo-transaction undo-id) (dc/detach-comment-thread ids) diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index 310a79c58..e381b4bee 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -11,7 +11,6 @@ [app.common.data.macros :as dm] [app.common.files.changes-builder :as pcb] [app.common.files.helpers :as cfh] - [app.common.files.libraries-helpers :as cflh] [app.common.geom.matrix :as gmt] [app.common.geom.modifiers :as gm] [app.common.geom.point :as gpt] @@ -19,6 +18,7 @@ [app.common.geom.shapes :as gsh] [app.common.geom.shapes.flex-layout :as gslf] [app.common.geom.shapes.grid-layout :as gslg] + [app.common.logic.shapes :as cls] [app.common.math :as mth] [app.common.types.component :as ctk] [app.common.types.container :as ctn] @@ -839,7 +839,7 @@ (watch [it state _] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) - changes (cflh/generate-move-shapes-to-frame (pcb/empty-changes it) ids frame-id page-id objects drop-index cell)] + changes (cls/generate-move-shapes-to-frame (pcb/empty-changes it) ids frame-id page-id objects drop-index cell)] (when (and (some? frame-id) (d/not-empty? changes)) (rx/of (dch/commit-changes changes) diff --git a/frontend/test/frontend_tests/helpers/pages.cljs b/frontend/test/frontend_tests/helpers/pages.cljs index e650c3d28..9289d992a 100644 --- a/frontend/test/frontend_tests/helpers/pages.cljs +++ b/frontend/test/frontend_tests/helpers/pages.cljs @@ -9,9 +9,9 @@ [app.common.files.changes :as cp] [app.common.files.changes-builder :as pcb] [app.common.files.helpers :as cfh] - [app.common.files.libraries-helpers :as cflh] [app.common.files.shapes-helpers :as cfsh] [app.common.geom.point :as gpt] + [app.common.logic.libraries :as cll] [app.common.types.shape :as cts] [app.common.uuid :as uuid] [app.main.data.workspace.groups :as dwg] @@ -132,14 +132,14 @@ shapes (dwg/shapes-for-grouping objects shape-ids) [group component-id changes] - (cflh/generate-add-component (pcb/empty-changes nil) - shapes - (:objects page) - (:id page) - current-file-id - true - dwg/prepare-create-group - cfsh/prepare-create-artboard-from-selection)] + (cll/generate-add-component (pcb/empty-changes nil) + shapes + (:objects page) + (:id page) + current-file-id + true + dwg/prepare-create-group + cfsh/prepare-create-artboard-from-selection)] (swap! idmap assoc instance-label (:id group) component-label component-id) @@ -158,13 +158,13 @@ (pcb/with-objects objects)) [new-shape changes] - (cflh/generate-instantiate-component changes - objects - file-id - component-id - (gpt/point 100 100) - page - libraries)] + (cll/generate-instantiate-component changes + objects + file-id + component-id + (gpt/point 100 100) + page + libraries)] (swap! idmap assoc label (:id new-shape)) (update state :workspace-data