diff --git a/backend/src/app/rpc/queries/files.clj b/backend/src/app/rpc/queries/files.clj index 8e22f6637..91e0c4023 100644 --- a/backend/src/app/rpc/queries/files.clj +++ b/backend/src/app/rpc/queries/files.clj @@ -7,7 +7,7 @@ (ns app.rpc.queries.files (:require [app.common.data :as d] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.pages.migrations :as pmg] [app.common.spec :as us] [app.common.uuid :as uuid] @@ -242,13 +242,10 @@ (defn- trim-file-data [file {:keys [page-id object-id]}] (let [page (get-in file [:data :pages-index page-id]) - objects (->> (:objects page) - (cp/get-object-with-children object-id) - (map #(dissoc % :thumbnail))) - - objects (d/index-by :id objects) + objects (->> (cph/get-children-with-self (:objects page) object-id) + (map #(dissoc % :thumbnail)) + (d/index-by :id)) page (assoc page :objects objects)] - (-> file (update :data assoc :pages-index {page-id page}) (update :data assoc :pages [page-id])))) diff --git a/common/src/app/common/pages.cljc b/common/src/app/common/pages.cljc index 25fe398fe..3c10910d4 100644 --- a/common/src/app/common/pages.cljc +++ b/common/src/app/common/pages.cljc @@ -10,7 +10,6 @@ [app.common.data :as d] [app.common.pages.changes :as changes] [app.common.pages.common :as common] - [app.common.pages.helpers :as helpers] [app.common.pages.indices :as indices] [app.common.pages.init :as init])) @@ -20,55 +19,6 @@ (d/export common/default-color) (d/export common/component-sync-attrs) -;; Helpers - -(d/export helpers/walk-pages) -(d/export helpers/select-objects) -(d/export helpers/update-object-list) -(d/export helpers/get-component-shape) -(d/export helpers/get-root-shape) -(d/export helpers/make-container) -(d/export helpers/page?) -(d/export helpers/component?) -(d/export helpers/get-container) -(d/export helpers/get-shape) -(d/export helpers/get-component) -(d/export helpers/is-main-of) -(d/export helpers/get-component-root) -(d/export helpers/get-children) -(d/export helpers/get-children-objects) -(d/export helpers/get-object-with-children) -(d/export helpers/select-children) -(d/export helpers/is-shape-grouped) -(d/export helpers/get-parent) -(d/export helpers/get-parents) -(d/export helpers/get-frame) -(d/export helpers/clean-loops) -(d/export helpers/calculate-invalid-targets) -(d/export helpers/valid-frame-target) -(d/export helpers/position-on-parent) -(d/export helpers/insert-at-index) -(d/export helpers/append-at-the-end) -(d/export helpers/select-toplevel-shapes) -(d/export helpers/select-frames) -(d/export helpers/clone-object) -(d/export helpers/indexed-shapes) -(d/export helpers/expand-region-selection) -(d/export helpers/frame-id-by-position) -(d/export helpers/set-touched-group) -(d/export helpers/touched-group?) -(d/export helpers/get-base-shape) -(d/export helpers/is-parent?) -(d/export helpers/get-index-in-parent) -(d/export helpers/split-path) -(d/export helpers/join-path) -(d/export helpers/parse-path-name) -(d/export helpers/merge-path-item) -(d/export helpers/compact-path) -(d/export helpers/compact-name) -(d/export helpers/unframed-shape?) -(d/export helpers/children-seq) - ;; Indices (d/export indices/calculate-z-index) (d/export indices/update-z-index) diff --git a/common/src/app/common/pages/changes.cljc b/common/src/app/common/pages/changes.cljc index 87283db38..e950bc7cc 100644 --- a/common/src/app/common/pages/changes.cljc +++ b/common/src/app/common/pages/changes.cljc @@ -160,7 +160,7 @@ (let [lookup (d/getf objects) update-fn #(d/update-when %1 %2 update-group %1) xform (comp - (mapcat #(cons % (cph/get-parents % objects))) + (mapcat #(cons % (cph/get-parent-ids objects %))) (filter #(contains? #{:group :bool} (-> % lookup :type))) (distinct))] @@ -202,11 +202,16 @@ (defmethod process-change :mov-objects [data {:keys [parent-id shapes index page-id component-id ignore-touched]}] - (letfn [(is-valid-move? [objects shape-id] - (let [invalid-targets (cph/calculate-invalid-targets shape-id objects)] + (letfn [(calculate-invalid-targets [objects shape-id] + (let [reduce-fn #(into %1 (calculate-invalid-targets objects %2))] + (->> (get-in objects [shape-id :shapes]) + (reduce reduce-fn #{shape-id})))) + + (is-valid-move? [objects shape-id] + (let [invalid-targets (calculate-invalid-targets objects shape-id)] (and (contains? objects shape-id) (not (invalid-targets parent-id)) - (cph/valid-frame-target shape-id parent-id objects)))) + (cph/valid-frame-target? objects parent-id shape-id)))) (insert-items [prev-shapes index shapes] (let [prev-shapes (or prev-shapes [])] diff --git a/common/src/app/common/pages/changes_builder.cljc b/common/src/app/common/pages/changes_builder.cljc index b808cbf61..e0c3b2715 100644 --- a/common/src/app/common/pages/changes_builder.cljc +++ b/common/src/app/common/pages/changes_builder.cljc @@ -7,8 +7,7 @@ (ns app.common.pages.changes-builder (:require [app.common.data :as d] - [app.common.pages :as cp] - [app.common.pages.helpers :as h])) + [app.common.pages.helpers :as cph])) ;; Auxiliary functions to help create a set of changes (undo + redo) @@ -78,7 +77,7 @@ :page-id (::page-id (meta changes)) :parent-id (:parent-id shape) :shapes [(:id shape)] - :index (cp/position-on-parent (:id shape) objects)}))] + :index (cph/get-position-on-parent objects (:id shape))}))] (-> changes (update :redo-changes conj set-parent-change) @@ -171,7 +170,7 @@ :page-id page-id :parent-id (:parent-id shape) :shapes [id] - :index (h/position-on-parent id objects) + :index (cph/get-position-on-parent objects id) :ignore-touched true})))] (-> changes diff --git a/common/src/app/common/pages/helpers.cljc b/common/src/app/common/pages/helpers.cljc index c529051f8..4fdd8e4b4 100644 --- a/common/src/app/common/pages/helpers.cljc +++ b/common/src/app/common/pages/helpers.cljc @@ -9,43 +9,234 @@ [app.common.data :as d] [app.common.geom.shapes :as gsh] [app.common.spec :as us] - [app.common.spec.interactions :as cti] + [app.common.spec.page :as spec.page] [app.common.uuid :as uuid] [cuerdas.core :as str])) -(defn walk-pages - "Go through all pages of a file and apply a function to each one" - ;; The function receives two parameters (page-id and page), and - ;; returns the updated page. - [f data] - (update data :pages-index #(d/mapm f %))) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; GENERIC SHAPE SELECTORS AND PREDICATES +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(defn select-objects - "Get a list of all objects in a container (a page or a component) that - satisfy a condition" - [f container] - (filter f (vals (get container :objects)))) +(defn ^boolean root-frame? + [{:keys [id type]}] + (and (= type :frame) + (= id uuid/zero))) -(defn update-object-list - "Update multiple objects in a page at once" - [page objects-list] - (update page :objects - #(into % (d/index-by :id objects-list)))) +(defn ^boolean frame-shape? + [{:keys [type]}] + (= type :frame)) + +(defn ^boolean group-shape? + [{:keys [type]}] + (= type :group)) + +(defn ^boolean text-shape? + [{:keys [type]}] + (= type :text)) + +(defn ^boolean unframed-shape? + "Checks if it's a non-frame shape in the top level." + [shape] + (and (not (frame-shape? shape)) + (= (:frame-id shape) uuid/zero))) + +(defn get-shape + [container shape-id] + (us/assert ::spec.page/container container) + (us/assert ::us/uuid shape-id) + (-> container + (get :objects) + (get shape-id))) + +(defn get-children-ids + [objects id] + (if-let [shapes (-> (get objects id) :shapes (some-> vec))] + (into shapes (mapcat #(get-children-ids objects %)) shapes) + [])) + +(defn get-children + [objects id] + (mapv (d/getf objects) (get-children-ids objects id))) + +(defn get-children-with-self + [objects id] + (let [lookup (d/getf objects)] + (into [(lookup id)] (map lookup) (get-children-ids objects id)))) + +(defn get-parent + "Retrieve the id of the parent for the shape-id (if exists)" + [objects id] + (let [lookup (d/getf objects)] + (-> id lookup :parent-id lookup))) + +(defn get-parent-id + "Retrieve the id of the parent for the shape-id (if exists)" + [objects id] + (-> objects (get id) :parent-id)) + +(defn get-parent-ids + "Returns a vector of parents of the specified shape." + [objects shape-id] + (loop [result [] id shape-id] + (if-let [parent-id (->> id (get objects) :parent-id)] + (recur (conj result parent-id) parent-id) + result))) + +(defn get-frame + "Get the frame that contains the shape. If the shape is already a + frame, get itself. If no shape is provided, returns the root frame." + ([objects] + (get objects uuid/zero)) + ([objects shape-or-id] + (cond + (map? shape-or-id) + (if (frame-shape? shape-or-id) + shape-or-id + (get objects (:frame-id shape-or-id))) + + (= uuid/zero shape-or-id) + (get objects uuid/zero) + + :else + (some->> shape-or-id + (get objects) + (get-frame objects))))) + +(defn valid-frame-target? + [objects parent-id shape-id] + (let [shape (get objects shape-id)] + (or (not (frame-shape? shape)) + (= parent-id uuid/zero)))) + +(defn get-position-on-parent + [objects id] + (let [obj (get objects id) + pid (:parent-id obj) + prt (get objects pid)] + (d/index-of (:shapes prt) id))) + +(defn get-immediate-children + "Retrieve resolved shape objects that are immediate children + of the specified shape-id" + ([objects] (get-immediate-children objects uuid/zero)) + ([objects shape-id] + (let [lookup (d/getf objects)] + (->> (lookup shape-id) + (:shapes) + (keep lookup))))) + +(defn get-frames + "Retrieves all frame objects as vector. It is not implemented in + function of `get-immediate-children` for performance reasons. This + function is executed in the render hot path." + [objects] + (let [lookup (d/getf objects) + xform (comp (keep lookup) + (filter frame-shape?))] + (->> (:shapes (lookup uuid/zero)) + (into [] xform)))) + +(defn frame-id-by-position + [objects position] + (let [frames (get-frames objects)] + (or + (->> frames + (reverse) + (d/seek #(and position (gsh/has-point? % position))) + :id) + uuid/zero))) + +(declare indexed-shapes) + +(defn get-base-shape + "Selects the shape that will be the base to add the shapes over" + [objects selected] + (let [;; Gets the tree-index for all the shapes + indexed-shapes (indexed-shapes objects) + + ;; Filters the selected and retrieve a list of ids + sorted-ids (->> indexed-shapes + (filter (comp selected second)) + (map second))] + + ;; The first id will be the top-most + (get objects (first sorted-ids)))) + +(defn is-parent? + "Check if `parent-candidate` is parent of `shape-id`" + [objects shape-id parent-candidate] + + (loop [current (get objects parent-candidate) + done #{} + pending (:shapes current)] + + (cond + (contains? done (:id current)) + (recur (get objects (first pending)) + done + (rest pending)) + + (empty? pending) false + (and current (contains? (set (:shapes current)) shape-id)) true + + :else + (recur (get objects (first pending)) + (conj done (:id current)) + (concat (rest pending) (:shapes current)))))) + +(defn get-index-in-parent + "Retrieves the index in the parent" + [objects shape-id] + (let [shape (get objects shape-id) + parent (get objects (:parent-id shape)) + [parent-idx _] (d/seek (fn [[_idx child-id]] (= child-id shape-id)) + (d/enumerate (:shapes parent)))] + parent-idx)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; COMPONENTS HELPERS +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defn set-touched-group + [touched group] + (conj (or touched #{}) group)) + +(defn touched-group? + [shape group] + ((or (:touched shape) #{}) group)) + +(defn get-component + "Retrieve a component from libraries, if no library-id is provided, we + iterate over all libraries and find the component on it." + ([libraries component-id] + (some #(-> % :components (get component-id)) (vals libraries))) + ([libraries library-id component-id] + (get-in libraries [library-id :components component-id]))) + +(defn ^boolean is-main-of? + [shape-main shape-inst] + (and (:shape-ref shape-inst) + (or (= (:shape-ref shape-inst) (:id shape-main)) + (= (:shape-ref shape-inst) (:shape-ref shape-main))))) + +(defn get-component-root + [component] + (get-in component [:objects (:id component)])) (defn get-component-shape "Get the parent shape linked to a component for this shape, if any" - [shape objects] + [objects shape] (if-not (:shape-ref shape) nil (if (:component-id shape) shape (if-let [parent-id (:parent-id shape)] - (get-component-shape (get objects parent-id) objects) + (get-component-shape objects (get objects parent-id)) nil)))) (defn get-root-shape - "Get the root shape linked to a component for this shape, if any" - [shape objects] + "Get the root shape linked to a component for this shape, if any." + [objects shape] (cond (some? (:component-root? shape)) @@ -57,12 +248,10 @@ (defn make-container [page-or-component type] - (assoc page-or-component - :type type)) + (assoc page-or-component :type type)) (defn page? [container] - (us/assert some? (:type container)) (= (:type container) :page)) (defn component? @@ -70,120 +259,32 @@ (= (:type container) :component)) (defn get-container - [id type local-file] - (assert (some? type)) + [file type id] + (us/assert map? file) + (us/assert keyword? type) + (us/assert uuid? id) + (-> (if (= type :page) - (get-in local-file [:pages-index id]) - (get-in local-file [:components id])) + (get-in file [:pages-index id]) + (get-in file [:components id])) (assoc :type type))) -(defn get-shape - [container shape-id] - (get-in container [:objects shape-id])) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ALGORITHMS & TRANSFORMATIONS FOR SHAPES +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(defn get-component - [component-id library-id local-library libraries] - (assert (some? (:id local-library))) - (let [file (if (= library-id (:id local-library)) - local-library - (get-in libraries [library-id :data]))] - (get-in file [:components component-id]))) +(defn walk-pages + "Go through all pages of a file and apply a function to each one" + ;; The function receives two parameters (page-id and page), and + ;; returns the updated page. + [f data] + (update data :pages-index #(d/mapm f %))) -(defn is-main-of - [shape-main shape-inst] - (and (:shape-ref shape-inst) - (or (= (:shape-ref shape-inst) (:id shape-main)) - (= (:shape-ref shape-inst) (:shape-ref shape-main))))) - -(defn get-component-root - [component] - (get-in component [:objects (:id component)])) - -(defn get-children [id objects] - (if-let [shapes (-> (get objects id) :shapes (some-> vec))] - (into shapes (mapcat #(get-children % objects)) shapes) - [])) - -(defn get-children-objects - "Retrieve all children objects recursively for a given object" - [id objects] - (mapv #(get objects %) (get-children id objects))) - -(defn get-object-with-children - "Retrieve a vector with an object and all of its children" - [id objects] - (mapv #(get objects %) (cons id (get-children id objects)))) - -(defn select-children [id objects] - (->> (get-children id objects) - (select-keys objects))) - -(defn is-shape-grouped - "Checks if a shape is inside a group" - [shape-id objects] - (let [contains-shape-fn (fn [{:keys [shapes]}] ((set shapes) shape-id)) - shapes (remove #(= (:type %) :frame) (vals objects))] - (some contains-shape-fn shapes))) - -(defn get-top-frame - [objects] - (get objects uuid/zero)) - -(defn get-parent - "Retrieve the id of the parent for the shape-id (if exists)" - [shape-id objects] - (let [obj (get objects shape-id)] - (:parent-id obj))) - -(defn get-parents - [shape-id objects] - (when-let [parent-id (->> shape-id (get objects) :parent-id)] - (lazy-seq (cons parent-id (get-parents parent-id objects))))) - -(defn get-frame - "Get the frame that contains the shape. If the shape is already a frame, get itself." - [shape objects] - (if (= (:type shape) :frame) - shape - (get objects (:frame-id shape)))) - -(defn clean-loops - "Clean a list of ids from circular references." - [objects ids] - - (let [parent-selected? - (fn [id] - (let [parents (get-parents id objects)] - (some ids parents))) - - add-element - (fn [result id] - (cond-> result - (not (parent-selected? id)) - (conj id)))] - - (reduce add-element (d/ordered-set) ids))) - -(defn calculate-invalid-targets - [shape-id objects] - (let [result #{shape-id} - children (get-in objects [shape-id :shapes]) - reduce-fn (fn [result child-id] - (into result (calculate-invalid-targets child-id objects)))] - (reduce reduce-fn result children))) - -(defn valid-frame-target - [shape-id parent-id objects] - (let [shape (get objects shape-id)] - (or (not= (:type shape) :frame) - (= parent-id uuid/zero)))) - -(defn position-on-parent - [id objects] - (let [obj (get objects id) - pid (:parent-id obj) - prt (get objects pid)] - (d/index-of (:shapes prt) id))) +(defn update-object-list + "Update multiple objects in a page at once" + [page objects-list] + (update page :objects + #(into % (d/index-by :id objects-list)))) (defn insert-at-index [objects index ids] @@ -203,41 +304,22 @@ (vec prev-ids) ids)) -(defn select-toplevel-shapes - ([objects] (select-toplevel-shapes objects nil)) - ([objects {:keys [include-frames? include-frame-children?] - :or {include-frames? false - include-frame-children? true}}] +(defn clean-loops + "Clean a list of ids from circular references." + [objects ids] - (let [lookup #(get objects %) - root (lookup uuid/zero) - root-children (:shapes root) + (let [parent-selected? + (fn [id] + (let [parents (get-parent-ids objects id)] + (some ids parents))) - lookup-shapes - (fn [result id] - (if (nil? id) - result - (let [obj (lookup id) - typ (:type obj) - children (:shapes obj)] + add-element + (fn [result id] + (cond-> result + (not (parent-selected? id)) + (conj id)))] - (cond-> result - (or (not= :frame typ) include-frames?) - (conj obj) - - (and (= :frame typ) include-frame-children?) - (into (map lookup) children)))))] - - (reduce lookup-shapes [] root-children)))) - -(defn select-frames - [objects] - (let [lookup #(get objects %) - frame? #(= :frame (:type %)) - xform (comp (map lookup) - (filter frame?))] - (->> (:shapes (lookup uuid/zero)) - (into [] xform)))) + (reduce add-element (d/ordered-set) ids))) (defn clone-object "Gets a copy of the object and all its children, with new ids @@ -304,8 +386,6 @@ (reduce red-fn cur-idx (reverse (:shapes object)))))] (into {} (rec-index '() uuid/zero)))) - - (defn expand-region-selection "Given a selection selects all the shapes between the first and last in an indexed manner (shift selection)" @@ -322,67 +402,9 @@ (map second) (into #{})))) -(defn frame-id-by-position [objects position] - (let [frames (select-frames objects)] - (or - (->> frames - (reverse) - (d/seek #(and position (gsh/has-point? % position))) - :id) - uuid/zero))) - -(defn set-touched-group - [touched group] - (conj (or touched #{}) group)) - -(defn touched-group? - [shape group] - ((or (:touched shape) #{}) group)) - -(defn get-base-shape - "Selects the shape that will be the base to add the shapes over" - [objects selected] - (let [;; Gets the tree-index for all the shapes - indexed-shapes (indexed-shapes objects) - - ;; Filters the selected and retrieve a list of ids - sorted-ids (->> indexed-shapes - (filter (comp selected second)) - (map second))] - - ;; The first id will be the top-most - (get objects (first sorted-ids)))) - -(defn is-parent? - "Check if `parent-candidate` is parent of `shape-id`" - [objects shape-id parent-candidate] - - (loop [current (get objects parent-candidate) - done #{} - pending (:shapes current)] - - (cond - (contains? done (:id current)) - (recur (get objects (first pending)) - done - (rest pending)) - - (empty? pending) false - (and current (contains? (set (:shapes current)) shape-id)) true - - :else - (recur (get objects (first pending)) - (conj done (:id current)) - (concat (rest pending) (:shapes current)))))) - -(defn get-index-in-parent - "Retrieves the index in the parent" - [objects shape-id] - (let [shape (get objects shape-id) - parent (get objects (:parent-id shape)) - [parent-idx _] (d/seek (fn [[_idx child-id]] (= child-id shape-id)) - (d/enumerate (:shapes parent)))] - parent-idx)) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; SHAPES ORGANIZATION (PATH MANAGEMENT) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defn split-path "Decompose a string in the form 'one / two / three' into @@ -442,26 +464,3 @@ [path name] (let [path-split (split-path path)] (merge-path-item (first path-split) name))) - -(defn connected-frame? - "Check if some frame is origin or destination of any navigate interaction - in the page" - [frame-id objects] - (let [children (get-object-with-children frame-id objects)] - (or (some cti/flow-origin? (map :interactions children)) - (some #(cti/flow-to? % frame-id) (map :interactions (vals objects)))))) - -(defn unframed-shape? - "Checks if it's a non-frame shape in the top level." - [shape] - (and (not= (:type shape) :frame) - (= (:frame-id shape) uuid/zero))) - -(defn children-seq - "Creates a sequence of shapes through the objects tree" - [shape objects] - (let [getter (partial get objects)] - (tree-seq #(d/not-empty? (get shape :shapes)) - #(->> (get % :shapes) (map getter)) - shape))) - diff --git a/common/src/app/common/pages/indices.cljc b/common/src/app/common/pages/indices.cljc index 8145d2f0a..2ec512478 100644 --- a/common/src/app/common/pages/indices.cljc +++ b/common/src/app/common/pages/indices.cljc @@ -7,7 +7,7 @@ (ns app.common.pages.indices (:require [app.common.data :as d] - [app.common.pages.helpers :as helpers] + [app.common.pages.helpers :as cph] [app.common.uuid :as uuid] [clojure.set :as set])) @@ -45,7 +45,7 @@ means is displayed over other shapes with less index." [objects] - (let [frames (helpers/select-frames objects) + (let [frames (cph/get-frames objects) z-index (calculate-frame-z-index {} uuid/zero objects)] (->> frames (map :id) @@ -61,7 +61,7 @@ changed-frames (set/union old-frames new-frames) - frames (->> (helpers/select-frames new-objects) + frames (->> (cph/get-frames new-objects) (map :id) (filter #(contains? changed-frames %))) @@ -84,13 +84,10 @@ (generate-child-all-parents-index objects (vals objects))) ([objects shapes] - (let [shape->parents - (fn [shape] - (->> (helpers/get-parents (:id shape) objects) - (into [])))] - (->> shapes - (map #(vector (:id %) (shape->parents %))) - (into {}))))) + (let [xf-parents (comp + (map :id) + (map #(vector % (cph/get-parent-ids objects %))))] + (into {} xf-parents shapes)))) (defn create-clip-index "Retrieves the mask information for an object" diff --git a/common/src/app/common/spec/page.cljc b/common/src/app/common/spec/page.cljc index 9ed545ac4..135eadb1e 100644 --- a/common/src/app/common/spec/page.cljc +++ b/common/src/app/common/spec/page.cljc @@ -11,7 +11,6 @@ [app.common.spec.shape :as shape] [clojure.spec.alpha :as s])) - ;; --- Grid options (s/def :internal.grid.color/color string?) diff --git a/frontend/src/app/main/data/viewer.cljs b/frontend/src/app/main/data/viewer.cljs index d528509fa..c79909eec 100644 --- a/frontend/src/app/main/data/viewer.cljs +++ b/frontend/src/app/main/data/viewer.cljs @@ -8,7 +8,7 @@ (:require [app.common.data :as d] [app.common.geom.point :as gpt] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.spec :as us] [app.common.spec.interactions :as cti] [app.common.uuid :as uuid] @@ -571,7 +571,7 @@ (conj id))] (-> state (assoc-in [:viewer-local :selected] - (cp/expand-region-selection objects selection))))))) + (cph/expand-region-selection objects selection))))))) (defn select-all [] diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 21fb41f39..ce81ba363 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -484,7 +484,7 @@ (initialize [state local] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) - shapes (cp/select-toplevel-shapes objects {:include-frames? true}) + shapes (cph/get-immediate-children objects) srect (gsh/selection-rect shapes) local (assoc local :vport size :zoom 1)] (cond @@ -675,7 +675,7 @@ (update [_ state] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) - shapes (cp/select-toplevel-shapes objects {:include-frames? true}) + shapes (cph/get-immediate-children objects) srect (gsh/selection-rect shapes)] (if (empty? shapes) state @@ -794,7 +794,7 @@ :frame-id (:frame-id obj) :page-id page-id :shapes [id] - :index (cp/position-on-parent id objects)})) + :index (cph/get-position-on-parent objects id)})) selected)] ;; TODO: maybe missing the :reg-objects event? (rx/of (dch/commit-changes {:redo-changes rchanges @@ -821,7 +821,7 @@ {:type :mov-objects :parent-id (:parent-id obj) :page-id page-id - :index (cp/position-on-parent id objects) + :index (cph/get-position-on-parent objects id) :shapes [id]})) (reverse ids)) @@ -1023,11 +1023,11 @@ objects (wsh/lookup-page-objects state page-id) ;; Ignore any shape whose parent is also intented to be moved - ids (cp/clean-loops objects ids) + ids (cph/clean-loops objects ids) ;; If we try to move a parent into a child we remove it - ids (filter #(not (cp/is-parent? objects parent-id %)) ids) - parents (into #{parent-id} (map #(cp/get-parent % objects)) ids) + ids (filter #(not (cph/is-parent? objects parent-id %)) ids) + parents (into #{parent-id} (map #(cph/get-parent-id objects %)) ids) groups-to-delete (loop [current-id (first parents) @@ -1045,7 +1045,7 @@ (empty? (remove removed-id? (:shapes group)))) ;; Adds group to the remove and check its parent - (let [to-check (concat to-check [(cp/get-parent current-id objects)])] + (let [to-check (concat to-check [(cph/get-parent-id objects current-id)])] (recur (first to-check) (rest to-check) (conj removed-id? current-id) @@ -1090,8 +1090,8 @@ (not (:component-root? shape))) parent (get objects parent-id) - component-shape (cph/get-component-shape shape objects) - component-shape-parent (cph/get-component-shape parent objects) + component-shape (cph/get-component-shape objects shape) + component-shape-parent (cph/get-component-shape objects parent) detach? (and instance-part? (not= (:id component-shape) (:id component-shape-parent))) @@ -1099,7 +1099,7 @@ reroot? (and sub-instance? (not component-shape-parent)) ids-to-detach (when detach? - (cons id (cph/get-children id objects)))] + (cons id (cph/get-children-ids objects id)))] [(cond-> shapes-to-detach detach? (into ids-to-detach)) (cond-> shapes-to-deroot deroot? (conj id)) @@ -1286,7 +1286,7 @@ (boolean? blocked) (assoc :blocked blocked) (boolean? hidden) (assoc :hidden hidden))) objects (wsh/lookup-page-objects state) - ids (into ids (->> ids (mapcat #(cp/get-children % objects))))] + ids (into ids (->> ids (mapcat #(cph/get-children-ids objects %))))] (rx/of (dch/update-shapes ids update-fn)))))) (defn toggle-visibility-selected @@ -1483,7 +1483,7 @@ (watch [_ state _] (let [selected (wsh/lookup-selected state) objects (wsh/lookup-page-objects state) - all-selected (into [] (mapcat #(cp/get-object-with-children % objects)) selected) + all-selected (into [] (mapcat #(cph/get-children-with-self objects %)) selected) head (get objects (first selected)) not-group-like? (and (= (count selected) 1) @@ -1588,7 +1588,7 @@ (watch [_ state _] (let [objects (wsh/lookup-page-objects state) selected (->> (wsh/lookup-selected state) - (cp/clean-loops objects)) + (cph/clean-loops objects)) pdata (reduce (partial collect-object-ids objects) {} selected) initial {:type :copied-shapes :file-id (:current-file-id state) @@ -1771,18 +1771,18 @@ [frame-id frame-id delta]) (empty? page-selected) - (let [frame-id (cp/frame-id-by-position page-objects mouse-pos) + (let [frame-id (cph/frame-id-by-position page-objects mouse-pos) delta (gpt/subtract mouse-pos orig-pos)] [frame-id frame-id delta]) :else - (let [base (cp/get-base-shape page-objects page-selected) - index (cp/position-on-parent (:id base) page-objects) - frame-id (:frame-id base) + (let [base (cph/get-base-shape page-objects page-selected) + index (cph/get-position-on-parent page-objects (:id base)) + frame-id (:frame-id base) parent-id (:parent-id base) - delta (if in-viewport? - (gpt/subtract mouse-pos orig-pos) - (gpt/subtract (gpt/point (:selrect base)) orig-pos))] + delta (if in-viewport? + (gpt/subtract mouse-pos orig-pos) + (gpt/subtract (gpt/point (:selrect base)) orig-pos))] [frame-id parent-id delta index])))) ;; Change the indexes if the paste is done with an element selected @@ -1804,7 +1804,7 @@ ;; Check if the shape is an instance whose master is defined in a ;; library that is not linked to the current file (foreign-instance? [shape paste-objects state] - (let [root (cph/get-root-shape shape paste-objects) + (let [root (cph/get-root-shape paste-objects shape) root-file-id (:component-file root)] (and (some? root) (not= root-file-id (:current-file-id state)) @@ -1896,7 +1896,7 @@ height 16 page-id (:current-page-id state) frame-id (-> (wsh/lookup-page-objects state page-id) - (cp/frame-id-by-position @ms/mouse-position)) + (cph/frame-id-by-position @ms/mouse-position)) shape (gsh/setup-selrect {:id id :type :text @@ -1987,7 +1987,7 @@ (watch [_ state _] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) - shapes (cp/select-toplevel-shapes objects {:include-frames? true}) + shapes (cph/get-immediate-children objects) selected (wsh/lookup-selected state) selected-objs (map #(get objects %) selected) has-frame? (some #(= (:type %) :frame) selected-objs)] diff --git a/frontend/src/app/main/data/workspace/bool.cljs b/frontend/src/app/main/data/workspace/bool.cljs index ab0ec4fdd..6c705cb61 100644 --- a/frontend/src/app/main/data/workspace/bool.cljs +++ b/frontend/src/app/main/data/workspace/bool.cljs @@ -9,8 +9,8 @@ [app.common.colors :as clr] [app.common.data :as d] [app.common.geom.shapes :as gsh] - [app.common.pages :as cp] [app.common.pages.changes-builder :as cb] + [app.common.pages.helpers :as cph] [app.common.path.shapes-to-path :as stp] [app.common.uuid :as uuid] [app.main.data.workspace.changes :as dch] @@ -22,12 +22,12 @@ (defn selected-shapes [state] - (let [objects (wsh/lookup-page-objects state)] + (let [objects (wsh/lookup-page-objects state)] (->> (wsh/lookup-selected state) - (cp/clean-loops objects) - (map #(get objects %)) - (filter #(not= :frame (:type %))) - (map #(assoc % ::index (cp/position-on-parent (:id %) objects))) + (cph/clean-loops objects) + (map (d/getf objects)) + (remove cph/frame-shape?) + (map #(assoc % ::index (cph/get-position-on-parent objects (:id %)))) (sort-by ::index)))) (defn create-bool-data @@ -51,7 +51,7 @@ (merge head-data) (gsh/update-bool-selrect shapes objects))] - [bool-shape (cp/position-on-parent (:id head) objects)])) + [bool-shape (cph/get-position-on-parent objects (:id head))])) (defn group->bool [group bool-type objects] diff --git a/frontend/src/app/main/data/workspace/common.cljs b/frontend/src/app/main/data/workspace/common.cljs index a58bf8aa5..461a0f7f5 100644 --- a/frontend/src/app/main/data/workspace/common.cljs +++ b/frontend/src/app/main/data/workspace/common.cljs @@ -11,6 +11,7 @@ [app.common.geom.shapes :as gsh] [app.common.logging :as log] [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.spec :as us] [app.common.spec.interactions :as csi] [app.common.spec.page :as csp] @@ -58,12 +59,13 @@ ;; --- Common Helpers & Events +;; TODO: looks duplicate + (defn get-frame-at-point [objects point] - (let [frames (cp/select-frames objects)] + (let [frames (cph/get-frames objects)] (d/seek #(gsh/has-point? % point) frames))) - (defn- extract-numeric-suffix [basename] (if-let [[_ p1 p2] (re-find #"(.*)-([0-9]+)$" basename)] @@ -195,9 +197,9 @@ (let [expand-fn (fn [expanded] (merge expanded (->> ids - (map #(cp/get-parents % objects)) + (map #(cph/get-parent-ids objects %)) flatten - (filter #(not= % uuid/zero)) + (remove #(= % uuid/zero)) (map (fn [id] {id true})) (into {}))))] (update-in state [:workspace-local :expanded] expand-fn))))) @@ -264,9 +266,9 @@ ;; Calculate the frame over which we're drawing (let [position @ms/mouse-position - frame-id (:frame-id attrs (cp/frame-id-by-position objects position)) + frame-id (:frame-id attrs (cph/frame-id-by-position objects position)) shape (when-not (empty? selected) - (cp/get-base-shape objects selected))] + (cph/get-base-shape objects selected))] ;; When no shapes has been selected or we're over a different frame ;; we add it as the latest shape of that frame @@ -274,7 +276,7 @@ [frame-id frame-id nil] ;; Otherwise, we add it to next to the selected shape - (let [index (cp/position-on-parent (:id shape) objects) + (let [index (cph/get-position-on-parent objects (:id shape)) {:keys [frame-id parent-id]} shape] [frame-id parent-id (inc index)]))))) @@ -356,8 +358,9 @@ (watch [it state _] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) - to-move-shapes (->> (cp/select-toplevel-shapes objects {:include-frames? false}) - (filterv #(= (:frame-id %) uuid/zero)) + + to-move-shapes (->> (cph/get-immediate-children objects) + (remove cph/frame-shape?) (mapv :id) (d/enumerate) (filterv (comp shapes second))) @@ -394,7 +397,7 @@ objects (wsh/lookup-page-objects state page-id) options (wsh/lookup-page-options state page-id) - ids (cp/clean-loops objects ids) + ids (cph/clean-loops objects ids) flows (:flows options) groups-to-unmask @@ -434,14 +437,14 @@ all-parents (reduce (fn [res id] - (into res (cp/get-parents id objects))) + (into res (cph/get-parent-ids objects id))) (d/ordered-set) ids) all-children (->> ids (reduce (fn [res id] - (into res (cp/get-children id objects))) + (into res (cph/get-children-ids objects id))) []) (reverse) (into (d/ordered-set))) @@ -463,7 +466,7 @@ {:type :add-obj :id (:id item) :page-id page-id - :index (cp/position-on-parent id objects) + :index (cph/get-position-on-parent objects id) :frame-id (:frame-id item) :parent-id (:parent-id item) :obj item})))) @@ -588,7 +591,7 @@ y (:y data (- vbc-y (/ height 2))) page-id (:current-page-id state) frame-id (-> (wsh/lookup-page-objects state page-id) - (cp/frame-id-by-position {:x frame-x :y frame-y})) + (cph/frame-id-by-position {:x frame-x :y frame-y})) shape (-> (cp/make-minimal-shape type) (merge data) (merge {:x x :y y}) diff --git a/frontend/src/app/main/data/workspace/drawing/box.cljs b/frontend/src/app/main/data/workspace/drawing/box.cljs index 01632a744..561a372b8 100644 --- a/frontend/src/app/main/data/workspace/drawing/box.cljs +++ b/frontend/src/app/main/data/workspace/drawing/box.cljs @@ -9,7 +9,7 @@ [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] [app.common.math :as mth] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.uuid :as uuid] [app.main.data.workspace.drawing.common :as common] [app.main.data.workspace.state-helpers :as wsh] @@ -62,7 +62,7 @@ layout (get state :workspace-layout) zoom (get-in state [:workspace-local :zoom] 1) - frames (cp/select-frames objects) + frames (cph/get-frames objects) fid (or (->> frames (filter #(gsh/has-point? % initial)) first diff --git a/frontend/src/app/main/data/workspace/drawing/curve.cljs b/frontend/src/app/main/data/workspace/drawing/curve.cljs index 463c1e9ea..f221ff4f2 100644 --- a/frontend/src/app/main/data/workspace/drawing/curve.cljs +++ b/frontend/src/app/main/data/workspace/drawing/curve.cljs @@ -8,7 +8,7 @@ (:require [app.common.geom.shapes :as gsh] [app.common.geom.shapes.path :as gsp] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.main.data.workspace.drawing.common :as common] [app.main.data.workspace.state-helpers :as wsh] [app.main.streams :as ms] @@ -44,10 +44,10 @@ ptk/UpdateEvent (update [_ state] - (let [objects (wsh/lookup-page-objects state) - content (get-in state [:workspace-drawing :object :content] []) + (let [objects (wsh/lookup-page-objects state) + content (get-in state [:workspace-drawing :object :content] []) position (get-in content [0 :params] nil) - frame-id (cp/frame-id-by-position objects position)] + frame-id (cph/frame-id-by-position objects position)] (-> state (assoc-in [:workspace-drawing :object :frame-id] frame-id)))))) diff --git a/frontend/src/app/main/data/workspace/groups.cljs b/frontend/src/app/main/data/workspace/groups.cljs index bf452c58f..2cfdc1a4e 100644 --- a/frontend/src/app/main/data/workspace/groups.cljs +++ b/frontend/src/app/main/data/workspace/groups.cljs @@ -10,6 +10,7 @@ [app.common.geom.shapes :as gsh] [app.common.pages :as cp] [app.common.pages.changes-builder :as cb] + [app.common.pages.helpers :as cph] [app.common.spec :as us] [app.main.data.workspace.changes :as dch] [app.main.data.workspace.common :as dwc] @@ -22,7 +23,7 @@ (->> selected (map #(get objects %)) (filter #(not= :frame (:type %))) - (map #(assoc % ::index (cp/position-on-parent (:id %) objects))) + (map #(assoc % ::index (cph/get-position-on-parent objects (:id %)))) (sort-by ::index))) (defn- get-empty-groups-after-group-creation @@ -34,10 +35,8 @@ group, one (or many) groups can become empty because they have had a single shape which is moved to the created group." [objects parent-id shapes] - (let [ids (cp/clean-loops objects (into #{} (map :id) shapes)) - parents (->> ids - (reduce #(conj %1 (cp/get-parent %2 objects)) - #{}))] + (let [ids (cph/clean-loops objects (into #{} (map :id) shapes)) + parents (into #{} (map #(cph/get-parent-id objects %)) ids)] (loop [current-id (first parents) to-check (rest parents) removed-id? ids @@ -53,7 +52,7 @@ (empty? (remove removed-id? (:shapes group)))) ;; Adds group to the remove and check its parent - (let [to-check (concat to-check [(cp/get-parent current-id objects)]) ] + (let [to-check (concat to-check [(cph/get-parent-id objects current-id)]) ] (recur (first to-check) (rest to-check) (conj removed-id? current-id) @@ -139,7 +138,7 @@ (defn prepare-remove-group [it page-id group objects] (let [children (mapv #(get objects %) (:shapes group)) - parent-id (cp/get-parent (:id group) objects) + parent-id (cph/get-parent-id objects (:id group)) parent (get objects parent-id) index-in-parent @@ -149,7 +148,7 @@ (ffirst)) ids-to-detach (when (:component-id group) - (cp/get-children (:id group) objects)) + (cph/get-children-ids objects (:id group))) detach-fn (fn [attrs] (dissoc attrs @@ -202,7 +201,7 @@ (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) selected (wsh/lookup-selected state) - selected (cp/clean-loops objects selected) + selected (cph/clean-loops objects selected) shapes (shapes-for-grouping objects selected)] (when-not (empty? shapes) (let [[group rchanges uchanges] @@ -241,7 +240,7 @@ (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) selected (wsh/lookup-selected state) - selected (cp/clean-loops objects selected) + selected (cph/clean-loops objects selected) shapes (shapes-for-grouping objects selected)] (when-not (empty? shapes) (let [;; If the selected shape is a group, we can use it. If not, diff --git a/frontend/src/app/main/data/workspace/interactions.cljs b/frontend/src/app/main/data/workspace/interactions.cljs index 5b515539d..cf71f907b 100644 --- a/frontend/src/app/main/data/workspace/interactions.cljs +++ b/frontend/src/app/main/data/workspace/interactions.cljs @@ -126,6 +126,14 @@ ;; --- Interactions +(defn- connected-frame? + "Check if some frame is origin or destination of any navigate interaction + in the page" + [objects frame-id] + (let [children (cph/get-children-with-self objects frame-id)] + (or (some csi/flow-origin? (map :interactions children)) + (some #(csi/flow-to? % frame-id) (map :interactions (vals objects)))))) + (defn add-new-interaction ([shape] (add-new-interaction shape nil)) ([shape destination] @@ -134,7 +142,7 @@ (watch [_ state _] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) - frame (cph/get-frame shape objects) + frame (cph/get-frame objects shape) flows (get-in state [:workspace-data :pages-index page-id @@ -149,7 +157,7 @@ destination)] (update shape :interactions csi/add-interaction new-interaction))))) - (when (and (not (cph/connected-frame? (:id frame) objects)) + (when (and (not (connected-frame? objects (:id frame))) (nil? flow)) (rx/of (add-flow (:id frame)))))))))) @@ -278,7 +286,7 @@ overlay-pos (-> shape (get-in [:interactions index]) :overlay-position) - orig-frame (cph/get-frame shape objects) + orig-frame (cph/get-frame objects shape) frame-pos (gpt/point (:x orig-frame) (:y orig-frame)) offset (-> initial-pos (gpt/subtract overlay-pos) diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index 5c1a24c1c..9c30f882b 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -11,6 +11,7 @@ [app.common.geom.shapes :as geom] [app.common.logging :as log] [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.spec :as us] [app.common.spec.change :as spec.change] [app.common.spec.color :as spec.color] @@ -132,7 +133,7 @@ (ptk/reify ::update-color ptk/WatchEvent (watch [it state _] - (let [[path name] (cp/parse-path-name (:name color)) + (let [[path name] (cph/parse-path-name (:name color)) color (assoc color :path path :name name) prev (get-in state [:workspace-data :colors id]) rchg {:type :mod-color @@ -184,7 +185,7 @@ ptk/WatchEvent (watch [it state _] (let [object (get-in state [:workspace-data :media id]) - [path name] (cp/parse-path-name new-name) + [path name] (cph/parse-path-name new-name) rchanges [{:type :mod-media :object {:id id @@ -244,7 +245,7 @@ (ptk/reify ::update-typography ptk/WatchEvent (watch [it state _] - (let [[path name] (cp/parse-path-name (:name typography)) + (let [[path name] (cph/parse-path-name (:name typography)) typography (assoc typography :path path :name name) prev (get-in state [:workspace-data :typographies (:id typography)]) rchg {:type :mod-typography @@ -307,7 +308,7 @@ (watch [_ state _] (let [objects (wsh/lookup-page-objects state) selected (->> (wsh/lookup-selected state) - (cp/clean-loops objects))] + (cph/clean-loops objects))] (rx/of (add-component2 selected)))))) (defn rename-component @@ -318,7 +319,7 @@ (ptk/reify ::rename-component ptk/WatchEvent (watch [it state _] - (let [[path name] (cp/parse-path-name new-name) + (let [[path name] (cph/parse-path-name new-name) component (get-in state [:workspace-data :components id]) objects (get component :objects) ; Give the same name to the root shape @@ -348,12 +349,10 @@ (ptk/reify ::duplicate-component ptk/WatchEvent (watch [it state _] - (let [component (cp/get-component id - (:current-file-id state) - (dwlh/get-local-file state) - nil) - all-components (vals (get-in state [:workspace-data :components])) - unames (set (map :name all-components)) + (let [libraries (dwlh/get-libraries state) + component (cph/get-component libraries id) + all-components (-> state :workspace-data :components vals) + unames (into #{} (map :name) all-components) new-name (dwc/generate-unique-name unames (:name component)) [new-shape new-shapes _updated-shapes] @@ -404,10 +403,9 @@ (ptk/reify ::instantiate-component ptk/WatchEvent (watch [it state _] - (let [local-library (dwlh/get-local-file state) - libraries (get state :workspace-libraries) - component (cp/get-component component-id file-id local-library libraries) - component-shape (cp/get-shape component component-id) + (let [libraries (dwlh/get-libraries state) + component (cph/get-component libraries file-id component-id) + component-shape (cph/get-shape component component-id) orig-pos (gpt/point (:x component-shape) (:y component-shape)) delta (gpt/subtract position orig-pos) @@ -416,7 +414,7 @@ objects (wsh/lookup-page-objects state page-id) unames (volatile! (dwc/retrieve-used-names objects)) - frame-id (cp/frame-id-by-position objects (gpt/add orig-pos delta)) + frame-id (cph/frame-id-by-position objects (gpt/add orig-pos delta)) update-new-shape (fn [new-shape original-shape] @@ -447,10 +445,10 @@ (dissoc :component-root?)))) [new-shape new-shapes _] - (cp/clone-object component-shape - nil - (get component :objects) - update-new-shape) + (cph/clone-object component-shape + nil + (get component :objects) + update-new-shape) rchanges (mapv (fn [obj] {:type :add-obj @@ -482,13 +480,12 @@ (ptk/reify ::detach-component ptk/WatchEvent (watch [it state _] - (let [local-library (dwlh/get-local-file state) - container (cp/get-container (get state :current-page-id) - :page - local-library) + (let [file (dwlh/get-local-file state) + page-id (get state :current-page-id) + container (cph/get-container file :page page-id) [rchanges uchanges] - (dwlh/generate-detach-instance id container)] + (dwlh/generate-detach-instance container id)] (rx/of (dch/commit-changes {:redo-changes rchanges :undo-changes uchanges @@ -498,20 +495,19 @@ (ptk/reify ::detach-selected-components ptk/WatchEvent (watch [it state _] - (let [page-id (:current-page-id state) - objects (wsh/lookup-page-objects state page-id) - local-library (dwlh/get-local-file state) - container (cp/get-container page-id :page local-library) - - selected (->> state - (wsh/lookup-selected) - (cp/clean-loops objects)) + (let [page-id (:current-page-id state) + objects (wsh/lookup-page-objects state page-id) + file (dwlh/get-local-file state) + container (cph/get-container file :page page-id) + selected (->> state + (wsh/lookup-selected) + (cph/clean-loops objects)) [rchanges uchanges] (reduce (fn [changes id] (dwlh/concat-changes changes - (dwlh/generate-detach-instance id container))) + (dwlh/generate-detach-instance container id))) dwlh/empty-changes selected)] @@ -557,21 +553,18 @@ ptk/WatchEvent (watch [it state _] (log/info :msg "RESET-COMPONENT of shape" :id (str id)) - (let [local-library (dwlh/get-local-file state) - libraries (dwlh/get-libraries state) - container (cp/get-container (get state :current-page-id) - :page - local-library) + (let [file (dwlh/get-local-file state) + libraries (dwlh/get-libraries state) + + page-id (:current-page-id state) + container (cph/get-container file :page page-id) + [rchanges uchanges] - (dwlh/generate-sync-shape-direct container - id - local-library - libraries - true)] + (dwlh/generate-sync-shape-direct libraries container id true)] + (log/debug :msg "RESET-COMPONENT finished" :js/rchanges (log-changes rchanges - local-library)) - + file)) (rx/of (dch/commit-changes {:redo-changes rchanges :undo-changes uchanges :origin it})))))) @@ -592,17 +585,16 @@ (watch [it state _] (log/info :msg "UPDATE-COMPONENT of shape" :id (str id)) (let [page-id (get state :current-page-id) - local-library (dwlh/get-local-file state) + + local-file (dwlh/get-local-file state) libraries (dwlh/get-libraries state) - [rchanges uchanges] - (dwlh/generate-sync-shape-inverse page-id - id - local-library - libraries) + container (cph/get-container local-file :page page-id) + shape (cph/get-shape container id) + + [rchanges uchanges] + (dwlh/generate-sync-shape-inverse libraries container id) - container (cp/get-container page-id :page local-library) - shape (cp/get-shape container id) file-id (:component-file shape) file (dwlh/get-file state file-id) @@ -623,21 +615,22 @@ (log/debug :msg "UPDATE-COMPONENT finished" :js/local-rchanges (log-changes local-rchanges - local-library) + file) :js/rchanges (log-changes rchanges file)) - (rx/of (when (seq local-rchanges) - (dch/commit-changes {:redo-changes local-rchanges - :undo-changes local-uchanges - :origin it - :file-id (:id local-library)})) - (when (seq rchanges) - (dch/commit-changes {:redo-changes rchanges - :undo-changes uchanges - :origin it - :file-id file-id}))))))) + (rx/of + (when (seq local-rchanges) + (dch/commit-changes {:redo-changes local-rchanges + :undo-changes local-uchanges + :origin it + :file-id (:id local-file)})) + (when (seq rchanges) + (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it + :file-id file-id}))))))) (defn update-component-sync [shape-id file-id] diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index b917a971d..6ec7dcaeb 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -11,6 +11,7 @@ [app.common.geom.shapes :as geom] [app.common.logging :as log] [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.spec :as us] [app.common.text :as txt] [app.main.data.workspace.groups :as dwg] @@ -57,7 +58,7 @@ (letfn [(concat-changes' [[rchanges1 uchanges1] [rchanges2 uchanges2]] [(d/concat-vec rchanges1 rchanges2) (d/concat-vec uchanges1 uchanges2)])] - (transduce (remove nil?) concat-changes' empty-changes rest))) + (transduce (remove nil?) (completing concat-changes') empty-changes rest))) (defn get-local-file [state] @@ -70,8 +71,11 @@ (get-in state [:workspace-libraries file-id :data]))) (defn get-libraries + "Retrieve all libraries, including the local file." [state] - (get state :workspace-libraries)) + (let [{:keys [id] :as local} (:workspace-data state)] + (-> (:workspace-libraries state) + (assoc id local)))) (defn pretty-file [file-id state] @@ -120,7 +124,7 @@ (some? (:parent-id new-shape)) (dissoc :component-root?)))] - (cp/clone-object shape nil objects update-new-shape update-original-shape))) + (cph/clone-object shape nil objects update-new-shape update-original-shape))) (defn generate-add-component "If there is exactly one id, and it's a group, use it as root. Otherwise, @@ -204,18 +208,18 @@ "Clone the root shape of the component and all children. Generate new ids from all of them." [component] - (let [component-root (cp/get-component-root component)] - (cp/clone-object component-root - nil - (get component :objects) - identity))) + (let [component-root (cph/get-component-root component)] + (cph/clone-object component-root + nil + (get component :objects) + identity))) (defn generate-detach-instance "Generate changes to remove the links between a shape and all its children with a component." - [shape-id container] + [container shape-id] (log/debug :msg "Detach instance" :shape-id shape-id :container (:id container)) - (let [shapes (cp/get-object-with-children shape-id (:objects container)) + (let [shapes (cph/get-children-with-self (:objects container) shape-id) rchanges (mapv (fn [obj] (make-change container @@ -293,7 +297,7 @@ (generate-sync-container asset-type library-id state - (cp/make-container page :page))] + (cph/make-container page :page))] (recur (next pages) (into rchanges page-rchanges) (into uchanges page-uchanges))) @@ -319,8 +323,7 @@ (generate-sync-container asset-type library-id state - (cp/make-container local-component - :component))] + (cph/make-container local-component :component))] (recur (next local-components) (into rchanges comp-rchanges) (into uchanges comp-uchanges))) @@ -331,12 +334,13 @@ or a component) that use assets of the given type in the given library." [asset-type library-id state container] - (if (cp/page? container) + (if (cph/page? container) (log/debug :msg "Sync page in local file" :page-id (:id container)) (log/debug :msg "Sync component in local library" :component-id (:id container))) - (let [has-asset-reference? (has-asset-reference-fn asset-type library-id (cp/page? container)) - linked-shapes (cp/select-objects has-asset-reference? container)] + (let [has-asset-reference? (has-asset-reference-fn asset-type library-id (cph/page? container)) + linked-shapes (->> (vals (:objects container)) + (filter has-asset-reference?))] (loop [shapes (seq linked-shapes) rchanges [] uchanges []] @@ -398,11 +402,9 @@ (defmethod generate-sync-shape :components [_ _ state container shape] - (generate-sync-shape-direct container - (:id shape) - (get-local-file state) - (get-libraries state) - false)) + (let [shape-id (:id shape) + libraries (get-libraries state)] + (generate-sync-shape-direct libraries container shape-id false))) (defn- generate-sync-text-shape [shape container update-node] @@ -624,19 +626,18 @@ (defn generate-sync-shape-direct "Generate changes to synchronize one shape that the root of a component instance, and all its children, from the given component." - [container shape-id local-library libraries reset?] + [libraries container shape-id reset?] (log/debug :msg "Sync shape direct" :shape (str shape-id) :reset? reset?) - (let [shape-inst (cp/get-shape container shape-id) - component (cp/get-component (:component-id shape-inst) - (:component-file shape-inst) - local-library - libraries) - shape-main (cp/get-shape component (:shape-ref shape-inst)) + (let [shape-inst (cph/get-shape container shape-id) + component (cph/get-component libraries + (:component-file shape-inst) + (:component-id shape-inst)) + shape-main (cph/get-shape component (:shape-ref shape-inst)) initial-root? (:component-root? shape-inst) root-inst shape-inst - root-main (cp/get-component-root component)] + root-main (cph/get-component-root component)] (if component (generate-sync-shape-direct-recursive container @@ -683,9 +684,9 @@ (when set-remote-synced? (change-remote-synced shape-inst container true))) - children-inst (mapv #(cp/get-shape container %) + children-inst (mapv #(cph/get-shape container %) (:shapes shape-inst)) - children-main (mapv #(cp/get-shape component %) + children-main (mapv #(cph/get-shape component %) (:shapes shape-main)) only-inst (fn [child-inst] @@ -743,20 +744,18 @@ (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." - [page-id shape-id local-library libraries] + [libraries container shape-id] (log/debug :msg "Sync shape inverse" :shape (str shape-id)) - (let [container (cp/get-container page-id :page local-library) - shape-inst (cp/get-shape container shape-id) - component (cp/get-component (:component-id shape-inst) - (:component-file shape-inst) - local-library - libraries) - shape-main (cp/get-shape component (:shape-ref shape-inst)) + (let [shape-inst (cph/get-shape container shape-id) + component (cph/get-component libraries + (:component-file shape-inst) + (:component-id shape-inst)) + shape-main (cph/get-shape component (:shape-ref shape-inst)) initial-root? (:component-root? shape-inst) root-inst shape-inst - root-main (cp/get-component-root component)] + root-main (cph/get-component-root component)] (if component (generate-sync-shape-inverse-recursive container @@ -777,7 +776,7 @@ (if (nil? shape-main) ;; This should not occur, but protect against it in any case empty-changes - (let [component-container (cp/make-container component :component) + (let [component-container (cph/make-container component :component) omit-touched? false set-remote-synced? (not initial-root?) @@ -805,9 +804,9 @@ (when set-remote-synced? (change-remote-synced shape-inst container true))) - children-inst (mapv #(cp/get-shape container %) + children-inst (mapv #(cph/get-shape container %) (:shapes shape-inst)) - children-main (mapv #(cp/get-shape component %) + children-main (mapv #(cph/get-shape component %) (:shapes shape-main)) only-inst (fn [child-inst] @@ -885,13 +884,13 @@ (transduce (map only-inst-cb) concat-changes changes children-inst) :else - (if (cp/is-main-of child-main child-inst) + (if (cph/is-main-of? child-main child-inst) (recur (next children-inst) (next children-main) (concat-changes changes (both-cb child-inst child-main))) - (let [child-inst' (d/seek #(cp/is-main-of child-main %) children-inst) - child-main' (d/seek #(cp/is-main-of % child-inst) children-main)] + (let [child-inst' (d/seek #(cph/is-main-of? child-main %) children-inst) + child-main' (d/seek #(cph/is-main-of? % child-inst) children-main)] (cond (nil? child-inst') (recur children-inst @@ -919,13 +918,13 @@ (defn- add-shape-to-instance [component-shape index component container root-instance root-main omit-touched? set-remote-synced?] (log/info :msg (str "ADD [P] " (:name component-shape))) - (let [component-parent-shape (cp/get-shape component (:parent-id component-shape)) - parent-shape (d/seek #(cp/is-main-of component-parent-shape %) - (cp/get-object-with-children (:id root-instance) - (:objects container))) - all-parents (vec (cons (:id parent-shape) - (cp/get-parents (:id parent-shape) - (:objects container)))) + (let [component-parent-shape (cph/get-shape component (:parent-id component-shape)) + parent-shape (d/seek #(cph/is-main-of? component-parent-shape %) + (cph/get-children-with-self (:objects container) + (:id root-instance))) + all-parents (into [(:id parent-shape)] + (cph/get-parent-ids (:objects container) + (:id parent-shape))) update-new-shape (fn [new-shape original-shape] (let [new-shape (reposition-shape new-shape @@ -945,11 +944,11 @@ original-shape) [_ new-shapes _] - (cp/clone-object component-shape - (:id parent-shape) - (get component :objects) - update-new-shape - update-original-shape) + (cph/clone-object component-shape + (:id parent-shape) + (get component :objects) + update-new-shape + update-original-shape) rchanges (d/concat-vec (map (fn [shape'] @@ -978,20 +977,20 @@ :ignore-touched true})) new-shapes)] - (if (and (cp/touched-group? parent-shape :shapes-group) omit-touched?) + (if (and (cph/touched-group? parent-shape :shapes-group) omit-touched?) empty-changes [rchanges uchanges]))) (defn- add-shape-to-main [shape index component page root-instance root-main] (log/info :msg (str "ADD [C] " (:name shape))) - (let [parent-shape (cp/get-shape page (:parent-id shape)) - component-parent-shape (d/seek #(cp/is-main-of % parent-shape) - (cp/get-object-with-children (:id root-main) - (:objects component))) - all-parents (vec (cons (:id component-parent-shape) - (cp/get-parents (:id component-parent-shape) - (:objects component)))) + (let [parent-shape (cph/get-shape page (:parent-id shape)) + component-parent-shape (d/seek #(cph/is-main-of? % parent-shape) + (cph/get-children-with-self (:objects component) + (:id root-main))) + all-parents (into [(:id component-parent-shape)] + (cph/get-parent-ids (:objects component) + (:id component-parent-shape))) update-new-shape (fn [new-shape _original-shape] (reposition-shape new-shape @@ -1005,11 +1004,11 @@ original-shape)) [_new-shape new-shapes updated-shapes] - (cp/clone-object shape - (:id component-parent-shape) - (get page :objects) - update-new-shape - update-original-shape) + (cph/clone-object shape + (:id component-parent-shape) + (get page :objects) + update-new-shape + update-original-shape) rchanges (d/concat-vec (map (fn [shape'] @@ -1057,12 +1056,12 @@ (defn- remove-shape [shape container omit-touched?] (log/info :msg (str "REMOVE-SHAPE " - (if (cp/page? container) "[P] " "[C] ") + (if (cph/page? container) "[P] " "[C] ") (:name shape))) (let [objects (get container :objects) - parents (cp/get-parents (:id shape) objects) + parents (cph/get-parent-ids objects (:id shape)) parent (first parents) - children (cp/get-children (:id shape) objects) + children (cph/get-children-ids objects (:id shape)) rchanges [(make-change container @@ -1080,7 +1079,7 @@ container (as-> {:type :add-obj :id id - :index (cp/position-on-parent id objects) + :index (cph/get-position-on-parent objects id) :parent-id (:parent-id shape') :ignore-touched true :obj shape'} $ @@ -1096,20 +1095,20 @@ {:type :reg-objects :shapes (vec parents)})])] - (if (and (cp/touched-group? parent :shapes-group) omit-touched?) + (if (and (cph/touched-group? parent :shapes-group) omit-touched?) empty-changes [rchanges uchanges]))) (defn- move-shape [shape index-before index-after container omit-touched?] (log/info :msg (str "MOVE " - (if (cp/page? container) "[P] " "[C] ") + (if (cph/page? container) "[P] " "[C] ") (:name shape) " " index-before " -> " index-after)) - (let [parent (cp/get-shape container (:parent-id shape)) + (let [parent (cph/get-shape container (:parent-id shape)) rchanges [(make-change container @@ -1126,7 +1125,7 @@ :index index-before :ignore-touched true})]] - (if (and (cp/touched-group? parent :shapes-group) omit-touched?) + (if (and (cph/touched-group? parent :shapes-group) omit-touched?) empty-changes [rchanges uchanges]))) @@ -1138,7 +1137,7 @@ empty-changes (do (log/info :msg (str "CHANGE-TOUCHED " - (if (cp/page? container) "[P] " "[C] ") + (if (cph/page? container) "[P] " "[C] ") (:name dest-shape)) :options options) (let [new-touched (cond @@ -1174,7 +1173,7 @@ empty-changes (do (log/info :msg (str "CHANGE-REMOTE-SYNCED? " - (if (cp/page? container) "[P] " "[C] ") + (if (cph/page? container) "[P] " "[C] ") (:name shape)) :remote-synced? remote-synced?) (let [rchanges [(make-change @@ -1205,7 +1204,7 @@ (log/info :msg (str "SYNC " (:name origin-shape) " -> " - (if (cp/page? container) "[P] " "[C] ") + (if (cph/page? container) "[P] " "[C] ") (:name dest-shape))) (let [; To synchronize geometry attributes we need to make a prior @@ -1224,8 +1223,8 @@ (let [attr (first attrs)] (if (nil? attr) - (let [all-parents (vec (or (cp/get-parents (:id dest-shape) - (:objects container)) [])) + (let [all-parents (cph/get-parent-ids (:objects container) + (:id dest-shape)) rchanges [(make-change container {:type :mod-obj @@ -1285,7 +1284,7 @@ (defn- make-change [container change] - (if (cp/page? container) + (if (cph/page? container) (assoc change :page-id (:id container)) (assoc change :component-id (:id container)))) diff --git a/frontend/src/app/main/data/workspace/path/changes.cljs b/frontend/src/app/main/data/workspace/path/changes.cljs index c31745bab..87fb18be1 100644 --- a/frontend/src/app/main/data/workspace/path/changes.cljs +++ b/frontend/src/app/main/data/workspace/path/changes.cljs @@ -6,7 +6,7 @@ (ns app.main.data.workspace.path.changes (:require - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.spec :as us] [app.main.data.workspace.changes :as dch] [app.main.data.workspace.path.helpers :as helpers] @@ -24,7 +24,7 @@ (let [shape-id (:id shape) frame-id (:frame-id shape) parent-id (:parent-id shape) - parent-index (cp/position-on-parent shape-id objects) + parent-index (cph/get-position-on-parent objects shape-id) [old-points old-selrect] (helpers/content->points+selrect shape old-content) [new-points new-selrect] (helpers/content->points+selrect shape new-content) diff --git a/frontend/src/app/main/data/workspace/path/drawing.cljs b/frontend/src/app/main/data/workspace/path/drawing.cljs index 8e7de7cae..a6f0a41f5 100644 --- a/frontend/src/app/main/data/workspace/path/drawing.cljs +++ b/frontend/src/app/main/data/workspace/path/drawing.cljs @@ -8,7 +8,7 @@ (:require [app.common.geom.point :as gpt] [app.common.geom.shapes.path :as upg] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.path.commands :as upc] [app.common.path.shapes-to-path :as upsp] [app.common.spec :as us] @@ -255,10 +255,10 @@ (ptk/reify ::setup-frame-path ptk/UpdateEvent (update [_ state] - (let [objects (wsh/lookup-page-objects state) - content (get-in state [:workspace-drawing :object :content] []) + (let [objects (wsh/lookup-page-objects state) + content (get-in state [:workspace-drawing :object :content] []) position (get-in content [0 :params] nil) - frame-id (cp/frame-id-by-position objects position)] + frame-id (cph/frame-id-by-position objects position)] (-> state (assoc-in [:workspace-drawing :object :frame-id] frame-id)))))) diff --git a/frontend/src/app/main/data/workspace/path/shapes_to_path.cljs b/frontend/src/app/main/data/workspace/path/shapes_to_path.cljs index eae4dfb91..54dfda178 100644 --- a/frontend/src/app/main/data/workspace/path/shapes_to_path.cljs +++ b/frontend/src/app/main/data/workspace/path/shapes_to_path.cljs @@ -6,8 +6,8 @@ (ns app.main.data.workspace.path.shapes-to-path (:require - [app.common.pages :as cp] [app.common.pages.changes-builder :as cb] + [app.common.pages.helpers :as cph] [app.common.path.shapes-to-path :as upsp] [app.main.data.workspace.changes :as dch] [app.main.data.workspace.state-helpers :as wsh] @@ -24,7 +24,7 @@ children-ids (into #{} - (mapcat #(cp/get-children % objects)) + (mapcat #(cph/get-children-ids objects %)) selected) changes diff --git a/frontend/src/app/main/data/workspace/persistence.cljs b/frontend/src/app/main/data/workspace/persistence.cljs index 26b77c5a4..82f856c0a 100644 --- a/frontend/src/app/main/data/workspace/persistence.cljs +++ b/frontend/src/app/main/data/workspace/persistence.cljs @@ -9,6 +9,7 @@ [app.common.data :as d] [app.common.exceptions :as ex] [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.spec :as us] [app.common.spec.change :as spec.change] [app.common.spec.file :as spec.file] @@ -658,7 +659,7 @@ (rx/map extract-frame-changes) (rx/share)) - frames (-> state wsh/lookup-page-objects cp/select-frames) + frames (-> state wsh/lookup-page-objects cph/get-frames) no-thumb-frames (->> frames (filter (comp nil? :thumbnail)) (mapv :id))] diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index 5214d2ed5..bb29ac8f1 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -10,7 +10,7 @@ [app.common.geom.point :as gpt] [app.common.geom.shapes :as geom] [app.common.math :as mth] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.spec :as us] [app.common.spec.interactions :as cti] [app.common.uuid :as uuid] @@ -151,7 +151,7 @@ (conj id))] (-> state (assoc-in [:workspace-local :selected] - (cp/expand-region-selection objects selection)))))))) + (cph/expand-region-selection objects selection)))))))) (defn select-shapes [ids] @@ -171,39 +171,23 @@ (ptk/reify ::select-all ptk/WatchEvent (watch [_ state _] - (let [page-id (:current-page-id state) - objects (wsh/lookup-page-objects state page-id) - new-selected (let [selected-objs - (->> (wsh/lookup-selected state) - (map #(get objects %))) + (let [page-id (:current-page-id state) + objects (wsh/lookup-page-objects state page-id) - frame-ids - (reduce #(conj %1 (:frame-id %2)) - #{} - selected-objs) + selected (let [frame-ids (into #{} (comp + (map (d/getf objects)) + (map :frame-id)) + (wsh/lookup-selected state)) + frame-id (if (= 1 (count frame-ids)) + (first frame-ids) + uuid/zero)] + (cph/get-immediate-children objects frame-id)) - common-frame-id - (when (= (count frame-ids) 1) (first frame-ids))] + selected (into (d/ordered-set) + (remove :blocked) + selected)] - (if (and common-frame-id - (not= (:id common-frame-id) uuid/zero)) - (-> (get objects common-frame-id) - :shapes) - (->> (cp/select-toplevel-shapes objects - {:include-frames? true - :include-frame-children? false}) - (map :id)))) - - is-not-blocked (fn [shape-id] (not (get-in state [:workspace-data - :pages-index page-id - :objects shape-id - :blocked] false))) - - selected-ids (into lks/empty-linked-set - (comp (filter some?) - (filter is-not-blocked)) - new-selected)] - (rx/of (select-shapes selected-ids)))))) + (rx/of (select-shapes selected)))))) (defn deselect-all "Clear all possible state of drawing, edition @@ -250,7 +234,7 @@ :include-frames? true :ignore-groups? ignore-groups? :full-frame? true}) - (rx/map #(cp/clean-loops objects %)) + (rx/map #(cph/clean-loops objects %)) (rx/map #(into initial-set (filter (comp not blocked?)) %)) (rx/map select-shapes))))))) @@ -314,11 +298,8 @@ [objects page-id unames ids delta] (let [unames (volatile! unames) update-unames! (fn [new-name] (vswap! unames conj new-name)) - all-ids (reduce (fn [ids-set id] - (into ids-set (cons id (cp/get-children id objects)))) - #{} - ids) - ids-map (into {} (map #(vector % (uuid/next)) all-ids))] + all-ids (reduce #(into %1 (cons %2 (cph/get-children-ids objects %2))) #{} ids) + ids-map (into {} (map #(vector % (uuid/next))) all-ids)] (loop [ids (seq ids) chgs []] (if ids @@ -337,7 +318,7 @@ (let [process-id (fn [index-map id] (let [parent-id (get-in objects [id :parent-id]) - parent-index (cp/position-on-parent id objects)] + parent-index (cph/get-position-on-parent objects id)] (update index-map parent-id (fnil conj []) [id parent-index]))) index-map (reduce process-id {} ids)] (-> changes (update-indices index-map)))) @@ -345,7 +326,7 @@ (defn- prepare-duplicate-change [objects page-id unames update-unames! ids-map id delta] (let [obj (get objects id)] - (if (= :frame (:type obj)) + (if (cph/frame-shape? obj) (prepare-duplicate-frame-change objects page-id unames update-unames! ids-map obj delta) (prepare-duplicate-shape-change objects page-id unames update-unames! ids-map obj delta (:frame-id obj) (:parent-id obj))))) @@ -449,7 +430,7 @@ ;; The default is leave normal shapes in place, but put ;; new frames to the right of the original. - (if (= (:type obj) :frame) + (if (cph/frame-shape? obj) (gpt/point (+ (:width obj) 50) 0) (gpt/point 0 0)) diff --git a/frontend/src/app/main/data/workspace/state_helpers.cljs b/frontend/src/app/main/data/workspace/state_helpers.cljs index 661b272ad..bade10256 100644 --- a/frontend/src/app/main/data/workspace/state_helpers.cljs +++ b/frontend/src/app/main/data/workspace/state_helpers.cljs @@ -7,7 +7,7 @@ (ns app.main.data.workspace.state-helpers (:require [app.common.data :as d] - [app.common.pages :as cp])) + [app.common.pages.helpers :as cph])) (defn lookup-page ([state] @@ -43,7 +43,7 @@ :or {omit-blocked? false}}] (let [objects (lookup-page-objects state) selected (->> (get-in state [:workspace-local :selected]) - (cp/clean-loops objects)) + (cph/clean-loops objects)) selectable? (fn [id] (and (contains? objects id) (or (not omit-blocked?) diff --git a/frontend/src/app/main/data/workspace/svg_upload.cljs b/frontend/src/app/main/data/workspace/svg_upload.cljs index 118fbc0da..b649250aa 100644 --- a/frontend/src/app/main/data/workspace/svg_upload.cljs +++ b/frontend/src/app/main/data/workspace/svg_upload.cljs @@ -12,7 +12,7 @@ [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] [app.common.math :as mth] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.spec :refer [max-safe-int min-safe-int]] [app.common.uuid :as uuid] [app.main.data.workspace.changes :as dch] @@ -454,9 +454,9 @@ ptk/WatchEvent (watch [it state _] (try - (let [page-id (:current-page-id state) - objects (wsh/lookup-page-objects state page-id) - frame-id (cp/frame-id-by-position objects position) + (let [page-id (:current-page-id state) + objects (wsh/lookup-page-objects state page-id) + frame-id (cph/frame-id-by-position objects position) selected (wsh/lookup-selected state) [vb-x vb-y vb-width vb-height] (svg-dimensions svg-data) diff --git a/frontend/src/app/main/data/workspace/texts.cljs b/frontend/src/app/main/data/workspace/texts.cljs index 04d6b0eb9..061130b15 100644 --- a/frontend/src/app/main/data/workspace/texts.cljs +++ b/frontend/src/app/main/data/workspace/texts.cljs @@ -10,7 +10,7 @@ [app.common.data :as d] [app.common.geom.shapes :as gsh] [app.common.math :as mth] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.text :as txt] [app.main.data.workspace.changes :as dch] [app.main.data.workspace.common :as dwc] @@ -160,8 +160,9 @@ shape (get objects id) update-fn #(update-shape % txt/is-root-node? attrs/merge attrs) - shape-ids (cond (= (:type shape) :text) [id] - (= (:type shape) :group) (cp/get-children id objects))] + + shape-ids (cond (cph/text-shape? shape) [id] + (cph/group-shape? shape) (cph/get-children-ids objects id))] (rx/of (dch/update-shapes shape-ids update-fn)))))) @@ -186,8 +187,9 @@ attrs)) update-fn #(update-shape % txt/is-paragraph-node? merge-fn attrs) - shape-ids (cond (= (:type shape) :text) [id] - (= (:type shape) :group) (cp/get-children id objects))] + shape-ids (cond + (cph/text-shape? shape) [id] + (cph/group-shape? shape) (cph/get-children-ids objects id))] (rx/of (dch/update-shapes shape-ids update-fn)))))))) @@ -208,8 +210,9 @@ (txt/is-paragraph-node? node))) update-fn #(update-shape % update-node? attrs/merge attrs) - shape-ids (cond (= (:type shape) :text) [id] - (= (:type shape) :group) (cp/get-children id objects))] + shape-ids (cond + (cph/text-shape? shape) [id] + (cph/group-shape? shape) (cph/get-children-ids objects id))] (rx/of (dch/update-shapes shape-ids update-fn))))))) ;; --- RESIZE UTILS diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index 1d343f035..fc0e79248 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -12,7 +12,7 @@ [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] [app.common.math :as mth] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.spec :as us] [app.main.data.workspace.changes :as dch] [app.main.data.workspace.common :as dwc] @@ -144,9 +144,7 @@ (let [objects (wsh/lookup-page-objects state) shapes (->> shapes (remove #(get % :blocked false)) - (mapcat (fn [shape] - (->> (cp/get-children (:id shape) objects) - (map #(get objects %))))) + (mapcat #(cph/get-children objects (:id %))) (concat shapes)) update-shape @@ -156,8 +154,6 @@ (update state :workspace-modifiers #(reduce update-shape % shapes))))))) - - (defn- apply-modifiers [ids] (us/verify (s/coll-of uuid?) ids) @@ -165,8 +161,7 @@ ptk/WatchEvent (watch [_ state _] (let [objects (wsh/lookup-page-objects state) - children-ids (->> ids (mapcat #(cp/get-children % objects))) - ids-with-children (d/concat-vec children-ids ids) + ids-with-children (into (vec ids) (mapcat #(cph/get-children-ids objects %)) ids) object-modifiers (get state :workspace-modifiers) ignore-tree (get-ignore-tree object-modifiers objects ids)] @@ -203,7 +198,7 @@ shape (nil? root) - (cp/get-root-shape shape objects) + (cph/get-root-shape objects shape) :else root) @@ -213,7 +208,7 @@ transformed-shape (nil? transformed-root) - (cp/get-root-shape transformed-shape objects) + (cph/get-root-shape objects transformed-shape) :else transformed-root) @@ -663,10 +658,10 @@ (let [position @ms/mouse-position page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) - frame-id (cp/frame-id-by-position objects position) + frame-id (cph/frame-id-by-position objects position) moving-shapes (->> ids - (cp/clean-loops objects) + (cph/clean-loops objects) (map #(get objects %)) (remove #(or (nil? %) (= (:frame-id %) frame-id)))) @@ -683,7 +678,7 @@ {:type :mov-objects :page-id page-id :parent-id (:parent-id shape) - :index (cp/get-index-in-parent objects (:id shape)) + :index (cph/get-index-in-parent objects (:id shape)) :shapes [(:id shape)]})))] (when-not (empty? uch) diff --git a/frontend/src/app/main/refs.cljs b/frontend/src/app/main/refs.cljs index b24e1af90..b94e0af0e 100644 --- a/frontend/src/app/main/refs.cljs +++ b/frontend/src/app/main/refs.cljs @@ -9,7 +9,7 @@ (:require [app.common.data :as d] [app.common.geom.shapes :as gsh] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.path.commands :as upc] [app.main.data.workspace.state-helpers :as wsh] [app.main.store :as st] @@ -218,7 +218,7 @@ :media :typographies :components])) - st/state)) + st/state =)) (def workspace-libraries (l/derived :workspace-libraries st/state)) @@ -246,7 +246,7 @@ (l/derived :options workspace-page)) (def workspace-frames - (l/derived cp/select-frames workspace-page-objects =)) + (l/derived cph/get-frames workspace-page-objects =)) (def workspace-editor (l/derived :workspace-editor st/state)) @@ -276,9 +276,11 @@ (defn select-bool-children [id] (let [selector (fn [state] - (let [objects (wsh/lookup-page-objects state) - modifiers (:workspace-modifiers state)] - (as-> (cp/select-children id objects) $ + (let [objects (wsh/lookup-page-objects state) + modifiers (:workspace-modifiers state) + children (->> (cph/get-children-ids objects id) + (select-keys objects))] + (as-> children $ (gsh/merge-modifiers $ modifiers) (d/mapm (set-content-modifiers state) $))))] (l/derived selector st/state =))) @@ -293,7 +295,7 @@ (defn is-child-selected? [id] (letfn [(selector [{:keys [selected objects]}] - (let [children (cp/get-children id objects)] + (let [children (cph/get-children-ids objects id)] (some #(contains? selected %) children)))] (l/derived selector selected-data =))) @@ -307,7 +309,7 @@ (def selected-shapes-with-children (letfn [(selector [{:keys [selected objects]}] (let [xform (comp (remove nil?) - (mapcat #(cp/get-children % objects))) + (mapcat #(cph/get-children-ids objects %))) shapes (into selected xform selected)] (mapv (d/getf objects) shapes)))] (l/derived selector selected-data =))) diff --git a/frontend/src/app/main/render.cljs b/frontend/src/app/main/render.cljs index 91d6dd72d..fa0864282 100644 --- a/frontend/src/app/main/render.cljs +++ b/frontend/src/app/main/render.cljs @@ -19,8 +19,7 @@ [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] [app.common.math :as mth] - [app.common.pages :as cp] - [app.common.uuid :as uuid] + [app.common.pages.helpers :as cph] [app.config :as cfg] [app.main.fonts :as fonts] [app.main.ui.shapes.bool :as bool] @@ -59,12 +58,11 @@ (defn- calculate-dimensions [{:keys [objects] :as data} vport] - (let [shapes (cp/select-toplevel-shapes objects {:include-frames? true - :include-frame-children? false}) + (let [shapes (cph/get-immediate-children objects) to-finite (fn [val fallback] (if (not (mth/finite? val)) fallback val)) - rect (cond->> (gsh/selection-rect shapes) - (some? vport) - (gal/adjust-to-viewport vport))] + rect (cond->> (gsh/selection-rect shapes) + (some? vport) + (gal/adjust-to-viewport vport))] (-> rect (update :x to-finite 0) (update :y to-finite 0) @@ -101,11 +99,9 @@ bool-shape (bool/bool-shape shape-wrapper)] (mf/fnc bool-wrapper [{:keys [shape] :as props}] - (let [childs (mf/use-memo - (mf/deps (:id shape) objects) - (fn [] - (->> (cp/get-children (:id shape) objects) - (select-keys objects))))] + (let [childs (mf/with-memo [(:id shape) objects] + (->> (cph/get-children-ids objects (:id shape)) + (select-keys objects)))] [:& bool-shape {:shape shape :childs childs}])))) (defn svg-raw-wrapper-factory @@ -166,15 +162,12 @@ [{:keys [data width height thumbnails? embed? include-metadata?] :as props :or {embed? false include-metadata? false}}] (let [objects (:objects data) - root (get objects uuid/zero) - shapes - (->> (:shapes root) - (map #(get objects %))) + shapes (cph/get-immediate-children objects) root-children (->> shapes - (filter #(not= :frame (:type %))) - (mapcat #(cp/get-object-with-children (:id %) objects))) + (remove cph/frame-shape?) + (mapcat #(cph/get-children-with-self objects (:id %)))) vport (when (and (some? width) (some? height)) {:width width :height height}) @@ -237,7 +230,7 @@ objects (mf/with-memo [frame-id objects modifier] (let [update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier)] - (->> (cp/get-children frame-id objects) + (->> (cph/get-children-ids objects frame-id) (into [frame-id]) (reduce update-fn objects)))) @@ -280,7 +273,7 @@ (mf/use-memo (mf/deps modifier objects group-id) (fn [] - (let [modifier-ids (concat [group-id] (cp/get-children group-id objects)) + (let [modifier-ids (cons group-id (cph/get-children-ids objects group-id)) update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier) modifiers (reduce update-fn {} modifier-ids)] (gsh/merge-modifiers objects modifiers)))) @@ -334,7 +327,7 @@ (mf/use-memo (mf/deps modifier id objects) (fn [] - (let [modifier-ids (concat [id] (cp/get-children id objects)) + (let [modifier-ids (cons id (cph/get-children-ids objects id)) update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier)] (reduce update-fn objects modifier-ids)))) diff --git a/frontend/src/app/main/snap.cljs b/frontend/src/app/main/snap.cljs index 3da469e5d..862d7bbd7 100644 --- a/frontend/src/app/main/snap.cljs +++ b/frontend/src/app/main/snap.cljs @@ -10,7 +10,7 @@ [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] [app.common.math :as mth] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.uuid :refer [zero]] [app.main.refs :as refs] [app.main.worker :as uw] @@ -202,9 +202,9 @@ :frame-id (->> shapes first :frame-id) :include-frames? true :rect area-selrect}) - (rx/map #(cp/clean-loops objects %)) + (rx/map #(cph/clean-loops objects %)) (rx/map #(set/difference % (into #{} (map :id shapes)))) - (rx/map (fn [ids] (map #(get objects %) ids))))) + (rx/map #(map (d/getf objects) %)))) (defn closest-distance-snap [page-id shapes objects zoom movev] diff --git a/frontend/src/app/main/ui/render.cljs b/frontend/src/app/main/ui/render.cljs index 5542a4671..6d021f534 100644 --- a/frontend/src/app/main/ui/render.cljs +++ b/frontend/src/app/main/ui/render.cljs @@ -10,7 +10,7 @@ [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] [app.common.math :as mth] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.uuid :as uuid] [app.main.data.fonts :as df] [app.main.render :as render] @@ -60,7 +60,7 @@ (gpt/negate) (gmt/translate-matrix)) - mod-ids (cons frame-id (cp/get-children frame-id objects)) + mod-ids (cons frame-id (cph/get-children-ids objects frame-id)) updt-fn #(-> %1 (assoc-in [%2 :modifiers :displacement] modifier) (update %2 gsh/transform-shape)) @@ -133,7 +133,7 @@ [objects object-id] (if (uuid/zero? object-id) (let [object (get objects object-id) - shapes (cp/select-toplevel-shapes objects {:include-frames? true}) + shapes (cph/get-immediate-children objects) srect (gsh/selection-rect shapes) object (merge object (select-keys srect [:x :y :width :height])) object (gsh/transform-shape object) diff --git a/frontend/src/app/main/ui/viewer/handoff/render.cljs b/frontend/src/app/main/ui/viewer/handoff/render.cljs index 0f1854fc1..7aa9c7568 100644 --- a/frontend/src/app/main/ui/viewer/handoff/render.cljs +++ b/frontend/src/app/main/ui/viewer/handoff/render.cljs @@ -8,7 +8,7 @@ "The main container for a frame in handoff mode" (:require [app.common.geom.shapes :as geom] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.main.data.viewer :as dv] [app.main.store :as st] [app.main.ui.shapes.bool :as bool] @@ -116,12 +116,12 @@ (mf/fnc bool-container {::mf/wrap-props false} [props] - (let [shape (unchecked-get props "shape") - children-ids (cp/get-children (:id shape) objects) - childs (select-keys objects children-ids) - props (-> (obj/new) - (obj/merge! props) - (obj/merge! #js {:childs childs}))] + (let [shape (unchecked-get props "shape") + children (->> (cph/get-children-ids objects (:id shape)) + (select-keys objects)) + props (-> (obj/new) + (obj/merge! props) + (obj/merge! #js {:childs children}))] [:> bool-wrapper props])))) (defn svg-raw-container-factory diff --git a/frontend/src/app/main/ui/viewer/interactions.cljs b/frontend/src/app/main/ui/viewer/interactions.cljs index e60c5af34..e3e0b55b4 100644 --- a/frontend/src/app/main/ui/viewer/interactions.cljs +++ b/frontend/src/app/main/ui/viewer/interactions.cljs @@ -9,7 +9,7 @@ [app.common.data :as d] [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.spec.page :as csp] [app.main.data.comments :as dcm] [app.main.data.viewer :as dv] @@ -35,11 +35,10 @@ update-fn #(d/update-when %1 %2 assoc-in [:modifiers :displacement] modifier)] - (->> (cp/get-children frame-id objects) + (->> (cph/get-children-ids objects frame-id) (into [frame-id]) (reduce update-fn objects))))) - (mf/defc viewport {::mf/wrap [mf/memo]} [{:keys [page interactions-mode frame base-frame frame-offset size]}] diff --git a/frontend/src/app/main/ui/viewer/shapes.cljs b/frontend/src/app/main/ui/viewer/shapes.cljs index 8ccc9a145..ab39c835e 100644 --- a/frontend/src/app/main/ui/viewer/shapes.cljs +++ b/frontend/src/app/main/ui/viewer/shapes.cljs @@ -10,7 +10,7 @@ [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.geom.shapes :as geom] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.spec.interactions :as cti] [app.main.data.viewer :as dv] [app.main.refs :as refs] @@ -330,7 +330,8 @@ {::mf/wrap-props false} [props] (let [shape (unchecked-get props "shape") - childs (select-keys objects (cp/get-children (:id shape) objects)) + childs (->> (cph/get-children-ids objects (:id shape)) + (select-keys objects)) props (obj/merge! #js {} props #js {:childs childs :objects objects})] @@ -399,7 +400,7 @@ update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier) frame-id (:id frame) - modifier-ids (into [frame-id] (cp/get-children frame-id objects)) + modifier-ids (into [frame-id] (cph/get-children-ids objects frame-id)) objects (reduce update-fn objects modifier-ids) frame (assoc-in frame [:modifiers :displacement] modifier) diff --git a/frontend/src/app/main/ui/workspace/header.cljs b/frontend/src/app/main/ui/workspace/header.cljs index 17a40500d..945b29395 100644 --- a/frontend/src/app/main/ui/workspace/header.cljs +++ b/frontend/src/app/main/ui/workspace/header.cljs @@ -100,13 +100,11 @@ (mf/defc menu [{:keys [layout project file team-id page-id] :as props}] - (let [show-menu? (mf/use-state false) + (let [show-menu? (mf/use-state false) show-sub-menu? (mf/use-state false) - editing? (mf/use-state false) - - frames (mf/deref refs/workspace-frames) - + editing? (mf/use-state false) edit-input-ref (mf/use-ref nil) + frames (mf/deref refs/workspace-frames) add-shared-fn (st/emitf (dw/set-file-shared (:id file) true)) diff --git a/frontend/src/app/main/ui/workspace/shapes.cljs b/frontend/src/app/main/ui/workspace/shapes.cljs index 315d697a9..359e2c56f 100644 --- a/frontend/src/app/main/ui/workspace/shapes.cljs +++ b/frontend/src/app/main/ui/workspace/shapes.cljs @@ -12,9 +12,7 @@ others are defined using a generic wrapper implemented in common." (:require - [app.common.pages :as cp] - [app.common.uuid :as uuid] - [app.main.refs :as refs] + [app.common.pages.helpers :as cph] [app.main.ui.shapes.circle :as circle] [app.main.ui.shapes.image :as image] [app.main.ui.shapes.rect :as rect] @@ -29,7 +27,6 @@ [app.main.ui.workspace.shapes.text :as text] [app.util.object :as obj] [debug :refer [debug?]] - [okulary.core :as l] [rumext.alpha :as mf])) (declare shape-wrapper) @@ -42,31 +39,23 @@ (def image-wrapper (common/generic-wrapper-factory image/image-shape)) (def rect-wrapper (common/generic-wrapper-factory rect/rect-shape)) -(defn make-is-moving-ref - [id] - (fn [] - (let [check-moving (fn [local] - (and (= :move (:transform local)) - (contains? (:selected local) id)))] - (l/derived check-moving refs/workspace-local)))) - (mf/defc root-shape "Draws the root shape of the viewport and recursively all the shapes" {::mf/wrap-props false} [props] (let [objects (obj/get props "objects") active-frames (obj/get props "active-frames") - root-shapes (get-in objects [uuid/zero :shapes]) - shapes (->> root-shapes (mapv #(get objects %))) - - root-children (->> shapes - (filter #(not= :frame (:type %))) - (mapcat #(cp/get-object-with-children (:id %) objects)))] - + shapes (cph/get-immediate-children objects)] [:* - [:& ff/fontfaces-style {:shapes root-children}] + ;; Render font faces only for shapes that are part of the root + ;; frame but don't belongs to any other frame. + (let [xform (comp + (remove cph/frame-shape?) + (mapcat #(cph/get-children-with-self objects (:id %))))] + [:& ff/fontfaces-style {:shapes (into [] xform shapes)}]) + (for [item shapes] - (if (= (:type item) :frame) + (if (cph/frame-shape? item) [:& frame-wrapper {:shape item :key (:id item) :objects objects diff --git a/frontend/src/app/main/ui/workspace/shapes/frame.cljs b/frontend/src/app/main/ui/workspace/shapes/frame.cljs index fe79dd29e..def968464 100644 --- a/frontend/src/app/main/ui/workspace/shapes/frame.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/frame.cljs @@ -7,7 +7,7 @@ (ns app.main.ui.workspace.shapes.frame (:require [app.common.data :as d] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.main.ui.hooks :as hooks] [app.main.ui.shapes.frame :as frame] [app.main.ui.shapes.shape :refer [shape-container]] @@ -105,7 +105,7 @@ (hooks/use-equal-memo)) all-children - (-> (cp/get-children-objects (:id shape) objects) + (-> (cph/get-children objects (:id shape)) (hooks/use-equal-memo)) show-thumbnail? diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs index ca278502c..8ed877406 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs @@ -8,7 +8,7 @@ (:require [app.common.data :as d] [app.common.media :as cm] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.spec :as us] [app.common.text :as txt] [app.config :as cfg] @@ -43,18 +43,18 @@ [potok.core :as ptk] [rumext.alpha :as mf])) -; TODO: refactor to remove duplicate code and less parameter passing. -; - Move all state to [:workspace-local :assets-bar file-id :open-boxes {} -; :open-groups {} -; :reverse-sort? -; :listing-thumbs? -; :selected-assets {}] -; - Move selection code to independent functions that receive the state as a parameter. -; -; TODO: change update operations to admit multiple ids, thus avoiding the need of -; emitting many events and opening an undo transaction. Also move the logic -; of grouping, deleting, etc. to events in the data module, since now the -; selection info is in the global state. +;; TODO: refactor to remove duplicate code and less parameter passing. +;; - Move all state to [:workspace-local :assets-bar file-id :open-boxes {} +;; :open-groups {} +;; :reverse-sort? +;; :listing-thumbs? +;; :selected-assets {}] +;; - Move selection code to independent functions that receive the state as a parameter. +;; +;; TODO: change update operations to admit multiple ids, thus avoiding the need of +;; emitting many events and opening an undo transaction. Also move the logic +;; of grouping, deleting, etc. to events in the data module, since now the +;; selection info is in the global state. ;; ---- Group assets management ---- @@ -74,7 +74,7 @@ (compare (d/name key1) (d/name key2))))] (when-not (empty? assets) (reduce (fn [groups asset] - (let [path-vector (cp/split-path (or (:path asset) ""))] + (let [path-vector (cph/split-path (or (:path asset) ""))] (update-in groups (conj path-vector "") (fn [group] (if-not group @@ -86,30 +86,30 @@ (defn add-group [asset group-name] (-> (:path asset) - (cp/merge-path-item group-name) - (cp/merge-path-item (:name asset)))) + (cph/merge-path-item group-name) + (cph/merge-path-item (:name asset)))) (defn rename-group [asset path last-path] (-> (:path asset) (str/slice 0 (count path)) - (cp/split-path) + (cph/split-path) butlast (vec) (conj last-path) - (cp/join-path) + (cph/join-path) (str (str/slice (:path asset) (count path))) - (cp/merge-path-item (:name asset)))) + (cph/merge-path-item (:name asset)))) (defn ungroup [asset path] (-> (:path asset) (str/slice 0 (count path)) - (cp/split-path) + (cph/split-path) butlast - (cp/join-path) + (cph/join-path) (str (str/slice (:path asset) (count path))) - (cp/merge-path-item (:name asset)))) + (cph/merge-path-item (:name asset)))) (s/def ::asset-name ::us/not-empty-string) (s/def ::name-group-form @@ -121,8 +121,8 @@ [{:keys [path last-path accept] :as ctx :or {path "" last-path ""}}] (let [initial (mf/use-memo - (mf/deps last-path) - (constantly {:asset-name last-path})) + (mf/deps last-path) + (constantly {:asset-name last-path})) form (fm/use-form :spec ::name-group-form :initial initial) @@ -225,27 +225,27 @@ (mf/defc asset-group-title [{:keys [file-id box path group-open? on-rename on-ungroup]}] (when-not (empty? path) - (let [[other-path last-path truncated] (cp/compact-path path 35) + (let [[other-path last-path truncated] (cph/compact-path path 35) menu-state (mf/use-state auto-pos-menu-state) on-fold-group (mf/use-callback - (mf/deps file-id box path group-open?) - (fn [event] - (dom/stop-propagation event) - (st/emit! (dwl/set-assets-group-open file-id - box - path - (not group-open?))))) + (mf/deps file-id box path group-open?) + (fn [event] + (dom/stop-propagation event) + (st/emit! (dwl/set-assets-group-open file-id + box + path + (not group-open?))))) on-context-menu (mf/use-callback - (fn [event] - (swap! menu-state #(open-auto-pos-menu % event)))) + (fn [event] + (swap! menu-state #(open-auto-pos-menu % event)))) on-close-menu (mf/use-callback - (fn [] - (swap! menu-state close-auto-pos-menu)))] + (fn [] + (swap! menu-state close-auto-pos-menu)))] [:div.group-title {:class (when-not group-open? "closed") :on-click on-fold-group @@ -268,38 +268,38 @@ (mf/defc components-item [{:keys [component renaming listing-thumbs? selected-components on-asset-click on-context-menu on-drag-start do-rename cancel-rename]}] - [:div {:key (:id component) - :class-name (dom/classnames - :selected (contains? selected-components (:id component)) - :grid-cell @listing-thumbs? - :enum-item (not @listing-thumbs?)) - :id (str "component-shape-id-" (:id component)) - :draggable true - :on-click #(on-asset-click % (:id component) nil) - :on-context-menu (on-context-menu (:id component)) - :on-drag-start (partial on-drag-start component)} - [:& component-svg {:group (get-in component [:objects (:id component)]) - :objects (:objects component)}] - (let [renaming? (= renaming (:id component))] - [:& editable-label - {:class-name (dom/classnames - :cell-name @listing-thumbs? - :item-name (not @listing-thumbs?) - :editing renaming?) - :value (cp/merge-path-item (:path component) (:name component)) - :tooltip (cp/merge-path-item (:path component) (:name component)) - :display-value (if @listing-thumbs? - (:name component) - (cp/compact-name (:path component) - (:name component))) - :editing? renaming? - :disable-dbl-click? true - :on-change do-rename - :on-cancel cancel-rename}])]) + [:div {:key (:id component) + :class-name (dom/classnames + :selected (contains? selected-components (:id component)) + :grid-cell @listing-thumbs? + :enum-item (not @listing-thumbs?)) + :id (str "component-shape-id-" (:id component)) + :draggable true + :on-click #(on-asset-click % (:id component) nil) + :on-context-menu (on-context-menu (:id component)) + :on-drag-start (partial on-drag-start component)} + [:& component-svg {:group (get-in component [:objects (:id component)]) + :objects (:objects component)}] + (let [renaming? (= renaming (:id component))] + [:& editable-label + {:class-name (dom/classnames + :cell-name @listing-thumbs? + :item-name (not @listing-thumbs?) + :editing renaming?) + :value (cph/merge-path-item (:path component) (:name component)) + :tooltip (cph/merge-path-item (:path component) (:name component)) + :display-value (if @listing-thumbs? + (:name component) + (cph/compact-name (:path component) + (:name component))) + :editing? renaming? + :disable-dbl-click? true + :on-change do-rename + :on-cancel cancel-rename}])]) (mf/defc components-group [{:keys [file-id prefix groups open-groups renaming listing-thumbs? selected-components on-asset-click - on-drag-start do-rename cancel-rename on-rename-group on-ungroup on-context-menu]}] + on-drag-start do-rename cancel-rename on-rename-group on-ungroup on-context-menu]}] (let [group-open? (get open-groups prefix true)] [:* @@ -313,9 +313,9 @@ [:* (let [components (get groups "" [])] [:div {:class-name (dom/classnames - :asset-grid @listing-thumbs? - :big @listing-thumbs? - :asset-enum (not @listing-thumbs?))} + :asset-grid @listing-thumbs? + :big @listing-thumbs? + :asset-enum (not @listing-thumbs?))} (for [component components] [:& components-item {:component component :renaming renaming @@ -329,7 +329,7 @@ (for [[path-item content] groups] (when-not (empty? path-item) [:& components-group {:file-id file-id - :prefix (cp/merge-path-item prefix path-item) + :prefix (cph/merge-path-item prefix path-item) :groups content :open-groups open-groups :renaming renaming @@ -361,119 +361,119 @@ on-duplicate (mf/use-callback - (mf/deps @state) - (fn [] - (if (empty? selected-components) - (st/emit! (dwl/duplicate-component {:id (:component-id @state)})) - (do - (st/emit! (dwu/start-undo-transaction)) - (apply st/emit! (map #(dwl/duplicate-component {:id %}) selected-components)) - (st/emit! (dwu/commit-undo-transaction)))))) + (mf/deps @state) + (fn [] + (if (empty? selected-components) + (st/emit! (dwl/duplicate-component {:id (:component-id @state)})) + (do + (st/emit! (dwu/start-undo-transaction)) + (apply st/emit! (map #(dwl/duplicate-component {:id %}) selected-components)) + (st/emit! (dwu/commit-undo-transaction)))))) on-delete (mf/use-callback - (mf/deps @state file-id multi-components? multi-assets?) - (fn [] - (if (or multi-components? multi-assets?) - (on-assets-delete) - (st/emit! (dwu/start-undo-transaction) - (dwl/delete-component {:id (:component-id @state)}) - (dwl/sync-file file-id file-id) - (dwu/commit-undo-transaction))))) + (mf/deps @state file-id multi-components? multi-assets?) + (fn [] + (if (or multi-components? multi-assets?) + (on-assets-delete) + (st/emit! (dwu/start-undo-transaction) + (dwl/delete-component {:id (:component-id @state)}) + (dwl/sync-file file-id file-id) + (dwu/commit-undo-transaction))))) on-rename (mf/use-callback - (mf/deps @state) - (fn [] - (swap! state assoc :renaming (:component-id @state)))) + (mf/deps @state) + (fn [] + (swap! state assoc :renaming (:component-id @state)))) do-rename (mf/use-callback - (mf/deps @state) - (fn [new-name] - (st/emit! (dwl/rename-component (:renaming @state) new-name)) - (swap! state assoc :renaming nil))) + (mf/deps @state) + (fn [new-name] + (st/emit! (dwl/rename-component (:renaming @state) new-name)) + (swap! state assoc :renaming nil))) cancel-rename (mf/use-callback - (fn [] - (swap! state assoc :renaming nil))) + (fn [] + (swap! state assoc :renaming nil))) on-context-menu (mf/use-callback - (mf/deps selected-components on-clear-selection) - (fn [component-id] - (fn [event] - (when local? - (when-not (contains? selected-components component-id) - (on-clear-selection)) - (swap! state assoc :component-id component-id) - (swap! menu-state #(open-auto-pos-menu % event)))))) + (mf/deps selected-components on-clear-selection) + (fn [component-id] + (fn [event] + (when local? + (when-not (contains? selected-components component-id) + (on-clear-selection)) + (swap! state assoc :component-id component-id) + (swap! menu-state #(open-auto-pos-menu % event)))))) on-close-menu (mf/use-callback - (fn [] - (swap! menu-state close-auto-pos-menu))) + (fn [] + (swap! menu-state close-auto-pos-menu))) create-group (mf/use-callback - (mf/deps components selected-components on-clear-selection) - (fn [group-name] - (on-clear-selection) - (st/emit! (dwu/start-undo-transaction)) - (apply st/emit! - (->> components - (filter #(if multi-components? - (contains? selected-components (:id %)) - (= (:component-id @state) (:id %)))) - (map #(dwl/rename-component - (:id %) - (add-group % group-name))))) - (st/emit! (dwu/commit-undo-transaction)))) + (mf/deps components selected-components on-clear-selection) + (fn [group-name] + (on-clear-selection) + (st/emit! (dwu/start-undo-transaction)) + (apply st/emit! + (->> components + (filter #(if multi-components? + (contains? selected-components (:id %)) + (= (:component-id @state) (:id %)))) + (map #(dwl/rename-component + (:id %) + (add-group % group-name))))) + (st/emit! (dwu/commit-undo-transaction)))) rename-group (mf/use-callback - (mf/deps components) - (fn [path last-path] - (on-clear-selection) - (st/emit! (dwu/start-undo-transaction)) - (apply st/emit! - (->> components - (filter #(str/starts-with? (:path %) path)) - (map #(dwl/rename-component - (:id %) - (rename-group % path last-path))))) - (st/emit! (dwu/commit-undo-transaction)))) + (mf/deps components) + (fn [path last-path] + (on-clear-selection) + (st/emit! (dwu/start-undo-transaction)) + (apply st/emit! + (->> components + (filter #(str/starts-with? (:path %) path)) + (map #(dwl/rename-component + (:id %) + (rename-group % path last-path))))) + (st/emit! (dwu/commit-undo-transaction)))) on-group (mf/use-callback - (mf/deps components selected-components) - (fn [event] - (dom/stop-propagation event) - (modal/show! :name-group-dialog {:accept create-group}))) + (mf/deps components selected-components) + (fn [event] + (dom/stop-propagation event) + (modal/show! :name-group-dialog {:accept create-group}))) on-rename-group (mf/use-callback - (mf/deps components) - (fn [event path last-path] - (dom/stop-propagation event) - (modal/show! :name-group-dialog {:path path - :last-path last-path - :accept rename-group}))) + (mf/deps components) + (fn [event path last-path] + (dom/stop-propagation event) + (modal/show! :name-group-dialog {:path path + :last-path last-path + :accept rename-group}))) on-ungroup (mf/use-callback - (mf/deps components) - (fn [path] - (on-clear-selection) - (st/emit! (dwu/start-undo-transaction)) - (apply st/emit! - (->> components - (filter #(str/starts-with? (:path %) path)) - (map #(dwl/rename-component - (:id %) - (ungroup % path))))) - (st/emit! (dwu/commit-undo-transaction)))) + (mf/deps components) + (fn [path] + (on-clear-selection) + (st/emit! (dwu/start-undo-transaction)) + (apply st/emit! + (->> components + (filter #(str/starts-with? (:path %) path)) + (map #(dwl/rename-component + (:id %) + (ungroup % path))))) + (st/emit! (dwu/commit-undo-transaction)))) on-drag-start (mf/use-callback @@ -522,9 +522,9 @@ on-asset-click on-context-menu on-drag-start do-rename cancel-rename]}] [:div {:key (:id object) :class-name (dom/classnames - :selected (contains? selected-objects (:id object)) - :grid-cell @listing-thumbs? - :enum-item (not @listing-thumbs?)) + :selected (contains? selected-objects (:id object)) + :grid-cell @listing-thumbs? + :enum-item (not @listing-thumbs?)) :draggable true :on-click #(on-asset-click % (:id object) nil) :on-context-menu (on-context-menu (:id object)) @@ -535,15 +535,15 @@ (let [renaming? (= renaming (:id object))] [:& editable-label {:class-name (dom/classnames - :cell-name @listing-thumbs? - :item-name (not @listing-thumbs?) - :editing renaming?) - :value (cp/merge-path-item (:path object) (:name object)) - :tooltip (cp/merge-path-item (:path object) (:name object)) + :cell-name @listing-thumbs? + :item-name (not @listing-thumbs?) + :editing renaming?) + :value (cph/merge-path-item (:path object) (:name object)) + :tooltip (cph/merge-path-item (:path object) (:name object)) :display-value (if @listing-thumbs? (:name object) - (cp/compact-name (:path object) - (:name object))) + (cph/compact-name (:path object) + (:name object))) :editing? renaming? :disable-dbl-click? true :on-change do-rename @@ -566,8 +566,8 @@ [:* (let [objects (get groups "" [])] [:div {:class-name (dom/classnames - :asset-grid @listing-thumbs? - :asset-enum (not @listing-thumbs?))} + :asset-grid @listing-thumbs? + :asset-enum (not @listing-thumbs?))} (for [object objects] [:& graphics-item {:object object :renaming renaming @@ -581,7 +581,7 @@ (for [[path-item content] groups] (when-not (empty? path-item) [:& graphics-group {:file-id file-id - :prefix (cp/merge-path-item prefix path-item) + :prefix (cph/merge-path-item prefix path-item) :groups content :open-groups open-groups :renaming renaming @@ -638,96 +638,96 @@ on-rename (mf/use-callback - (mf/deps @state) - (fn [] - (swap! state assoc :renaming (:object-id @state)))) + (mf/deps @state) + (fn [] + (swap! state assoc :renaming (:object-id @state)))) cancel-rename (mf/use-callback - (fn [] - (swap! state assoc :renaming nil))) + (fn [] + (swap! state assoc :renaming nil))) do-rename (mf/use-callback - (mf/deps @state) - (fn [new-name] - (st/emit! (dwl/rename-media (:renaming @state) new-name)) - (swap! state assoc :renaming nil))) + (mf/deps @state) + (fn [new-name] + (st/emit! (dwl/rename-media (:renaming @state) new-name)) + (swap! state assoc :renaming nil))) on-context-menu (mf/use-callback - (mf/deps selected-objects on-clear-selection) - (fn [object-id] - (fn [event] - (when local? - (when-not (contains? selected-objects object-id) - (on-clear-selection)) - (swap! state assoc :object-id object-id) - (swap! menu-state #(open-auto-pos-menu % event)))))) + (mf/deps selected-objects on-clear-selection) + (fn [object-id] + (fn [event] + (when local? + (when-not (contains? selected-objects object-id) + (on-clear-selection)) + (swap! state assoc :object-id object-id) + (swap! menu-state #(open-auto-pos-menu % event)))))) on-close-menu (mf/use-callback - (fn [] - (swap! menu-state close-auto-pos-menu))) + (fn [] + (swap! menu-state close-auto-pos-menu))) create-group (mf/use-callback - (mf/deps objects selected-objects on-clear-selection) - (fn [group-name] - (on-clear-selection) - (st/emit! (dwu/start-undo-transaction)) - (apply st/emit! - (->> objects - (filter #(if multi-objects? - (contains? selected-objects (:id %)) - (= (:object-id @state) (:id %)))) - (map #(dwl/rename-media - (:id %) - (add-group % group-name))))) - (st/emit! (dwu/commit-undo-transaction)))) + (mf/deps objects selected-objects on-clear-selection) + (fn [group-name] + (on-clear-selection) + (st/emit! (dwu/start-undo-transaction)) + (apply st/emit! + (->> objects + (filter #(if multi-objects? + (contains? selected-objects (:id %)) + (= (:object-id @state) (:id %)))) + (map #(dwl/rename-media + (:id %) + (add-group % group-name))))) + (st/emit! (dwu/commit-undo-transaction)))) rename-group (mf/use-callback - (mf/deps objects) - (fn [path last-path] - (on-clear-selection) - (st/emit! (dwu/start-undo-transaction)) - (apply st/emit! - (->> objects - (filter #(str/starts-with? (:path %) path)) - (map #(dwl/rename-media - (:id %) - (rename-group % path last-path))))) - (st/emit! (dwu/commit-undo-transaction)))) + (mf/deps objects) + (fn [path last-path] + (on-clear-selection) + (st/emit! (dwu/start-undo-transaction)) + (apply st/emit! + (->> objects + (filter #(str/starts-with? (:path %) path)) + (map #(dwl/rename-media + (:id %) + (rename-group % path last-path))))) + (st/emit! (dwu/commit-undo-transaction)))) on-group (mf/use-callback - (mf/deps objects selected-objects) - (fn [event] - (dom/stop-propagation event) - (modal/show! :name-group-dialog {:accept create-group}))) + (mf/deps objects selected-objects) + (fn [event] + (dom/stop-propagation event) + (modal/show! :name-group-dialog {:accept create-group}))) on-rename-group (mf/use-callback - (mf/deps objects) - (fn [event path last-path] - (dom/stop-propagation event) - (modal/show! :name-group-dialog {:path path - :last-path last-path - :accept rename-group}))) + (mf/deps objects) + (fn [event path last-path] + (dom/stop-propagation event) + (modal/show! :name-group-dialog {:path path + :last-path last-path + :accept rename-group}))) on-ungroup (mf/use-callback - (mf/deps objects) - (fn [path] - (on-clear-selection) - (st/emit! (dwu/start-undo-transaction)) - (apply st/emit! - (->> objects - (filter #(str/starts-with? (:path %) path)) - (map #(dwl/rename-media - (:id %) - (ungroup % path))))) - (st/emit! (dwu/commit-undo-transaction)))) + (mf/deps objects) + (fn [path] + (on-clear-selection) + (st/emit! (dwu/start-undo-transaction)) + (apply st/emit! + (->> objects + (filter #(str/starts-with? (:path %) path)) + (map #(dwl/rename-media + (:id %) + (ungroup % path))))) + (st/emit! (dwu/commit-undo-transaction)))) on-drag-start (mf/use-callback @@ -742,39 +742,39 @@ :box :graphics :assets-count (count objects) :open? open?} - (when local? - [:& asset-section-block {:role :title-button} - [:div.assets-button {:on-click add-graphic} - i/plus - [:& file-uploader {:accept cm/str-image-types - :multi true - :ref input-ref - :on-selected on-file-selected}]]]) + (when local? + [:& asset-section-block {:role :title-button} + [:div.assets-button {:on-click add-graphic} + i/plus + [:& file-uploader {:accept cm/str-image-types + :multi true + :ref input-ref + :on-selected on-file-selected}]]]) - [:& asset-section-block {:role :content} - [:& graphics-group {:file-id file-id - :prefix "" - :groups groups - :open-groups open-groups - :renaming (:renaming @state) - :listing-thumbs? listing-thumbs? - :selected-objects selected-objects - :on-asset-click (partial on-asset-click groups) - :on-drag-start on-drag-start - :do-rename do-rename - :cancel-rename cancel-rename - :on-rename-group on-rename-group - :on-ungroup on-ungroup - :on-context-menu on-context-menu}] - (when local? - [:& auto-pos-menu - {:on-close on-close-menu - :state @menu-state - :options [(when-not (or multi-objects? multi-assets?) - [(tr "workspace.assets.rename") on-rename]) - [(tr "workspace.assets.delete") on-delete] - (when-not multi-assets? - [(tr "workspace.assets.group") on-group])]}])]])) + [:& asset-section-block {:role :content} + [:& graphics-group {:file-id file-id + :prefix "" + :groups groups + :open-groups open-groups + :renaming (:renaming @state) + :listing-thumbs? listing-thumbs? + :selected-objects selected-objects + :on-asset-click (partial on-asset-click groups) + :on-drag-start on-drag-start + :do-rename do-rename + :cancel-rename cancel-rename + :on-rename-group on-rename-group + :on-ungroup on-ungroup + :on-context-menu on-context-menu}] + (when local? + [:& auto-pos-menu + {:on-close on-close-menu + :state @menu-state + :options [(when-not (or multi-objects? multi-assets?) + [(tr "workspace.assets.rename") on-rename]) + [(tr "workspace.assets.delete") on-delete] + (when-not multi-assets? + [(tr "workspace.assets.group") on-group])]}])]])) ;; ---- Colors box ---- @@ -808,7 +808,7 @@ edit-color (fn [new-color] (let [old-data (-> (select-keys color [:id :file-id]) - (assoc :name (cp/merge-path-item (:path color) (:name color)))) + (assoc :name (cph/merge-path-item (:path color) (:name color)))) updated-color (merge new-color old-data)] (st/emit! (dwl/update-color updated-color file-id)))) @@ -856,31 +856,31 @@ on-context-menu (mf/use-callback - (mf/deps color selected-colors on-clear-selection) - (fn [event] - (when local? - (when-not (contains? selected-colors (:id color)) - (on-clear-selection)) - (swap! menu-state #(open-auto-pos-menu % event))))) + (mf/deps color selected-colors on-clear-selection) + (fn [event] + (when local? + (when-not (contains? selected-colors (:id color)) + (on-clear-selection)) + (swap! menu-state #(open-auto-pos-menu % event))))) on-close-menu (mf/use-callback - (fn [] - (swap! menu-state close-auto-pos-menu)))] + (fn [] + (swap! menu-state close-auto-pos-menu)))] (mf/use-effect - (mf/deps (:editing @state)) - #(when (:editing @state) - (let [input (mf/ref-val input-ref)] - (dom/select-text! input)) - nil)) + (mf/deps (:editing @state)) + #(when (:editing @state) + (let [input (mf/ref-val input-ref)] + (dom/select-text! input)) + nil)) [:div.asset-list-item {:class-name (dom/classnames - :selected (contains? selected-colors (:id color))) + :selected (contains? selected-colors (:id color))) :on-context-menu on-context-menu :on-click (when-not (:editing @state) #(on-asset-click % (:id color) - (partial apply-color (:id color))))} + (partial apply-color (:id color))))} [:& bc/color-bullet {:color color}] (if (:editing @state) @@ -890,7 +890,7 @@ :on-blur input-blur :on-key-down input-key-down :auto-focus true - :default-value (cp/merge-path-item (:path color) (:name color))}] + :default-value (cph/merge-path-item (:path color) (:name color))}] [:div.name-block {:on-double-click rename-color-clicked} (:name color) @@ -898,15 +898,15 @@ [:span default-name])]) (when local? [:& auto-pos-menu - {:on-close on-close-menu - :state @menu-state - :options [(when-not (or multi-colors? multi-assets?) - [(tr "workspace.assets.rename") rename-color-clicked]) - (when-not (or multi-colors? multi-assets?) - [(tr "workspace.assets.edit") edit-color-clicked]) - [(tr "workspace.assets.delete") delete-color] - (when-not multi-assets? - [(tr "workspace.assets.group") (on-group (:id color))])]}])])) + {:on-close on-close-menu + :state @menu-state + :options [(when-not (or multi-colors? multi-assets?) + [(tr "workspace.assets.rename") rename-color-clicked]) + (when-not (or multi-colors? multi-assets?) + [(tr "workspace.assets.edit") edit-color-clicked]) + [(tr "workspace.assets.delete") delete-color] + (when-not multi-assets? + [(tr "workspace.assets.group") (on-group (:id color))])]}])])) (mf/defc colors-group [{:keys [file-id prefix groups open-groups local? selected-colors @@ -945,7 +945,7 @@ (for [[path-item content] groups] (when-not (empty? path-item) [:& colors-group {:file-id file-id - :prefix (cp/merge-path-item prefix path-item) + :prefix (cph/merge-path-item prefix path-item) :key (str "group-" path-item) :groups content :open-groups open-groups @@ -995,94 +995,94 @@ create-group (mf/use-callback - (mf/deps colors selected-colors on-clear-selection file-id) - (fn [color-id] - (fn [group-name] - (on-clear-selection) - (st/emit! (dwu/start-undo-transaction)) - (apply st/emit! - (->> colors - (filter #(if multi-colors? - (contains? selected-colors (:id %)) - (= color-id (:id %)))) - (map #(dwl/update-color - (assoc % :name - (add-group % group-name)) - file-id)))) - (st/emit! (dwu/commit-undo-transaction))))) + (mf/deps colors selected-colors on-clear-selection file-id) + (fn [color-id] + (fn [group-name] + (on-clear-selection) + (st/emit! (dwu/start-undo-transaction)) + (apply st/emit! + (->> colors + (filter #(if multi-colors? + (contains? selected-colors (:id %)) + (= color-id (:id %)))) + (map #(dwl/update-color + (assoc % :name + (add-group % group-name)) + file-id)))) + (st/emit! (dwu/commit-undo-transaction))))) rename-group (mf/use-callback - (mf/deps colors) - (fn [path last-path] - (on-clear-selection) - (st/emit! (dwu/start-undo-transaction)) - (apply st/emit! - (->> colors - (filter #(str/starts-with? (:path %) path)) - (map #(dwl/update-color - (assoc % :name - (rename-group % path last-path)) - file-id)))) - (st/emit! (dwu/commit-undo-transaction)))) + (mf/deps colors) + (fn [path last-path] + (on-clear-selection) + (st/emit! (dwu/start-undo-transaction)) + (apply st/emit! + (->> colors + (filter #(str/starts-with? (:path %) path)) + (map #(dwl/update-color + (assoc % :name + (rename-group % path last-path)) + file-id)))) + (st/emit! (dwu/commit-undo-transaction)))) on-group (mf/use-callback - (mf/deps colors selected-colors) - (fn [color-id] - (fn [event] - (dom/stop-propagation event) - (modal/show! :name-group-dialog {:accept (create-group color-id)})))) + (mf/deps colors selected-colors) + (fn [color-id] + (fn [event] + (dom/stop-propagation event) + (modal/show! :name-group-dialog {:accept (create-group color-id)})))) on-rename-group (mf/use-callback - (mf/deps colors) - (fn [event path last-path] - (dom/stop-propagation event) - (modal/show! :name-group-dialog {:path path - :last-path last-path - :accept rename-group}))) + (mf/deps colors) + (fn [event path last-path] + (dom/stop-propagation event) + (modal/show! :name-group-dialog {:path path + :last-path last-path + :accept rename-group}))) on-ungroup (mf/use-callback - (mf/deps colors) - (fn [path] - (on-clear-selection) - (st/emit! (dwu/start-undo-transaction)) - (apply st/emit! - (->> colors - (filter #(str/starts-with? (:path %) path)) - (map #(dwl/update-color - (assoc % :name - (ungroup % path)) - file-id)))) - (st/emit! (dwu/commit-undo-transaction))))] + (mf/deps colors) + (fn [path] + (on-clear-selection) + (st/emit! (dwu/start-undo-transaction)) + (apply st/emit! + (->> colors + (filter #(str/starts-with? (:path %) path)) + (map #(dwl/update-color + (assoc % :name + (ungroup % path)) + file-id)))) + (st/emit! (dwu/commit-undo-transaction))))] [:& asset-section {:file-id file-id :title (tr "workspace.assets.colors") :box :colors :assets-count (count colors) :open? open?} - (when local? - [:& asset-section-block {:role :title-button} - [:div.assets-button {:on-click add-color-clicked} - i/plus]]) + (when local? + [:& asset-section-block {:role :title-button} + [:div.assets-button {:on-click add-color-clicked} + i/plus]]) - [:& asset-section-block {:role :content} - [:& colors-group {:file-id file-id - :prefix "" - :groups groups - :open-groups open-groups - :local? local? - :selected-colors selected-colors - :multi-colors? multi-colors? - :multi-assets? multi-assets? - :on-asset-click (partial on-asset-click groups) - :on-assets-delete on-assets-delete - :on-clear-selection on-clear-selection - :on-group on-group - :on-rename-group on-rename-group - :on-ungroup on-ungroup - :colors colors}]]])) + [:& asset-section-block {:role :content} + [:& colors-group {:file-id file-id + :prefix "" + :groups groups + :open-groups open-groups + :local? local? + :selected-colors selected-colors + :multi-colors? multi-colors? + :multi-assets? multi-assets? + :on-asset-click (partial on-asset-click groups) + :on-assets-delete on-assets-delete + :on-clear-selection on-clear-selection + :on-group on-group + :on-rename-group on-rename-group + :on-ungroup on-ungroup + :colors colors}]]])) ;; ---- Typography box ---- @@ -1120,7 +1120,7 @@ (for [[path-item content] groups] (when-not (empty? path-item) [:& typographies-group {:file-id file-id - :prefix (cp/merge-path-item prefix path-item) + :prefix (cph/merge-path-item prefix path-item) :groups content :open-groups open-groups :file file @@ -1169,9 +1169,9 @@ (fn [typography _event] (let [ids (wsh/lookup-selected @st/state) attrs (merge - {:typography-ref-file file-id - :typography-ref-id (:id typography)} - (dissoc typography :id :name))] + {:typography-ref-file file-id + :typography-ref-id (:id typography)} + (dissoc typography :id :name))] (run! #(st/emit! (dwt/update-text-attrs {:id % @@ -1181,80 +1181,80 @@ create-group (mf/use-callback - (mf/deps typographies selected-typographies on-clear-selection file-id) - (fn [group-name] - (on-clear-selection) - (st/emit! (dwu/start-undo-transaction)) - (apply st/emit! - (->> typographies - (filter #(if multi-typographies? - (contains? selected-typographies (:id %)) - (= (:id @state) (:id %)))) - (map #(dwl/update-typography - (assoc % :name - (add-group % group-name)) - file-id)))) - (st/emit! (dwu/commit-undo-transaction)))) + (mf/deps typographies selected-typographies on-clear-selection file-id) + (fn [group-name] + (on-clear-selection) + (st/emit! (dwu/start-undo-transaction)) + (apply st/emit! + (->> typographies + (filter #(if multi-typographies? + (contains? selected-typographies (:id %)) + (= (:id @state) (:id %)))) + (map #(dwl/update-typography + (assoc % :name + (add-group % group-name)) + file-id)))) + (st/emit! (dwu/commit-undo-transaction)))) rename-group (mf/use-callback - (mf/deps typographies) - (fn [path last-path] - (on-clear-selection) - (st/emit! (dwu/start-undo-transaction)) - (apply st/emit! - (->> typographies - (filter #(str/starts-with? (:path %) path)) - (map #(dwl/update-typography - (assoc % :name - (rename-group % path last-path)) - file-id)))) - (st/emit! (dwu/commit-undo-transaction)))) + (mf/deps typographies) + (fn [path last-path] + (on-clear-selection) + (st/emit! (dwu/start-undo-transaction)) + (apply st/emit! + (->> typographies + (filter #(str/starts-with? (:path %) path)) + (map #(dwl/update-typography + (assoc % :name + (rename-group % path last-path)) + file-id)))) + (st/emit! (dwu/commit-undo-transaction)))) on-group (mf/use-callback - (mf/deps typographies selected-typographies) - (fn [event] - (dom/stop-propagation event) - (modal/show! :name-group-dialog {:accept create-group}))) + (mf/deps typographies selected-typographies) + (fn [event] + (dom/stop-propagation event) + (modal/show! :name-group-dialog {:accept create-group}))) on-rename-group (mf/use-callback - (mf/deps typographies) - (fn [event path last-path] - (dom/stop-propagation event) - (modal/show! :name-group-dialog {:path path - :last-path last-path - :accept rename-group}))) + (mf/deps typographies) + (fn [event path last-path] + (dom/stop-propagation event) + (modal/show! :name-group-dialog {:path path + :last-path last-path + :accept rename-group}))) on-ungroup (mf/use-callback - (mf/deps typographies) - (fn [path] - (on-clear-selection) - (st/emit! (dwu/start-undo-transaction)) - (apply st/emit! - (->> typographies - (filter #(str/starts-with? (:path %) path)) - (map #(dwl/update-typography - (assoc % :name - (ungroup % path)) - file-id)))) - (st/emit! (dwu/commit-undo-transaction)))) + (mf/deps typographies) + (fn [path] + (on-clear-selection) + (st/emit! (dwu/start-undo-transaction)) + (apply st/emit! + (->> typographies + (filter #(str/starts-with? (:path %) path)) + (map #(dwl/update-typography + (assoc % :name + (ungroup % path)) + file-id)))) + (st/emit! (dwu/commit-undo-transaction)))) on-context-menu (mf/use-callback - (mf/deps selected-typographies on-clear-selection) - (fn [id event] - (when local? - (when-not (contains? selected-typographies id) - (on-clear-selection)) - (swap! state assoc :id id) - (swap! menu-state #(open-auto-pos-menu % event))))) + (mf/deps selected-typographies on-clear-selection) + (fn [id event] + (when local? + (when-not (contains? selected-typographies id) + (on-clear-selection)) + (swap! state assoc :id id) + (swap! menu-state #(open-auto-pos-menu % event))))) on-close-menu (mf/use-callback - (fn [] - (swap! menu-state close-auto-pos-menu))) + (fn [] + (swap! menu-state close-auto-pos-menu))) handle-rename-typography-clicked (fn [] @@ -1291,40 +1291,40 @@ :box :typographies :assets-count (count typographies) :open? open?} + (when local? + [:& asset-section-block {:role :title-button} + [:div.assets-button {:on-click add-typography} + i/plus]]) + + [:& asset-section-block {:role :content} + [:& typographies-group {:file-id file-id + :prefix "" + :groups groups + :open-groups open-groups + :state state + :file file + :local? local? + :selected-typographies selected-typographies + :editing-id editing-id + :local-data local-data + :on-asset-click (partial on-asset-click groups) + :handle-change handle-change + :apply-typography apply-typography + :on-rename-group on-rename-group + :on-ungroup on-ungroup + :on-context-menu on-context-menu}] + (when local? - [:& asset-section-block {:role :title-button} - [:div.assets-button {:on-click add-typography} - i/plus]]) - - [:& asset-section-block {:role :content} - [:& typographies-group {:file-id file-id - :prefix "" - :groups groups - :open-groups open-groups - :state state - :file file - :local? local? - :selected-typographies selected-typographies - :editing-id editing-id - :local-data local-data - :on-asset-click (partial on-asset-click groups) - :handle-change handle-change - :apply-typography apply-typography - :on-rename-group on-rename-group - :on-ungroup on-ungroup - :on-context-menu on-context-menu}] - - (when local? - [:& auto-pos-menu - {:on-close on-close-menu - :state @menu-state - :options [(when-not (or multi-typographies? multi-assets?) - [(tr "workspace.assets.rename") handle-rename-typography-clicked]) - (when-not (or multi-typographies? multi-assets?) - [(tr "workspace.assets.edit") handle-edit-typography-clicked]) - [(tr "workspace.assets.delete") handle-delete-typography] - (when-not multi-assets? - [(tr "workspace.assets.group") on-group])]}])]])) + [:& auto-pos-menu + {:on-close on-close-menu + :state @menu-state + :options [(when-not (or multi-typographies? multi-assets?) + [(tr "workspace.assets.rename") handle-rename-typography-clicked]) + (when-not (or multi-typographies? multi-assets?) + [(tr "workspace.assets.edit") handle-edit-typography-clicked]) + [(tr "workspace.assets.delete") handle-delete-typography] + (when-not multi-assets? + [(tr "workspace.assets.group") on-group])]}])]])) ;; --- Assets toolbox ---- @@ -1377,12 +1377,12 @@ (filter (fn [item] (or (matches-search (:name item "!$!") (:term filters)) (matches-search (:value item "!$!") (:term filters))))) - ; Sort by folder order, but putting all "root" items always first, - ; independently of sort order. - (sort-by #(str/lower (cp/merge-path-item (if (empty? (:path %)) - (if reverse-sort? "z" "a") - (:path %)) - (:name %))) + ; Sort by folder order, but putting all "root" items always first, + ; independently of sort order. + (sort-by #(str/lower (cph/merge-path-item (if (empty? (:path %)) + (if reverse-sort? "z" "a") + (:path %)) + (:name %))) comp-fn)))) (mf/defc file-library @@ -1528,16 +1528,16 @@ (if local? [:* - [:span (tr "workspace.assets.file-library")] - (when shared? - [:span.tool-badge (tr "workspace.assets.shared")])] + [:span (tr "workspace.assets.file-library")] + (when shared? + [:span.tool-badge (tr "workspace.assets.shared")])] [:* - [:span (:name file)] - [:span.tool-link.tooltip.tooltip-left {:alt "Open library file"} - [:a {:href (str "#" url) - :target "_blank" - :on-click dom/stop-propagation} - i/chain]]])] + [:span (:name file)] + [:span.tool-link.tooltip.tooltip-left {:alt "Open library file"} + [:a {:href (str "#" url) + :target "_blank" + :on-click dom/stop-propagation} + i/chain]]])] (when open? (let [show-components? (and (or (= (:box filters) :all) @@ -1658,33 +1658,33 @@ [:div.assets-bar [:div.tool-window - [:div.tool-window-content - [:div.assets-bar-title - (tr "workspace.assets.assets") - [:div.libraries-button {:on-click #(modal/show! :libraries-dialog {})} - i/text-align-justify - (tr "workspace.assets.libraries")]] + [:div.tool-window-content + [:div.assets-bar-title + (tr "workspace.assets.assets") + [:div.libraries-button {:on-click #(modal/show! :libraries-dialog {})} + i/text-align-justify + (tr "workspace.assets.libraries")]] - [:div.search-block - [:input.search-input - {:placeholder (tr "workspace.assets.search") - :type "text" - :value (:term @filters) - :on-change on-search-term-change}] - (if (str/empty? (:term @filters)) - [:div.search-icon - i/search] - [:div.search-icon.close - {:on-click on-search-clear-click} - i/close])] + [:div.search-block + [:input.search-input + {:placeholder (tr "workspace.assets.search") + :type "text" + :value (:term @filters) + :on-change on-search-term-change}] + (if (str/empty? (:term @filters)) + [:div.search-icon + i/search] + [:div.search-icon.close + {:on-click on-search-clear-click} + i/close])] - [:select.input-select {:value (:box @filters) - :on-change on-box-filter-change} - [:option {:value ":all"} (tr "workspace.assets.box-filter-all")] - [:option {:value ":components"} (tr "workspace.assets.components")] - [:option {:value ":graphics"} (tr "workspace.assets.graphics")] - [:option {:value ":colors"} (tr "workspace.assets.colors")] - [:option {:value ":typographies"} (tr "workspace.assets.typography")]]]] + [:select.input-select {:value (:box @filters) + :on-change on-box-filter-change} + [:option {:value ":all"} (tr "workspace.assets.box-filter-all")] + [:option {:value ":components"} (tr "workspace.assets.components")] + [:option {:value ":graphics"} (tr "workspace.assets.graphics")] + [:option {:value ":colors"} (tr "workspace.assets.colors")] + [:option {:value ":typographies"} (tr "workspace.assets.typography")]]]] [:div.libraries-wrapper [:& file-library diff --git a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs index e18483c09..9e65bbf54 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs @@ -7,7 +7,7 @@ (ns app.main.ui.workspace.sidebar.layers (:require [app.common.data :as d] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.uuid :as uuid] [app.main.data.workspace :as dw] [app.main.data.workspace.common :as dwc] @@ -58,18 +58,16 @@ (when (kbd/enter? event) (accept-edit)) (when (kbd/esc? event) (cancel-edit)))] - (mf/use-effect - (mf/deps shape-for-rename) - #(when (and (= shape-for-rename (:id shape)) - (not (:edition @local))) - (start-edit))) + (mf/with-effect [shape-for-rename] + (when (and (= shape-for-rename (:id shape)) + (not (:edition @local))) + (start-edit))) - (mf/use-effect - (mf/deps (:edition @local)) - #(when (:edition @local) - (let [name-input (mf/ref-val name-ref)] - (dom/select-text! name-input)) - nil)) + (mf/with-effect [(:edition @local)] + (when (:edition @local) + (let [name-input (mf/ref-val name-ref)] + (dom/select-text! name-input) + nil))) (if (:edition @local) [:input.element-name @@ -92,9 +90,10 @@ (mf/defc layer-item [{:keys [index item selected objects] :as props}] - (let [id (:id item) - selected? (contains? selected id) - container? (or (= (:type item) :frame) (= (:type item) :group)) + (let [id (:id item) + selected? (contains? selected id) + container? (or (cph/frame-shape? item) + (cph/group-shape? item)) disable-drag (mf/use-state false) @@ -160,7 +159,7 @@ (if (= side :center) (st/emit! (dw/relocate-selected-shapes (:id item) 0)) (let [to-index (if (= side :top) (inc index) index) - parent-id (cp/get-parent (:id item) objects)] + parent-id (cph/get-parent-id objects (:id item))] (st/emit! (dw/relocate-selected-shapes parent-id to-index))))) on-hold diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.cljs index 8710ff7d5..4552b3c40 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.cljs @@ -6,7 +6,7 @@ (ns app.main.ui.workspace.sidebar.options.menus.component (:require - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.main.data.modal :as modal] [app.main.data.workspace :as dw] [app.main.data.workspace.libraries :as dwl] @@ -16,7 +16,7 @@ [app.main.ui.context :as ctx] [app.main.ui.icons :as i] [app.util.dom :as dom] - [app.util.i18n :as i18n :refer [t]] + [app.util.i18n :as i18n :refer [tr]] [rumext.alpha :as mf])) (def component-attrs [:component-id :component-file :shape-ref]) @@ -25,47 +25,59 @@ [{:keys [ids values] :as props}] (let [current-file-id (mf/use-ctx ctx/current-file-id) - id (first ids) - locale (mf/deref i18n/locale) - local (mf/use-state {:menu-open false}) + id (first ids) + local (mf/use-state {:menu-open false}) - show? (some? (:component-id values)) - local-library (mf/deref refs/workspace-local-library) - libraries (mf/deref refs/workspace-libraries) - {:keys [component-id component-file]} values + component-id (:component-id values) + library-id (:component-file values) - component (cp/get-component component-id component-file local-library libraries) + local-file (deref refs/workspace-local-library) + libraries (deref refs/workspace-libraries) - on-menu-click (mf/use-callback - (fn [event] - (dom/prevent-default event) - (dom/stop-propagation event) - (swap! local assoc :menu-open true))) + ;; NOTE: this is necessary because the `cph/get-component` + ;; expects a map of all libraries, including the local one. + libraries (assoc libraries (:id local-file) local-file) - on-menu-close (mf/use-callback - #(swap! local assoc :menu-open false)) + component (cph/get-component libraries library-id component-id) + show? (some? component-id) - do-detach-component (st/emitf (dwl/detach-component id)) - do-reset-component (st/emitf (dwl/reset-component id)) - do-update-component (st/emitf (dwl/update-component-sync id component-file)) + on-menu-click + (mf/use-callback + (fn [event] + (dom/prevent-default event) + (dom/stop-propagation event) + (swap! local assoc :menu-open true))) + + on-menu-close + (mf/use-callback + #(swap! local assoc :menu-open false)) + + do-detach-component + (st/emitf (dwl/detach-component id)) + + do-reset-component + (st/emitf (dwl/reset-component id)) + + do-update-component + (st/emitf (dwl/update-component-sync id library-id)) do-update-remote-component (st/emitf (modal/show {:type :confirm :message "" - :title (t locale "modals.update-remote-component.message") - :hint (t locale "modals.update-remote-component.hint") - :cancel-label (t locale "modals.update-remote-component.cancel") - :accept-label (t locale "modals.update-remote-component.accept") + :title (tr "modals.update-remote-component.message") + :hint (tr "modals.update-remote-component.hint") + :cancel-label (tr "modals.update-remote-component.cancel") + :accept-label (tr "modals.update-remote-component.accept") :accept-style :primary :on-accept do-update-component})) do-show-component (st/emitf (dw/go-to-component component-id)) - do-navigate-component-file (st/emitf (dwl/nav-to-component-file component-file))] + do-navigate-component-file (st/emitf (dwl/nav-to-component-file library-id))] (when show? [:div.element-set [:div.element-set-title - [:span (t locale "workspace.options.component")]] + [:span (tr "workspace.options.component")]] [:div.element-set-content [:div.row-flex.component-row i/component @@ -78,14 +90,14 @@ ;; app/main/ui/workspace/context_menu.cljs [:& context-menu {:on-close on-menu-close :show (:menu-open @local) - :options (if (= (:component-file values) current-file-id) - [[(t locale "workspace.shape.menu.detach-instance") do-detach-component] - [(t locale "workspace.shape.menu.reset-overrides") do-reset-component] - [(t locale "workspace.shape.menu.update-main") do-update-component] - [(t locale "workspace.shape.menu.show-main") do-show-component]] + :options (if (= library-id current-file-id) + [[(tr "workspace.shape.menu.detach-instance") do-detach-component] + [(tr "workspace.shape.menu.reset-overrides") do-reset-component] + [(tr "workspace.shape.menu.update-main") do-update-component] + [(tr "workspace.shape.menu.show-main") do-show-component]] - [[(t locale "workspace.shape.menu.detach-instance") do-detach-component] - [(t locale "workspace.shape.menu.reset-overrides") do-reset-component] - [(t locale "workspace.shape.menu.go-main") do-navigate-component-file] - [(t locale "workspace.shape.menu.update-main") do-update-remote-component]])}]]]]]))) + [[(tr "workspace.shape.menu.detach-instance") do-detach-component] + [(tr "workspace.shape.menu.reset-overrides") do-reset-component] + [(tr "workspace.shape.menu.go-main") do-navigate-component-file] + [(tr "workspace.shape.menu.update-main") do-update-remote-component]])}]]]]]))) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs index 598fea72f..a37c968fb 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs @@ -7,7 +7,7 @@ (ns app.main.ui.workspace.sidebar.options.menus.interactions (:require [app.common.data :as d] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.spec.interactions :as csi] [app.common.spec.page :as csp] [app.common.uuid :as uuid] @@ -178,10 +178,10 @@ (mf/defc interaction-entry [{:keys [index shape interaction update-interaction remove-interaction]}] - (let [objects (deref refs/workspace-page-objects) - destination (get objects (:destination interaction)) - frames (mf/use-memo (mf/deps objects) - #(cp/select-frames objects)) + (let [objects (deref refs/workspace-page-objects) + destination (get objects (:destination interaction)) + frames (mf/with-memo [objects] + (cph/get-frames objects)) overlay-pos-type (:overlay-pos-type interaction) close-click-outside? (:close-click-outside interaction false) @@ -190,10 +190,10 @@ way (-> interaction :animation :way) direction (-> interaction :animation :direction) - extended-open? (mf/use-state false) + extended-open? (mf/use-state false) - ext-delay-ref (mf/use-ref nil) - ext-duration-ref (mf/use-ref nil) + ext-delay-ref (mf/use-ref nil) + ext-duration-ref (mf/use-ref nil) select-text (fn [ref] (fn [_] (dom/select-text! (mf/ref-val ref)))) @@ -550,7 +550,7 @@ [:& page-flows {:flows flows}]) [:div.element-set.interactions-options - (when (and shape (not (cp/unframed-shape? shape))) + (when (and shape (not (cph/unframed-shape? shape))) [:div.element-set-title [:span (tr "workspace.options.interactions")] [:div.add-page {:on-click add-interaction} @@ -558,7 +558,7 @@ [:div.element-set-content (when (= (count interactions) 0) [:* - (when (and shape (not (cp/unframed-shape? shape))) + (when (and shape (not (cph/unframed-shape? shape))) [:* [:div.interactions-help-icon i/plus] [:div.interactions-help.separator (tr "workspace.options.add-interaction")]]) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs index 088bbbd84..8ab07deac 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs @@ -9,7 +9,7 @@ ["react-virtualized" :as rvt] [app.common.data :as d] [app.common.exceptions :as ex] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.text :as txt] [app.main.data.fonts :as fts] [app.main.data.shortcuts :as dsc] @@ -575,7 +575,7 @@ [:input.element-name.adv-typography-name {:type "text" :ref name-input-ref - :default-value (cp/merge-path-item (:path typography) (:name typography)) + :default-value (cph/merge-path-item (:path typography) (:name typography)) :on-blur on-name-blur :on-change on-name-change}] diff --git a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs index 49c1d9315..af3180260 100644 --- a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs @@ -8,7 +8,7 @@ (:require [app.common.data :as d] [app.common.geom.shapes :as gsh] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.main.data.shortcuts :as dsc] [app.main.data.workspace :as dw] [app.main.data.workspace.path.shortcuts :as psc] @@ -154,13 +154,13 @@ selected (mf/ref-val selected-ref) - remove-xfm (mapcat #(cp/get-parents % objects)) + remove-xfm (mapcat #(cph/get-parent-ids objects %)) remove-id? (cond-> (into #{} remove-xfm selected) @ctrl? (into (filter is-group?) ids)) hover-shape (->> ids - (filterv (comp not remove-id?)) + (filter (comp not remove-id?)) (first) (get objects))] (reset! hover hover-shape) diff --git a/frontend/src/app/main/ui/workspace/viewport/interactions.cljs b/frontend/src/app/main/ui/workspace/viewport/interactions.cljs index 780c223a5..590b392a2 100644 --- a/frontend/src/app/main/ui/workspace/viewport/interactions.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/interactions.cljs @@ -9,7 +9,7 @@ (:require [app.common.data :as d] [app.common.geom.shapes :as gsh] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.spec.interactions :as cti] [app.main.data.workspace :as dw] [app.main.refs :as refs] @@ -210,7 +210,7 @@ (st/emit! (dw/start-move-overlay-pos index)))] (when dest-shape - (let [orig-frame (cp/get-frame orig-shape objects) + (let [orig-frame (cph/get-frame objects orig-shape) marker-x (+ (:x orig-frame) (:x position)) marker-y (+ (:y orig-frame) (:y position)) width (:width dest-shape) @@ -326,7 +326,7 @@ :objects objects :hover-disabled? hover-disabled?}]))]))) (when (and shape - (not (cp/unframed-shape? shape)) + (not (cph/unframed-shape? shape)) (not (#{:move :rotate} current-transform))) [:& interaction-handle {:key (:id shape) :index nil diff --git a/frontend/src/app/main/ui/workspace/viewport/outline.cljs b/frontend/src/app/main/ui/workspace/viewport/outline.cljs index f525bb31f..95d58b016 100644 --- a/frontend/src/app/main/ui/workspace/viewport/outline.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/outline.cljs @@ -8,7 +8,7 @@ (:require [app.common.exceptions :as ex] [app.common.geom.shapes :as gsh] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.main.refs :as refs] [app.util.object :as obj] [app.util.path.format :as upf] @@ -89,7 +89,7 @@ transform (mf/deref refs/current-transform) outlines-ids (->> (set/union selected hover) - (cp/clean-loops objects)) + (cph/clean-loops objects)) show-outline? (fn [shape] (and (not (:hidden shape)) (not (:blocked shape)))) diff --git a/frontend/src/app/main/ui/workspace/viewport/scroll_bars.cljs b/frontend/src/app/main/ui/workspace/viewport/scroll_bars.cljs index 61830c566..3de69d6b2 100644 --- a/frontend/src/app/main/ui/workspace/viewport/scroll_bars.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/scroll_bars.cljs @@ -50,13 +50,10 @@ vbox-x (:x vbox) vbox-y (:y vbox) - base-objects-rect - (mf/use-memo - (mf/deps objects) - (fn [] - (let [root-shapes (-> objects cph/get-top-frame :shapes) - shapes (->> root-shapes (mapv #(get objects %)))] - (gsh/selection-rect shapes)))) + base-objects-rect (mf/with-memo [objects] + (-> objects + (cph/get-immediate-children) + (gsh/selection-rect))) inv-zoom (/ 1 zoom) vbox-height (- (:height vbox) (* inv-zoom scroll-height)) 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 cf990d062..ca450b2a8 100644 --- a/frontend/src/app/main/ui/workspace/viewport/snap_distances.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/snap_distances.cljs @@ -9,7 +9,7 @@ [app.common.data :as d] [app.common.geom.shapes :as gsh] [app.common.math :as mth] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.main.refs :as refs] [app.main.worker :as uw] [beicon.core :as rx] @@ -225,7 +225,7 @@ :frame-id (:id frame) :include-frames? true :rect rect}) - (rx/map #(cp/clean-loops @refs/workspace-page-objects %)) + (rx/map #(cph/clean-loops @refs/workspace-page-objects %)) (rx/map #(set/difference % selected)) (rx/map #(->> % (map (partial get @refs/workspace-page-objects))))) (rx/of nil))))] diff --git a/frontend/src/app/main/ui/workspace/viewport/snap_points.cljs b/frontend/src/app/main/ui/workspace/viewport/snap_points.cljs index d36109911..e5a63b11d 100644 --- a/frontend/src/app/main/ui/workspace/viewport/snap_points.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/snap_points.cljs @@ -9,7 +9,8 @@ [app.common.data :as d] [app.common.geom.shapes :as gsh] [app.common.math :as mth] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] + [app.common.spec :as us] [app.main.snap :as snap] [app.util.geom.snap-points :as sp] [beicon.core :as rx] @@ -151,18 +152,14 @@ (mf/defc snap-points {::mf/wrap [mf/memo]} [{:keys [layout zoom objects selected page-id drawing transform modifiers] :as props}] - - (let [shapes (into [] (keep (d/getf objects)) selected) + (us/assert set? selected) + (let [shapes (into [] (keep (d/getf objects)) selected) filter-shapes - (into #{} - (comp (mapcat #(cp/get-object-with-children % objects)) - (map :id)) - selected) + (into selected (mapcat #(cph/get-children-ids objects %)) selected) - remove-snap? (mf/use-memo - (mf/deps layout filter-shapes) - #(snap/make-remove-snap layout filter-shapes)) + remove-snap? (mf/with-memo [layout filter-shapes] + (snap/make-remove-snap layout filter-shapes)) shapes (if drawing [drawing] shapes)] (when (or drawing transform) diff --git a/frontend/src/app/main/ui/workspace/viewport/widgets.cljs b/frontend/src/app/main/ui/workspace/viewport/widgets.cljs index 2a1e9df0f..507d8fc67 100644 --- a/frontend/src/app/main/ui/workspace/viewport/widgets.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/widgets.cljs @@ -8,7 +8,7 @@ (:require [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.main.data.workspace :as dw] [app.main.data.workspace.interactions :as dwi] [app.main.refs :as refs] @@ -161,7 +161,7 @@ on-frame-enter (unchecked-get props "on-frame-enter") on-frame-leave (unchecked-get props "on-frame-leave") on-frame-select (unchecked-get props "on-frame-select") - frames (cp/select-frames objects)] + frames (cph/get-frames objects)] [:g.frame-titles (for [frame frames] diff --git a/frontend/src/app/util/snap_data.cljs b/frontend/src/app/util/snap_data.cljs index 6c667c217..95e0675db 100644 --- a/frontend/src/app/util/snap_data.cljs +++ b/frontend/src/app/util/snap_data.cljs @@ -10,8 +10,8 @@ https://en.wikipedia.org/wiki/Range_tree" (:require [app.common.data :as d] - [app.common.pages :as cp] [app.common.pages.diff :as diff] + [app.common.pages.helpers :as cph] [app.common.uuid :as uuid] [app.util.geom.grid :as gg] [app.util.geom.snap-points :as snap] @@ -187,9 +187,9 @@ (defn add-page "Adds page information" [snap-data {:keys [objects options] :as page}] - - (let [frames (cp/select-frames objects) - shapes (cp/select-objects #(not= :frame (:type %)) page) + (let [frames (cph/get-frames objects) + shapes (->> (vals (:objects page)) + (remove cph/frame-shape?)) guides (vals (:guides options)) page-data @@ -233,7 +233,7 @@ (reduce remove-guide $ removed-guides) (reduce update-guide $ updated-guides) (reduce add-guide $ new-guides))))) - + ;; Page doesn't exist, we create a new entry (add-page snap-data page))) diff --git a/frontend/src/app/worker/selection.cljs b/frontend/src/app/worker/selection.cljs index ed0412f86..30879d60b 100644 --- a/frontend/src/app/worker/selection.cljs +++ b/frontend/src/app/worker/selection.cljs @@ -9,6 +9,7 @@ [app.common.data :as d] [app.common.geom.shapes :as gsh] [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.uuid :as uuid] [app.util.quadtree :as qdt] [app.worker.impl :as impl] @@ -86,7 +87,7 @@ changed-ids (into #{} (comp (filter #(not= % uuid/zero)) (filter changes?) - (mapcat #(into [%] (cp/get-children % new-objects)))) + (mapcat #(into [%] (cph/get-children-ids new-objects %)))) (set/union (set (keys old-objects)) (set (keys new-objects)))) diff --git a/frontend/src/debug.cljs b/frontend/src/debug.cljs index 50f93a7bd..9c5cbbe07 100644 --- a/frontend/src/debug.cljs +++ b/frontend/src/debug.cljs @@ -8,11 +8,11 @@ (:require [app.common.data :as d] [app.common.math :as mth] - [app.common.pages :as cp] + [app.common.pages.helpers :as cph] [app.common.transit :as t] [app.common.uuid :as uuid] [app.main.data.workspace :as dw] - [app.main.data.workspace.changes :as dwc] + [app.main.data.workspace.changes :as dwc] [app.main.store :as st] [app.util.object :as obj] [app.util.timers :as timers] @@ -208,7 +208,7 @@ (show-component [shape objects] (if (nil? (:shape-ref shape)) "" - (let [root-shape (cp/get-component-shape shape objects) + (let [root-shape (cph/get-component-shape objects shape) component-id (when root-shape (:component-id root-shape)) component-file-id (when root-shape (:component-file root-shape)) component-file (when component-file-id (get libraries component-file-id nil)) diff --git a/frontend/test/app/components_basic_test.cljs b/frontend/test/app/components_basic_test.cljs index 6a22c61be..7b8138e25 100644 --- a/frontend/test/app/components_basic_test.cljs +++ b/frontend/test/app/components_basic_test.cljs @@ -197,13 +197,10 @@ "Renamed component")) (rx/do (fn [new-state] - (let [file (dwlh/get-local-file new-state) - component (cph/get-component - (:component-id instance1) - (:component-file instance1) - file - {})] - + (let [libs (dwlh/get-libraries new-state) + component (cph/get-component libs + (:component-file instance1) + (:component-id instance1))] (t/is (= (:name component) "Renamed component"))))) @@ -274,13 +271,10 @@ new-state (:id instance1)) - file (dwlh/get-local-file new-state) - component (cph/get-component - (:component-id instance1) - (:component-file instance1) - file - {})] - + libs (dwlh/get-libraries new-state) + component (cph/get-component libs + (:component-file instance1) + (:component-id instance1))] (t/is (nil? component))))) (rx/subs done #(throw %)))))) diff --git a/frontend/test/app/components_sync_test.cljs b/frontend/test/app/components_sync_test.cljs index 033ab60c1..29ea86996 100644 --- a/frontend/test/app/components_sync_test.cljs +++ b/frontend/test/app/components_sync_test.cljs @@ -3,7 +3,6 @@ [app.common.colors :as clr] [app.common.data :as d] [app.common.geom.point :as gpt] - [app.common.pages.helpers :as cph] [app.main.data.workspace.changes :as dwc] [app.main.data.workspace.libraries :as dwl] [app.main.data.workspace.libraries-helpers :as dwlh] diff --git a/frontend/test/app/test_helpers/libraries.cljs b/frontend/test/app/test_helpers/libraries.cljs index b93f81f2a..a49faa518 100644 --- a/frontend/test/app/test_helpers/libraries.cljs +++ b/frontend/test/app/test_helpers/libraries.cljs @@ -7,7 +7,6 @@ [app.common.uuid :as uuid] [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] - [app.common.pages :as cp] [app.common.pages.helpers :as cph] [app.main.data.workspace :as dw] [app.main.data.workspace.libraries-helpers :as dwlh] @@ -55,26 +54,22 @@ (defn resolve-instance [state root-inst-id] - (let [page (thp/current-page state) - root-inst (cph/get-shape page root-inst-id) - shapes-inst (cph/get-object-with-children - root-inst-id - (:objects page))] - + (let [page (thp/current-page state) + root-inst (cph/get-shape page root-inst-id) + shapes-inst (cph/get-children-with-self (:objects page) + root-inst-id)] ;; Validate that the instance tree is well constructed - (t/is (is-instance-root (first shapes-inst))) + (is-instance-root (first shapes-inst)) (run! is-instance-child (rest shapes-inst)) shapes-inst)) (defn resolve-noninstance [state root-inst-id] - (let [page (thp/current-page state) - root-inst (cph/get-shape page root-inst-id) - shapes-inst (cph/get-object-with-children - root-inst-id - (:objects page))] - + (let [page (thp/current-page state) + root-inst (cph/get-shape page root-inst-id) + shapes-inst (cph/get-children-with-self (:objects page) + root-inst-id)] ;; Validate that the tree is not an instance (run! is-noninstance shapes-inst) @@ -82,31 +77,23 @@ (defn resolve-instance-and-main [state root-inst-id] - (let [page (thp/current-page state) - root-inst (cph/get-shape page root-inst-id) + (let [page (thp/current-page state) + root-inst (cph/get-shape page root-inst-id) - file (dwlh/get-local-file state) - component (cph/get-component - (:component-id root-inst) - (:id file) - file - nil) + libs (dwlh/get-libraries state) + component (cph/get-component libs (:component-id root-inst)) - shapes-inst (cph/get-object-with-children - root-inst-id - (:objects page)) - shapes-main (cph/get-object-with-children - (:shape-ref root-inst) - (:objects component)) + shapes-inst (cph/get-children-with-self (:objects page) root-inst-id) + shapes-main (cph/get-children-with-self (:objects component) (:shape-ref root-inst)) - unique-refs (into #{} (map :shape-ref shapes-inst)) + unique-refs (into #{} (map :shape-ref) shapes-inst) - main-exists? (fn [shape] - (t/is (some #(= (:id %) (:shape-ref shape)) - shapes-main)))] + main-exists? (fn [shape] + (t/is (some #(= (:id %) (:shape-ref shape)) + shapes-main)))] ;; Validate that the instance tree is well constructed - (t/is (is-instance-root (first shapes-inst))) + (is-instance-root (first shapes-inst)) (run! is-instance-child (rest shapes-inst)) (run! is-noninstance shapes-main) (t/is (= (count shapes-inst) @@ -118,20 +105,11 @@ (defn resolve-component [state component-id] - (let [page (thp/current-page state) - - file (dwlh/get-local-file state) - component (cph/get-component - component-id - (:id file) - file - nil) - - root-main (cph/get-component-root - component) - shapes-main (cph/get-object-with-children - (:id root-main) - (:objects component))] + (let [page (thp/current-page state) + libs (dwlh/get-libraries state) + component (cph/get-component libs component-id) + root-main (cph/get-component-root component) + shapes-main (cph/get-children-with-self (:objects component) (:id root-main))] ;; Validate that the component tree is well constructed (run! is-noninstance shapes-main) diff --git a/frontend/test/app/test_helpers/pages.cljs b/frontend/test/app/test_helpers/pages.cljs index 9f3af5f33..e16fed14b 100644 --- a/frontend/test/app/test_helpers/pages.cljs +++ b/frontend/test/app/test_helpers/pages.cljs @@ -66,7 +66,7 @@ ([state label type] (sample-shape state type {})) ([state label type props] (let [page (current-page state) - frame (cph/get-top-frame (:objects page)) + frame (cph/get-frame (:objects page)) shape (-> (cp/make-minimal-shape type) (gsh/setup {:x 0 :y 0 :width 1 :height 1}) (merge props))]