From 1ef37281e6d5a1b36252a370652e92d6af23e3e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Fri, 8 Jul 2022 16:43:37 +0200 Subject: [PATCH] :tada: Auto sync when changing main instance --- common/src/app/common/pages/changes.cljc | 33 +++++++++++++- frontend/src/app/main/data/workspace.cljs | 3 +- .../app/main/data/workspace/libraries.cljs | 45 ++++++++++++++++++- .../data/workspace/libraries_helpers.cljs | 1 + .../app/main/ui/workspace/sidebar/assets.cljs | 1 - 5 files changed, 78 insertions(+), 5 deletions(-) diff --git a/common/src/app/common/pages/changes.cljc b/common/src/app/common/pages/changes.cljc index 200405061..f47ed59a2 100644 --- a/common/src/app/common/pages/changes.cljc +++ b/common/src/app/common/pages/changes.cljc @@ -17,6 +17,7 @@ [app.common.spec :as us] [app.common.pages.changes-spec :as pcs] [app.common.types.components-list :as ctkl] + [app.common.types.container :as ctn] [app.common.types.colors-list :as ctcl] [app.common.types.page :as ctp] [app.common.types.pages-list :as ctpl] @@ -37,7 +38,7 @@ ;; Page Transformation Changes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; --- Changes Processing Impl +;; === Changes Processing Impl (defmulti process-change (fn [_ change] (:type change))) (defmulti process-operation (fn [_ op] (:type op))) @@ -387,7 +388,7 @@ [data {:keys [id]}] (update data :typographies dissoc id)) -;; -- Operations +;; === Operations (defmethod process-operation :set [shape op] @@ -451,3 +452,31 @@ (ex/raise :type :not-implemented :code :operation-not-implemented :context {:type (:type op)})) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Component changes detection +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Analyze one change and checks if if modifies the main instance of +;; any component, so that it needs to be synced immediately to the +;; main component. Return the ids of the components that need sync. + +(defmulti components-changed (fn [_ change] (:type change))) + +(defmethod components-changed :mod-obj + [file-data {:keys [id page-id component-id operations]}] + (when page-id + (let [page (ctpl/get-page file-data page-id) + shape-and-parents (map #(ctn/get-shape page %) + (into [id] (cph/get-parent-ids (:objects page) id))) + any-set? (some #(= (:type %) :set) operations)] + (when any-set? + (into #{} (->> shape-and-parents + (filter #(:main-instance? %)) + (map :id))))))) + +(defmethod components-changed :default + [_ _] + nil) + diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 8407df47f..0b6db38e1 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -214,7 +214,8 @@ (watch [_ state _] (if (contains? (get-in state [:workspace-data :pages-index]) page-id) (rx/of (dwp/preload-data-uris) - (dwth/watch-state-changes)) + (dwth/watch-state-changes) + (dwl/watch-component-changes)) (let [default-page-id (get-in state [:workspace-data :pages 0])] (rx/of (go-to-page default-page-id))))) diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index 6be291020..8694a905d 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -10,6 +10,7 @@ [app.common.geom.point :as gpt] [app.common.logging :as log] [app.common.pages :as cp] + [app.common.pages.changes :as ch] [app.common.pages.changes-builder :as pcb] [app.common.pages.changes-spec :as pcs] [app.common.pages.helpers :as cph] @@ -29,6 +30,7 @@ [app.main.data.workspace.selection :as dws] [app.main.data.workspace.state-helpers :as wsh] [app.main.data.workspace.undo :as dwu] + [app.main.refs :as refs] [app.main.repo :as rp] [app.main.store :as st] [app.util.i18n :refer [tr]] @@ -615,7 +617,8 @@ (ptk/reify ::sync-file ptk/UpdateEvent (update [_ state] - (if (not= library-id (:current-file-id state)) + (if (and (not= library-id (:current-file-id state)) + (nil? asset-id)) (d/assoc-in-when state [:workspace-libraries library-id :synced-at] (dt/now)) state)) @@ -743,6 +746,46 @@ :callback do-dismiss}] :sync-dialog)))))) +(defn watch-component-changes + "Watch the state for changes that affect to any main instance. If a change is detected will throw + an update-component-sync, so changes are immediately propagated to the component and copies." + [] + (ptk/reify ::watch-component-changes + ptk/WatchEvent + (watch [_ _ stream] + (let [stopper + (->> stream + (rx/filter #(or (= :app.main.data.workspace/finalize-page (ptk/type %)) + (= ::watch-component-changes (ptk/type %))))) + + workspace-data-str + (->> (rx/concat + (rx/of nil) + (rx/from-atom refs/workspace-data {:emit-current-value? true}))) + + change-str + (->> stream + (rx/filter #(or (dch/commit-changes? %) + (= (ptk/type %) :app.main.data.workspace.notifications/handle-file-change))) + (rx/observe-on :async)) + + check-changes + (fn [[event data]] + (let [changes (-> event deref :changes) + components-changed (reduce #(into %1 (ch/components-changed data %2)) + #{} + changes)] + (js/console.log "components-changed" (clj->js components-changed)) + (when (d/not-empty? components-changed) + (apply st/emit! + (map #(update-component-sync % (:id data)) + components-changed)))))] + + (->> change-str + (rx/with-latest-from workspace-data-str) + (rx/map check-changes) + (rx/take-until stopper)))))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Backend interactions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index 41a29f64e..14a57309f 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -254,6 +254,7 @@ (and (if (nil? component-id) (ctk/uses-library-components? shape library-id) (ctk/instance-of? shape library-id component-id)) + (not (:main-instance? shape)) ; not need to sync the main instance (avoid infinite loop) (or (:component-root? shape) (not page?)))) ; avoid nested components inside pages (defmethod uses-assets? :colors diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs index fc84f8950..e80065095 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs @@ -188,7 +188,6 @@ (add-group % group-name))))) (st/emit! (dwu/commit-undo-transaction))) - (defn- on-drop-asset [event asset dragging? selected-assets selected-assets-full selected-assets-paths rename] (let [create-typed-assets-group (partial create-assets-group rename)]