diff --git a/CHANGES.md b/CHANGES.md index abac9d19d..14e62ec6b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,7 +4,7 @@ ### :sparkles: New features -- Allow for nested boards inside other boards and groups +- Allow for nested and rotated boards inside other boards and groups [Taiga #2874](https://tree.taiga.io/project/penpot/us/2874?milestone=319982) ### :bug: Bugs fixed ### :arrow_up: Deps updates diff --git a/common/src/app/common/pages/helpers.cljc b/common/src/app/common/pages/helpers.cljc index 4841e4700..442c43b47 100644 --- a/common/src/app/common/pages/helpers.cljc +++ b/common/src/app/common/pages/helpers.cljc @@ -153,30 +153,23 @@ (:shapes) (keep lookup))))) -(defn get-frames-ids - "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 (remove #(= uuid/zero %)) - (keep lookup) - (filter frame-shape?) - (map :id))] - (->> (keys objects) - (into [] xform)))) - (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." + "Retrieves all frame objects as vector" [objects] - (let [lookup (d/getf objects) - xform (comp (remove #(= uuid/zero %)) - (keep lookup) - (filter frame-shape?))] - (->> (keys objects) - (into [] xform)))) + (if (contains? (meta objects) ::index-frames) + (::index-frames (meta objects)) + (let [lookup (d/getf objects) + xform (comp (remove #(= uuid/zero %)) + (keep lookup) + (filter frame-shape?))] + (->> (keys objects) + (into [] xform))))) + +(defn get-frames-ids + "Retrieves all frame ids as vector" + [objects] + (->> (get-frames objects) + (mapv :id))) (defn get-nested-frames [objects frame-id] @@ -197,25 +190,19 @@ (conj (:id shape))))] (reduce-objects objects (complement frame-shape?) add-frame []))) -(defn get-root-shapes-ids +(defn get-root-shapes [objects] (let [add-shape (fn [result shape] (cond-> result (not (frame-shape? shape)) - (conj (:id shape))))] + (conj shape)))] (reduce-objects objects (complement frame-shape?) add-shape []))) -(defn get-root-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." +(defn get-root-shapes-ids [objects] - (let [lookup (d/getf objects) - xform (comp (keep lookup) - (filter frame-shape?))] - (->> (:shapes (lookup uuid/zero)) - (into [] xform)))) + (->> (get-root-shapes objects) + (mapv :id))) (defn- get-base [objects id-a id-b] @@ -697,3 +684,22 @@ identity (remove :hide-in-viewer))) (sort-z-index objects (get-frames-ids objects) {:top-frames? true})))) + + +(defn start-page-index + [objects] + (with-meta objects {::index-frames (get-frames objects)})) + +(defn update-page-index + [objects] + (with-meta objects {::index-frames (get-frames objects)})) + +(defn start-object-indices + [file] + (letfn [(process-index [page-index page-id] + (update-in page-index [page-id :objects] start-page-index))] + (update file :pages-index #(reduce process-index % (keys %))))) + +(defn update-object-indices + [file page-id] + (update-in file [:pages-index page-id :objects] update-page-index)) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 3e10ea51a..5bbd56046 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -32,7 +32,6 @@ [app.main.data.workspace.fix-bool-contents :as fbc] [app.main.data.workspace.groups :as dwg] [app.main.data.workspace.guides :as dwgu] - [app.main.data.workspace.indices :as dwidx] [app.main.data.workspace.interactions :as dwi] [app.main.data.workspace.layers :as dwly] [app.main.data.workspace.layout :as layout] @@ -128,9 +127,7 @@ team-id (dm/get-in bundle [:project :team-id])] (rx/merge (rx/of (dwn/initialize team-id file-id) - (dwp/initialize-file-persistence file-id) - (dwidx/start-indexing)) - + (dwp/initialize-file-persistence file-id)) (->> stream (rx/filter #(= ::dwc/index-initialized %)) (rx/take 1) @@ -153,6 +150,7 @@ :workspace-project project :workspace-file (assoc file :initialized true) :workspace-data (-> (:data file) + (cph/start-object-indices) ;; DEBUG: Uncomment this to try out migrations in local without changing ;; the version number #_(assoc :version 17) @@ -196,7 +194,6 @@ (watch [_ _ _] (rx/merge (rx/of (dwn/finalize file-id)) - (rx/of (dwidx/stop-indexing)) (->> (rx/of ::dwp/finalize) (rx/observe-on :async)))))) diff --git a/frontend/src/app/main/data/workspace/changes.cljs b/frontend/src/app/main/data/workspace/changes.cljs index 9c43d99de..decc1b5f5 100644 --- a/frontend/src/app/main/data/workspace/changes.cljs +++ b/frontend/src/app/main/data/workspace/changes.cljs @@ -162,7 +162,10 @@ (us/assert ::spec.change/changes redo-changes) (us/assert ::spec.change/changes undo-changes) - (update-in state path cp/process-changes redo-changes false) + (update-in state path (fn [file] + (-> file + (cp/process-changes redo-changes false) + (cph/update-object-indices page-id)))) (catch :default err (log/error :js/error err) diff --git a/frontend/src/app/main/data/workspace/indices.cljs b/frontend/src/app/main/data/workspace/indices.cljs deleted file mode 100644 index 739a3f9e8..000000000 --- a/frontend/src/app/main/data/workspace/indices.cljs +++ /dev/null @@ -1,75 +0,0 @@ -;; This Source Code Form is subject to the terms of the Mozilla Public -;; License, v. 2.0. If a copy of the MPL was not distributed with this -;; file, You can obtain one at http://mozilla.org/MPL/2.0/. -;; -;; Copyright (c) UXBOX Labs SL - -(ns app.main.data.workspace.indices - (:require - [app.main.data.workspace.changes :as dwc] - [app.main.data.workspace.indices.object-tree :as dwi-object-tree] - [app.main.data.workspace.state-helpers :as wsh] - [app.main.refs :as refs] - [beicon.core :as rx] - [potok.core :as ptk])) - -(def stop-indexing? (ptk/type? ::stop-indexing)) - -(def objects-changes #{:add-obj :mod-obj :del-obj :mov-objects}) - -(defn stop-indexing - [] - (ptk/reify ::stop-indexing - ptk/UpdateEvent - (update [_ state] - (-> state - (dissoc :index-object-tree))))) - -(defn process-changes - "Simplify changes so we have only the type of operation and the ids" - [changes] - (->> changes - (filter #(contains? objects-changes (:type %))) - (mapcat (fn [{:keys [type id shapes]}] - (if (some? shapes) - (->> shapes (map #(vector type %))) - [[type id]]))))) - -(defn update-indexing - [change-type shape-id old-objects new-objects] - (ptk/reify ::update-indexing - ptk/UpdateEvent - (update [_ state] - (-> state - (update :index-object-tree dwi-object-tree/update-index shape-id change-type old-objects new-objects))))) - -(defn start-indexing - [] - (ptk/reify ::start-indexing - ptk/UpdateEvent - (update [_ state] - (let [objects (wsh/lookup-page-objects state)] - (-> state - (assoc :index-object-tree (dwi-object-tree/init-index objects))))) - - ptk/WatchEvent - (watch [_ _ stream] - (let [stopper (->> stream (rx/filter stop-indexing?) (rx/take 1)) - objects-delta (->> (rx/from-atom refs/workspace-page-objects {:emit-current-value? true}) (rx/buffer 2 1))] - (->> stream - (rx/filter dwc/commit-changes?) - (rx/flat-map #(->> % deref :changes process-changes)) - (rx/with-latest-from objects-delta) - (rx/map (fn [[[type id] [objects-old objects-new]]] - (update-indexing type id objects-old objects-new))) - #_(rx/tap (fn [[[type id] [objects-old objects-new]]] - (let [obj-old (get objects-old id) - obj-new (get objects-new id)] - (prn ">change" (or (:name obj-old) (:name obj-new))) - (prn " > " type) - (.log js/console " >" (clj->js obj-old)) - (.log js/console " >" (clj->js obj-new)) - - ))) - (rx/take-until stopper) - (rx/ignore)))))) diff --git a/frontend/src/app/main/data/workspace/indices/object_tree.cljs b/frontend/src/app/main/data/workspace/indices/object_tree.cljs deleted file mode 100644 index b7aaad28d..000000000 --- a/frontend/src/app/main/data/workspace/indices/object_tree.cljs +++ /dev/null @@ -1,16 +0,0 @@ -;; This Source Code Form is subject to the terms of the Mozilla Public -;; License, v. 2.0. If a copy of the MPL was not distributed with this -;; file, You can obtain one at http://mozilla.org/MPL/2.0/. -;; -;; Copyright (c) UXBOX Labs SL - -(ns app.main.data.workspace.indices.object-tree) - -(defn objects-tree - [_objects]) - -(defn init-index - [_objects]) - -(defn update-index - [_index _shape-id _change-type _old-objects _new-objects]) diff --git a/frontend/src/app/main/data/workspace/thumbnails.cljs b/frontend/src/app/main/data/workspace/thumbnails.cljs index 25791cd72..1a97606df 100644 --- a/frontend/src/app/main/data/workspace/thumbnails.cljs +++ b/frontend/src/app/main/data/workspace/thumbnails.cljs @@ -73,12 +73,13 @@ (rx/merge-map (fn [data] - (let [params {:file-id file-id :object-id object-id :data data}] - (rx/merge - ;; Update the local copy of the thumbnails so we don't need to request it again - (rx/of #(assoc-in % [:workspace-file :thumbnails object-id] data)) - (->> (rp/mutation! :upsert-file-object-thumbnail params) - (rx/ignore))))))))))) + (when (some? file-id) + (let [params {:file-id file-id :object-id object-id :data data}] + (rx/merge + ;; Update the local copy of the thumbnails so we don't need to request it again + (rx/of #(assoc-in % [:workspace-file :thumbnails object-id] data)) + (->> (rp/mutation! :upsert-file-object-thumbnail params) + (rx/ignore)))))))))))) (defn- extract-frame-changes "Process a changes set in a commit to extract the frames that are changing" diff --git a/frontend/src/app/main/ui/workspace/shapes/path.cljs b/frontend/src/app/main/ui/workspace/shapes/path.cljs index dee228b39..0dd893faf 100644 --- a/frontend/src/app/main/ui/workspace/shapes/path.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/path.cljs @@ -14,6 +14,12 @@ [app.main.ui.workspace.shapes.path.common :as pc] [rumext.alpha :as mf])) +(defn apply-content-modifiers + [shape content-modifiers] + (let [shape (update shape :content upc/apply-content-modifiers content-modifiers) + [_ new-selrect] (helpers/content->points+selrect shape (:content shape))] + (assoc shape :selrect new-selrect))) + (mf/defc path-wrapper {::mf/wrap-props false} [props] @@ -22,11 +28,7 @@ content-modifiers (mf/deref content-modifiers-ref) editing-id (mf/deref refs/selected-edition) editing? (= editing-id (:id shape)) - shape (update shape :content upc/apply-content-modifiers content-modifiers) - - [_ new-selrect] - (helpers/content->points+selrect shape (:content shape)) - shape (assoc shape :selrect new-selrect)] + shape (mf/use-memo (mf/deps shape content-modifiers) #(apply-content-modifiers shape content-modifiers))] [:> shape-container {:shape shape :pointer-events (when editing? "none")} diff --git a/frontend/src/app/main/ui/workspace/shapes/text/viewport_texts.cljs b/frontend/src/app/main/ui/workspace/shapes/text/viewport_texts.cljs index 3aca3072c..5c69a3c48 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/viewport_texts.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/viewport_texts.cljs @@ -32,8 +32,8 @@ (defn strip-modifier [modifier] - (if (or (some? (get-in modifier [:modifiers :resize-vector])) - (some? (get-in modifier [:modifiers :resize-vector-2]))) + (if (or (some? (dm/get-in modifier [:modifiers :resize-vector])) + (some? (dm/get-in modifier [:modifiers :resize-vector-2]))) modifier (d/update-when modifier :modifiers dissoc :displacement :rotation)))