From 0f8e2a9b1be0e3c36cc4b1b2bb56b0cd299b7711 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Sat, 8 May 2021 14:59:58 +0200 Subject: [PATCH] :tada: Add experimental trazability to update-file. --- backend/src/app/rpc/mutations/files.clj | 59 +++++--- frontend/src/app/main/data/workspace.cljs | 141 ++++++++++-------- .../src/app/main/data/workspace/changes.cljs | 115 +++++++------- .../src/app/main/data/workspace/common.cljs | 43 ++++-- .../src/app/main/data/workspace/grid.cljs | 27 ++-- .../src/app/main/data/workspace/groups.cljs | 24 ++- .../app/main/data/workspace/libraries.cljs | 137 +++++++++++------ .../app/main/data/workspace/path/changes.cljs | 6 +- .../app/main/data/workspace/path/edition.cljs | 22 +-- .../app/main/data/workspace/path/tools.cljs | 6 +- .../app/main/data/workspace/persistence.cljs | 38 ++--- .../app/main/data/workspace/selection.cljs | 7 +- .../app/main/data/workspace/svg_upload.cljs | 8 +- .../app/main/data/workspace/transforms.cljs | 28 ++-- frontend/src/app/main/store.cljs | 18 +++ 15 files changed, 407 insertions(+), 272 deletions(-) diff --git a/backend/src/app/rpc/mutations/files.clj b/backend/src/app/rpc/mutations/files.clj index 493be817b..7ce732eca 100644 --- a/backend/src/app/rpc/mutations/files.clj +++ b/backend/src/app/rpc/mutations/files.clj @@ -228,16 +228,10 @@ {:id file-id})) +;; --- MUTATION: update-file + ;; A generic, Changes based (granular) file update method. -(s/def ::changes - (s/coll-of map? :kind vector?)) - -(s/def ::session-id ::us/uuid) -(s/def ::revn ::us/integer) -(s/def ::update-file - (s/keys :req-un [::id ::session-id ::profile-id ::revn ::changes])) - ;; File changes that affect to the library, and must be notified ;; to all clients using it. (defn library-change? @@ -256,6 +250,31 @@ (declare send-notifications) (declare update-file) +(s/def ::changes + (s/coll-of map? :kind vector?)) + +(s/def ::hint-origin ::us/keyword) +(s/def ::hint-events + (s/every ::us/keyword :kind vector?)) + +(s/def ::change-with-metadata + (s/keys :req-un [::changes] + :opt-un [::hint-origin + ::hint-events])) + +(s/def ::changes-with-metadata + (s/every ::change-with-metadata :kind vector?)) + +(s/def ::session-id ::us/uuid) +(s/def ::revn ::us/integer) +(s/def ::update-file + (s/and + (s/keys :req-un [::id ::session-id ::profile-id ::revn] + :opt-un [::changes ::changes-with-metadata]) + (fn [o] + (or (contains? o :changes) + (contains? o :changes-with-metadata))))) + (sv/defmethod ::update-file [{:keys [pool] :as cfg} {:keys [id profile-id] :as params}] (db/with-atomic [conn pool] @@ -265,7 +284,7 @@ (assoc params :file file))))) (defn- update-file - [{:keys [conn] :as cfg} {:keys [file changes session-id profile-id] :as params}] + [{:keys [conn] :as cfg} {:keys [file changes changes-with-metadata session-id profile-id] :as params}] (when (> (:revn params) (:revn file)) (ex/raise :type :validation @@ -274,15 +293,19 @@ :context {:incoming-revn (:revn params) :stored-revn (:revn file)})) - (let [file (-> file - (update :revn inc) - (update :data (fn [data] - (-> data - (blob/decode) - (assoc :id (:id file)) - (pmg/migrate-data) - (cp/process-changes changes) - (blob/encode)))))] + (let [changes (if changes-with-metadata + (mapcat :changes changes-with-metadata) + changes) + + file (-> file + (update :revn inc) + (update :data (fn [data] + (-> data + (blob/decode) + (assoc :id (:id file)) + (pmg/migrate-data) + (cp/process-changes changes) + (blob/encode)))))] ;; Insert change to the xlog (db/insert! conn :file-change {:id (uuid/next) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 69e19f32b..18ad355a9 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -134,7 +134,7 @@ (or layout default-layout)))) ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (if (and layout-name (contains? layout-names layout-name)) (rx/of (ensure-layout layout-name)) (rx/of (ensure-layout :layers)))))) @@ -153,7 +153,7 @@ :workspace-presence {})) ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (rx/merge (rx/of (dwp/fetch-bundle project-id file-id)) @@ -188,7 +188,7 @@ file)))) ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [ignore-until (get-in state [:workspace-file :ignore-sync-until]) needs-update? (some #(and (> (:modified-at %) (:synced-at %)) (or (not ignore-until) @@ -209,7 +209,7 @@ :workspace-persistence)) ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (rx/of (dwn/finalize file-id) ::dwp/finalize)))) @@ -263,7 +263,7 @@ {:id id :file-id file-id}) ptk/WatchEvent - (watch [this state stream] + (watch [it state stream] (let [pages (get-in state [:workspace-data :pages-index]) unames (dwc/retrieve-used-names pages) name (dwc/generate-unique-name unames "Page") @@ -273,9 +273,12 @@ :name name} uchange {:type :del-page :id id}] - (rx/of (dch/commit-changes [rchange] [uchange] {:commit-local? true}))))))) + (rx/of (dch/commit-changes {:redo-changes [rchange] + :undo-changes [uchange] + :origin it}))))))) -(defn duplicate-page [page-id] +(defn duplicate-page + [page-id] (ptk/reify ::duplicate-page ptk/WatchEvent (watch [this state stream] @@ -291,7 +294,9 @@ :page page} uchange {:type :del-page :id id}] - (rx/of (dch/commit-changes [rchange] [uchange] {:commit-local? true})))))) + (rx/of (dch/commit-changes {:redo-changes [rchange] + :undo-changes [uchange] + :origin this})))))) (s/def ::rename-page (s/keys :req-un [::id ::name])) @@ -302,7 +307,7 @@ (us/verify string? name) (ptk/reify ::rename-page ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page (get-in state [:workspace-data :pages-index id]) rchg {:type :mod-page :id id @@ -310,7 +315,9 @@ uchg {:type :mod-page :id id :name (:name page)}] - (rx/of (dch/commit-changes [rchg] [uchg] {:commit-local? true})))))) + (rx/of (dch/commit-changes {:redo-changes [rchg] + :undo-changes [uchg] + :origin it})))))) (declare purge-page) (declare go-to-file) @@ -321,13 +328,15 @@ [id] (ptk/reify ::delete-page ptk/WatchEvent - (watch [_ state s] + (watch [it state stream] (let [page (get-in state [:workspace-data :pages-index id]) rchg {:type :del-page :id id} uchg {:type :add-page :page page}] - (rx/of (dch/commit-changes [rchg] [uchg] {:commit-local? true}) + (rx/of (dch/commit-changes {:redo-changes [rchg] + :undo-changes [uchg] + :origin it}) (when (= id (:current-page-id state)) go-to-file)))))) @@ -345,7 +354,7 @@ (assoc-in state [:workspace-file :name] name)) ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [params {:id id :name name}] (->> (rp/mutation :rename-file params) (rx/ignore)))))) @@ -444,7 +453,7 @@ (defn start-panning [] (ptk/reify ::start-panning ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [stopper (->> stream (rx/filter (ptk/type? ::finish-panning))) zoom (-> (get-in state [:workspace-local :zoom]) gpt/point)] (when-not (get-in state [:workspace-local :panning]) @@ -607,7 +616,7 @@ (us/verify ::shape-attrs attrs) (ptk/reify ::update-shape ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (rx/of (dch/update-shapes [id] #(merge % attrs)))))) (defn start-rename-shape @@ -632,7 +641,7 @@ (us/verify ::shape-attrs attrs) (ptk/reify ::update-selected-shapes ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [selected (wsh/lookup-selected state)] (rx/from (map #(update-shape % attrs) selected)))))) @@ -670,7 +679,7 @@ "Deselect all and remove all selected shapes." (ptk/reify ::delete-selected ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [selected (wsh/lookup-selected state)] (rx/of (dwc/delete-shapes selected) (dws/deselect-all)))))) @@ -682,9 +691,9 @@ (defn vertical-order-selected [loc] (us/verify ::loc loc) - (ptk/reify ::vertical-order-selected-shpes + (ptk/reify ::vertical-order-selected ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) selected (wsh/lookup-selected state) @@ -716,7 +725,9 @@ :index (cp/position-on-parent id objects)})) selected)] ;; TODO: maybe missing the :reg-objects event? - (rx/of (dch/commit-changes rchanges uchanges {:commit-local? true})))))) + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it})))))) ;; --- Change Shape Order (D&D Ordering) @@ -891,7 +902,7 @@ (ptk/reify ::relocate-shapes ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) @@ -990,14 +1001,16 @@ shapes-to-detach shapes-to-reroot shapes-to-deroot)] - (rx/of (dch/commit-changes rchanges uchanges {:commit-local? true}) + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-chanes uchanges + :origin it}) (dwc/expand-collapse parent-id)))))) (defn relocate-selected-shapes [parent-id to-index] (ptk/reify ::relocate-selected-shapes ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [selected (wsh/lookup-selected state)] (rx/of (relocate-shapes selected parent-id to-index)))))) @@ -1006,7 +1019,7 @@ [] (ptk/reify ::start-editing-selected ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [selected (wsh/lookup-selected state)] (if-not (= 1 (count selected)) (rx/empty) @@ -1034,7 +1047,7 @@ [id index] (ptk/reify ::relocate-pages ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [cidx (-> (get-in state [:workspace-data :pages]) (d/index-of id)) rchg {:type :mov-page @@ -1043,7 +1056,9 @@ uchg {:type :mov-page :id id :index cidx}] - (rx/of (dch/commit-changes [rchg] [uchg])))))) + (rx/of (dch/commit-changes {:redo-changes [rchg] + :undo-chanes [uchg] + :origin it})))))) ;; --- Shape / Selection Alignment and Distribution @@ -1055,7 +1070,7 @@ (us/verify ::gal/align-axis axis) (ptk/reify :align-objects ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) selected (wsh/lookup-selected state) @@ -1086,7 +1101,7 @@ (us/verify ::gal/dist-axis axis) (ptk/reify :align-objects ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) selected (wsh/lookup-selected state) @@ -1104,7 +1119,7 @@ [id lock] (ptk/reify ::set-shape-proportion-lock ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (letfn [(assign-proportions [shape] (if-not lock (assoc shape :proportion-lock false) @@ -1125,7 +1140,7 @@ (us/verify ::position position) (ptk/reify ::update-position ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) shape (get objects id) @@ -1147,7 +1162,7 @@ (s/assert ::shape-attrs flags) (ptk/reify ::update-shape-flags ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (letfn [(update-fn [obj] (cond-> obj (boolean? blocked) (assoc :blocked blocked) @@ -1163,7 +1178,7 @@ [project-id] (ptk/reify ::navigate-to-project ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page-ids (get-in state [:projects project-id :pages]) params {:project project-id :page (first page-ids)}] (rx/of (rt/nav :workspace/page params)))))) @@ -1172,7 +1187,7 @@ ([] (ptk/reify ::go-to-page ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [project-id (:current-project-id state) file-id (:current-file-id state) page-id (get-in state [:workspace-data :pages 0]) @@ -1184,7 +1199,7 @@ (us/verify ::us/uuid page-id) (ptk/reify ::go-to-page ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [project-id (:current-project-id state) file-id (:current-file-id state) pparams {:file-id file-id :project-id project-id} @@ -1196,7 +1211,7 @@ (us/verify ::layout-flag layout) (ptk/reify ::go-to-layout ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [project-id (get-in state [:workspace-project :id]) file-id (get-in state [:workspace-file :id]) page-id (get-in state [:current-page-id]) @@ -1207,7 +1222,7 @@ (def go-to-file (ptk/reify ::go-to-file ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [{:keys [id project-id data] :as file} (:workspace-file state) page-id (get-in data [:pages 0]) pparams {:project-id project-id :file-id id} @@ -1220,7 +1235,7 @@ ([{:keys [file-id page-id]}] (ptk/reify ::go-to-viewer ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [{:keys [current-file-id current-page-id]} state params {:file-id (or file-id current-file-id) :page-id (or page-id current-page-id)}] @@ -1232,7 +1247,7 @@ ([{:keys [team-id]}] (ptk/reify ::go-to-dashboard ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [team-id (or team-id (get-in state [:workspace-project :team-id]))] (rx/of ::dwp/force-persist (rt/nav :dashboard-projects {:team-id team-id}))))))) @@ -1262,7 +1277,7 @@ (us/verify ::cp/minimal-shape shape) (ptk/reify ::show-shape-context-menu ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [selected (wsh/lookup-selected state)] (rx/concat (when-not (selected (:id shape)) @@ -1354,7 +1369,7 @@ (ptk/reify ::copy-selected ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [objects (wsh/lookup-page-objects state) selected (->> (wsh/lookup-selected state) (cp/clean-loops objects)) @@ -1381,7 +1396,7 @@ (def paste (ptk/reify ::paste ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (try (let [clipboard-str (wapi/read-from-clipboard) @@ -1420,7 +1435,7 @@ [event in-viewport?] (ptk/reify ::paste-from-event ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (try (let [objects (wsh/lookup-page-objects state) paste-data (wapi/read-from-paste-event event) @@ -1538,7 +1553,7 @@ change))) ;; Procceed with the standard shape paste procediment. - (do-paste [state mouse-pos media] + (do-paste [it state mouse-pos media] (let [media-idx (d/index-by :prev-id media) page-id (:current-page-id state) @@ -1584,19 +1599,21 @@ (map #(get-in % [:obj :id])) (into (d/ordered-set)))] - (rx/of (dch/commit-changes rchanges uchanges {:commit-local? true}) + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it}) (dwc/select-shapes selected))))] (ptk/reify ::paste-shape ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [file-id (:current-file-id state) mouse-pos (deref ms/mouse-position)] (if (= file-id (:file-id data)) - (do-paste state mouse-pos []) + (do-paste it state mouse-pos []) (->> (rx/from images) (rx/merge-map (partial upload-media file-id)) (rx/reduce conj []) - (rx/mapcat (partial do-paste state mouse-pos))))))))) + (rx/mapcat (partial do-paste it state mouse-pos))))))))) (defn as-content [text] @@ -1612,7 +1629,7 @@ (s/assert string? text) (ptk/reify ::paste-text ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [id (uuid/next) {:keys [x y]} @ms/mouse-position width (max 8 (min (* 7 (count text)) 700)) @@ -1641,7 +1658,7 @@ (s/assert string? text) (ptk/reify ::paste-svg ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [position (deref ms/mouse-position) file-id (:current-file-id state)] (->> (dwp/parse-svg ["svg" text]) @@ -1651,7 +1668,7 @@ [image] (ptk/reify ::paste-bin-impl ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [file-id (get-in state [:workspace-file :id]) params {:file-id file-id :blobs [image] @@ -1676,7 +1693,7 @@ [] (ptk/reify ::start-create-interaction ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [initial-pos @ms/mouse-position selected (wsh/lookup-selected state) stopper (rx/filter ms/mouse-up? stream)] @@ -1713,7 +1730,7 @@ (assoc-in [:workspace-local :draw-interaction-to-frame] nil))) ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [position @ms/mouse-position page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) @@ -1741,20 +1758,20 @@ [color] (ptk/reify ::change-canvas-color ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page-id (get state :current-page-id) options (wsh/lookup-page-options state page-id) previus-color (:background options)] (rx/of (dch/commit-changes - [{:type :set-option - :page-id page-id - :option :background - :value (:color color)}] - [{:type :set-option - :page-id page-id - :option :background - :value previus-color}] - {:commit-local? true})))))) + {:redo-changes [{:type :set-option + :page-id page-id + :option :background + :value (:color color)}] + :undo-changes [{:type :set-option + :page-id page-id + :option :background + :value previus-color}] + :origin it})))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/frontend/src/app/main/data/workspace/changes.cljs b/frontend/src/app/main/data/workspace/changes.cljs index b3a437835..53f5cd421 100644 --- a/frontend/src/app/main/data/workspace/changes.cljs +++ b/frontend/src/app/main/data/workspace/changes.cljs @@ -12,6 +12,7 @@ [app.common.spec :as us] [app.main.data.workspace.undo :as dwu] [app.main.worker :as uw] + [app.main.store :as st] [app.util.logging :as log] [beicon.core :as rx] [cljs.spec.alpha :as s] @@ -66,7 +67,7 @@ (us/assert fn? f) (ptk/reify ::update-shapes ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page-id (:current-page-id state) objects (get-in state [:workspace-data :pages-index page-id :objects]) reg-objects {:type :reg-objects :page-id page-id :shapes (vec ids)}] @@ -79,7 +80,9 @@ rch (cond-> rch (and has-rch? reg-objects?) (conj reg-objects)) uch (cond-> uch (and has-rch? reg-objects?) (conj reg-objects))] (when (and has-rch? has-uch?) - (commit-changes rch uch {:commit-local? true})))) + (commit-changes {:redo-changes rch + :undo-changes uch + :origin it})))) (let [id (first ids) obj1 (get objects id) @@ -140,11 +143,13 @@ (conj uchanges uchg))))))] (ptk/reify ::update-shapes-recursive ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page-id (:current-page-id state) objects (get-in state [:workspace-data :pages-index page-id :objects]) [rchanges uchanges] (impl-gen-changes objects page-id (seq ids))] - (rx/of (commit-changes rchanges uchanges {:commit-local? true}))))))) + (rx/of (commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it}))))))) (defn update-indices [page-id changes] @@ -156,62 +161,60 @@ :changes changes})))) (defn commit-changes - ([changes undo-changes] - (commit-changes changes undo-changes {})) - ([changes undo-changes {:keys [save-undo? - file-id] - :or {save-undo? true} - :as opts}] + [{:keys [redo-changes undo-changes origin save-undo? file-id] + :or {save-undo? true}}] - (log/debug :msg "commit-changes" - :js/changes changes - :js/undo-changes undo-changes) + (log/debug :msg "commit-changes" + :js/redo-changes redo-changes + :js/undo-changes undo-changes) - (let [error (volatile! nil)] - (ptk/reify ::commit-changes - cljs.core/IDeref - (-deref [_] - {:file-id file-id - :changes changes}) + (let [error (volatile! nil)] + (ptk/reify ::commit-changes + cljs.core/IDeref + (-deref [_] + {:file-id file-id + :hint-events @st/last-events + :hint-origin (ptk/type origin) + :changes redo-changes}) - ptk/UpdateEvent - (update [_ state] - (let [current-file-id (get state :current-file-id) - file-id (or file-id current-file-id) - path (if (= file-id current-file-id) - [:workspace-data] - [:workspace-libraries file-id :data])] - (try - (us/assert ::spec/changes changes) - (us/assert ::spec/changes undo-changes) - (update-in state path cp/process-changes changes false) - (catch :default e - (vreset! error e) - state)))) + ptk/UpdateEvent + (update [_ state] + (let [current-file-id (get state :current-file-id) + file-id (or file-id current-file-id) + path (if (= file-id current-file-id) + [:workspace-data] + [:workspace-libraries file-id :data])] + (try + (us/assert ::spec/changes redo-changes) + (us/assert ::spec/changes undo-changes) + (update-in state path cp/process-changes redo-changes false) + (catch :default e + (vreset! error e) + state)))) - ptk/WatchEvent - (watch [_ state stream] - (when-not @error - (let [;; adds page-id to page changes (that have the `id` field instead) - add-page-id - (fn [{:keys [id type page] :as change}] - (cond-> change - (page-change? type) - (assoc :page-id (or id (:id page))))) + ptk/WatchEvent + (watch [it state stream] + (when-not @error + (let [;; adds page-id to page changes (that have the `id` field instead) + add-page-id + (fn [{:keys [id type page] :as change}] + (cond-> change + (page-change? type) + (assoc :page-id (or id (:id page))))) - changes-by-pages - (->> changes - (map add-page-id) - (remove #(nil? (:page-id %))) - (group-by :page-id)) + changes-by-pages + (->> redo-changes + (map add-page-id) + (remove #(nil? (:page-id %))) + (group-by :page-id)) - process-page-changes - (fn [[page-id changes]] - (update-indices page-id changes))] - (rx/concat - (rx/from (map process-page-changes changes-by-pages)) + process-page-changes + (fn [[page-id changes]] + (update-indices page-id redo-changes))] + (rx/concat + (rx/from (map process-page-changes changes-by-pages)) - (when (and save-undo? (seq undo-changes)) - (let [entry {:undo-changes undo-changes - :redo-changes changes}] - (rx/of (dwu/append-undo entry)))))))))))) + (when (and save-undo? (seq undo-changes)) + (let [entry {:undo-changes undo-changes + :redo-changes redo-changes}] + (rx/of (dwu/append-undo entry))))))))))) diff --git a/frontend/src/app/main/data/workspace/common.cljs b/frontend/src/app/main/data/workspace/common.cljs index d43229cdd..3bffa6bdb 100644 --- a/frontend/src/app/main/data/workspace/common.cljs +++ b/frontend/src/app/main/data/workspace/common.cljs @@ -40,7 +40,7 @@ [{:keys [file] :as bundle}] (ptk/reify ::setup-selection-index ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [msg {:cmd :initialize-indices :file-id (:id file) :data (:data file)}] @@ -112,7 +112,7 @@ (def undo (ptk/reify ::undo ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [edition (get-in state [:workspace-local :edition]) drawing (get state :workspace-drawing)] ;; Editors handle their own undo's @@ -123,12 +123,15 @@ (when-not (or (empty? items) (= index -1)) (let [changes (get-in items [index :undo-changes])] (rx/of (dwu/materialize-undo changes (dec index)) - (dch/commit-changes changes [] {:save-undo? false})))))))))) + (dch/commit-changes {:redo-changes changes + :undo-changes [] + :save-undo? false + :origin it})))))))))) (def redo (ptk/reify ::redo ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [edition (get-in state [:workspace-local :edition]) drawing (get state :workspace-drawing)] (when-not (or (some? edition) (not-empty drawing)) @@ -138,7 +141,10 @@ (when-not (or (empty? items) (= index (dec (count items)))) (let [changes (get-in items [(inc index) :redo-changes])] (rx/of (dwu/materialize-undo changes (inc index)) - (dch/commit-changes changes [] {:save-undo? false})))))))))) + (dch/commit-changes {:redo-changes changes + :undo-changes [] + :origin it + :save-undo? false})))))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Shapes @@ -174,7 +180,7 @@ (assoc-in state [:workspace-local :selected] ids)) ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id)] (rx/of (expand-all-parents ids objects)))))) @@ -196,7 +202,7 @@ state))) ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [objects (wsh/lookup-page-objects state)] (->> stream (rx/filter interrupt?) @@ -276,7 +282,7 @@ (us/verify ::shape-attrs attrs) (ptk/reify ::add-shape ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) @@ -296,7 +302,9 @@ (assoc :name name)))] (rx/concat - (rx/of (dch/commit-changes rchanges uchanges {:commit-local? true}) + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it}) (select-shapes (d/ordered-set id))) (when (= :text (:type attrs)) (->> (rx/of (start-edition-mode id)) @@ -305,7 +313,7 @@ (defn move-shapes-into-frame [frame-id shapes] (ptk/reify ::move-shapes-into-frame ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (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}) @@ -329,14 +337,16 @@ :page-id page-id :index index :shapes [shape-id]})))] - (rx/of (dch/commit-changes rchanges uchanges {:commit-local? true})))))) + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it})))))) (defn delete-shapes [ids] (us/assert (s/coll-of ::us/uuid) ids) (ptk/reify ::delete-shapes ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) @@ -460,8 +470,9 @@ ;; (cljs.pprint/pprint rchanges) ;; (println "================ uchanges") ;; (cljs.pprint/pprint uchanges) - (rx/of (dch/commit-changes rchanges uchanges {:commit-local? true})))))) - + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it})))))) ;; --- Add shape to Workspace @@ -474,7 +485,7 @@ [type frame-x frame-y data] (ptk/reify ::create-and-add-shape ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [{:keys [width height]} data [vbc-x vbc-y] (viewport-center state) @@ -494,7 +505,7 @@ [image {:keys [x y]}] (ptk/reify ::image-uploaded ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [{:keys [name width height id mtype]} image shape {:name name :width width diff --git a/frontend/src/app/main/data/workspace/grid.cljs b/frontend/src/app/main/data/workspace/grid.cljs index 13a327103..e405c2364 100644 --- a/frontend/src/app/main/data/workspace/grid.cljs +++ b/frontend/src/app/main/data/workspace/grid.cljs @@ -40,7 +40,7 @@ (us/assert ::us/uuid frame-id) (ptk/reify ::add-frame-grid ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page-id (:current-page-id state) data (get-in state [:workspace-data :pages-index page-id]) params (or (get-in data [:options :saved-grids :square]) @@ -56,29 +56,30 @@ [frame-id index] (ptk/reify ::set-frame-grid ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (rx/of (dch/update-shapes [frame-id] (fn [o] (update o :grids (fnil #(d/remove-at-index % index) [])))))))) (defn set-frame-grid [frame-id index data] (ptk/reify ::set-frame-grid ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (rx/of (dch/update-shapes [frame-id] #(assoc-in % [:grids index] data)))))) (defn set-default-grid [type params] (ptk/reify ::set-default-grid ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [pid (:current-page-id state) prev-value (get-in state [:workspace-data :pages-index pid :options :saved-grids type])] - (rx/of (dch/commit-changes [{:type :set-option - :page-id pid - :option [:saved-grids type] - :value params}] - [{:type :set-option - :page-id pid - :option [:saved-grids type] - :value prev-value}] - {:commit-local? true})))))) + (rx/of (dch/commit-changes + {:redo-changes [{:type :set-option + :page-id pid + :option [:saved-grids type] + :value params}] + :undo-changes [{:type :set-option + :page-id pid + :option [:saved-grids type] + :value prev-value}] + :origin it})))))) diff --git a/frontend/src/app/main/data/workspace/groups.cljs b/frontend/src/app/main/data/workspace/groups.cljs index f34e1475c..356be5153 100644 --- a/frontend/src/app/main/data/workspace/groups.cljs +++ b/frontend/src/app/main/data/workspace/groups.cljs @@ -100,7 +100,7 @@ (def group-selected (ptk/reify ::group-selected ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) selected (wsh/lookup-selected state) @@ -108,13 +108,15 @@ shapes (shapes-for-grouping objects selected)] (when-not (empty? shapes) (let [[group rchanges uchanges] (prepare-create-group page-id shapes "Group-" false)] - (rx/of (dch/commit-changes rchanges uchanges {:commit-local? true}) + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it}) (dwc/select-shapes (d/ordered-set (:id group)))))))))) (def ungroup-selected (ptk/reify ::ungroup-selected ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) selected (wsh/lookup-selected state) @@ -124,12 +126,14 @@ (= (:type group) :group)) (let [[rchanges uchanges] (prepare-remove-group page-id group objects)] - (rx/of (dch/commit-changes rchanges uchanges {:commit-local? true})))))))) + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it})))))))) (def mask-group (ptk/reify ::mask-group ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) selected (wsh/lookup-selected state) @@ -178,13 +182,15 @@ :page-id page-id :shapes [(:id group)]})] - (rx/of (dch/commit-changes rchanges uchanges {:commit-local? true}) + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it}) (dwc/select-shapes (d/ordered-set (:id group)))))))))) (def unmask-group (ptk/reify ::unmask-group ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) selected (wsh/lookup-selected state)] @@ -211,7 +217,9 @@ :page-id page-id :shapes [(:id group)]}]] - (rx/of (dch/commit-changes rchanges uchanges {:commit-local? true}) + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it}) (dwc/select-shapes (d/ordered-set (:id group)))))))))) diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index c0370fdb6..67baf4330 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -86,23 +86,26 @@ (us/assert ::cp/color color) (ptk/reify ::add-color ptk/WatchEvent - (watch [_ state s] + (watch [it state s] (let [rchg {:type :add-color :color color} uchg {:type :del-color :id id}] (rx/of #(assoc-in % [:workspace-local :color-for-rename] id) - (dch/commit-changes [rchg] [uchg] {:commit-local? true}))))))) - + (dch/commit-changes {:redo-changes [rchg] + :undo-chages [uchg] + :origin it}))))))) (defn add-recent-color [color] (us/assert ::cp/recent-color color) (ptk/reify ::add-recent-color ptk/WatchEvent - (watch [_ state s] + (watch [it state s] (let [rchg {:type :add-recent-color :color color}] - (rx/of (dch/commit-changes [rchg] [] {:commit-local? true})))))) + (rx/of (dch/commit-changes {:redo-changes [rchg] + :undo-chages [] + :origin it})))))) (def clear-color-for-rename (ptk/reify ::clear-color-for-rename @@ -116,13 +119,15 @@ (us/assert ::us/uuid file-id) (ptk/reify ::update-color ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [prev (get-in state [:workspace-data :colors id]) rchg {:type :mod-color :color color} uchg {:type :mod-color :color prev}] - (rx/of (dch/commit-changes [rchg] [uchg] {:commit-local? true}) + (rx/of (dch/commit-changes {:redo-changes [rchg] + :undo-chages [uchg] + :origin it}) (sync-file (:current-file-id state) file-id)))))) (defn delete-color @@ -130,26 +135,30 @@ (us/assert ::us/uuid id) (ptk/reify ::delete-color ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [prev (get-in state [:workspace-data :colors id]) rchg {:type :del-color :id id} uchg {:type :add-color :color prev}] - (rx/of (dch/commit-changes [rchg] [uchg] {:commit-local? true})))))) + (rx/of (dch/commit-changes {:redo-changes [rchg] + :undo-chages [uchg] + :origin it})))))) (defn add-media [{:keys [id] :as media}] (us/assert ::cp/media-object media) (ptk/reify ::add-media ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [obj (select-keys media [:id :name :width :height :mtype]) rchg {:type :add-media :object obj} uchg {:type :del-media :id id}] - (rx/of (dch/commit-changes [rchg] [uchg] {:commit-local? true})))))) + (rx/of (dch/commit-changes {:redo-changes [rchg] + :undo-changes [uchg] + :origin it})))))) (defn rename-media [id new-name] @@ -157,7 +166,7 @@ (us/assert ::us/string new-name) (ptk/reify ::rename-media ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [object (get-in state [:workspace-data :media id]) [path name] (cp/parse-path-name new-name) @@ -171,20 +180,24 @@ :name (:name object) :path (:path object)}}]] - (rx/of (dch/commit-changes rchanges uchanges {:commit-local? true})))))) + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it})))))) (defn delete-media [{:keys [id] :as params}] (us/assert ::us/uuid id) (ptk/reify ::delete-media ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [prev (get-in state [:workspace-data :media id]) rchg {:type :del-media :id id} uchg {:type :add-media :object prev}] - (rx/of (dch/commit-changes [rchg] [uchg] {:commit-local? true})))))) + (rx/of (dch/commit-changes {:redo-changes [rchg] + :undo-changes [uchg] + :origin it})))))) (defn add-typography ([typography] (add-typography typography true)) @@ -193,12 +206,14 @@ (us/assert ::cp/typography typography) (ptk/reify ::add-typography ptk/WatchEvent - (watch [_ state s] + (watch [it state s] (let [rchg {:type :add-typography :typography typography} uchg {:type :del-typography :id (:id typography)}] - (rx/of (dch/commit-changes [rchg] [uchg] {:commit-local? true}) + (rx/of (dch/commit-changes {:redo-changes [rchg] + :undo-changes [uchg] + :origin it}) #(cond-> % edit? (assoc-in [:workspace-local :rename-typography] (:id typography)))))))))) @@ -209,13 +224,15 @@ (us/assert ::us/uuid file-id) (ptk/reify ::update-typography ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [prev (get-in state [:workspace-data :typographies (:id typography)]) rchg {:type :mod-typography :typography typography} uchg {:type :mod-typography :typography prev}] - (rx/of (dch/commit-changes [rchg] [uchg] {:commit-local? true}) + (rx/of (dch/commit-changes {:redo-changes [rchg] + :undo-changes [uchg] + :origin it}) (sync-file (:current-file-id state) file-id)))))) (defn delete-typography @@ -223,19 +240,21 @@ (us/assert ::us/uuid id) (ptk/reify ::delete-typography ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [prev (get-in state [:workspace-data :typographies id]) rchg {:type :del-typography :id id} uchg {:type :add-typography :typography prev}] - (rx/of (dch/commit-changes [rchg] [uchg] {:commit-local? true})))))) + (rx/of (dch/commit-changes {:redo-changes [rchg] + :undo-changes [uchg] + :origin it})))))) (def add-component "Add a new component to current file library, from the currently selected shapes." (ptk/reify ::add-component ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [file-id (:current-file-id state) page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) @@ -244,7 +263,9 @@ (let [[group rchanges uchanges] (dwlh/generate-add-component selected objects page-id file-id)] (when-not (empty? rchanges) - (rx/of (dch/commit-changes rchanges uchanges {:commit-local? true}) + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it}) (dwc/select-shapes (d/ordered-set (:id group)))))))))) (defn rename-component @@ -254,7 +275,7 @@ (us/assert ::us/string new-name) (ptk/reify ::rename-component ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [[path name] (cp/parse-path-name new-name) component (get-in state [:workspace-data :components id]) objects (get component :objects) @@ -275,14 +296,16 @@ :path (:path component) :objects objects}]] - (rx/of (dch/commit-changes rchanges uchanges {:commit-local? true})))))) + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it})))))) (defn duplicate-component "Create a new component copied from the one with the given id." [{:keys [id] :as params}] (ptk/reify ::duplicate-component ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [component (cp/get-component id (:current-file-id state) (dwlh/get-local-file state) @@ -303,7 +326,9 @@ uchanges [{:type :del-component :id (:id new-shape)}]] - (rx/of (dch/commit-changes rchanges uchanges {:commit-local? true})))))) + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it})))))) (defn delete-component "Delete the component with the given id, from the current file library." @@ -311,7 +336,7 @@ (us/assert ::us/uuid id) (ptk/reify ::delete-component ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [component (get-in state [:workspace-data :components id]) rchanges [{:type :del-component @@ -323,7 +348,9 @@ :path (:path component) :shapes (vals (:objects component))}]] - (rx/of (dch/commit-changes rchanges uchanges {:commit-local? true})))))) + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it})))))) (defn instantiate-component "Create a new shape in the current page, from the component with the given id @@ -334,7 +361,7 @@ (us/assert ::us/point position) (ptk/reify ::instantiate-component ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [local-library (dwlh/get-local-file state) libraries (get state :workspace-libraries) component (cp/get-component component-id file-id local-library libraries) @@ -400,7 +427,9 @@ :ignore-touched true}) new-shapes)] - (rx/of (dch/commit-changes rchanges uchanges {:commit-local? true}) + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it}) (dwc/select-shapes (d/ordered-set (:id new-shape)))))))) (defn detach-component @@ -410,7 +439,7 @@ (us/assert ::us/uuid id) (ptk/reify ::detach-component ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) shapes (cp/get-object-with-children id objects) @@ -463,14 +492,16 @@ :val (:touched obj)}]}) shapes)] - (rx/of (dch/commit-changes rchanges uchanges {:commit-local? true})))))) + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it})))))) (defn nav-to-component-file [file-id] (us/assert ::us/uuid file-id) (ptk/reify ::nav-to-component-file ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [file (get-in state [:workspace-libraries file-id]) pparams {:project-id (:project-id file) :file-id (:id file)} @@ -499,7 +530,7 @@ (us/assert ::us/uuid id) (ptk/reify ::reset-component ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (log/info :msg "RESET-COMPONENT of shape" :id (str id)) (let [local-library (dwlh/get-local-file state) libraries (dwlh/get-libraries state) @@ -516,7 +547,9 @@ rchanges local-library)) - (rx/of (dch/commit-changes rchanges uchanges {:commit-local? true})))))) + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it})))))) (defn update-component "Modify the component linked to the shape with the given id, in the @@ -531,7 +564,7 @@ (us/assert ::us/uuid id) (ptk/reify ::update-component ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (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) @@ -571,12 +604,14 @@ file)) (rx/of (when (seq local-rchanges) - (dch/commit-changes local-rchanges local-uchanges - {:commit-local? true + (dch/commit-changes {:redo-changes local-rchanges + :undo-changes local-uchanges + :origin it :file-id (:id local-library)})) (when (seq rchanges) - (dch/commit-changes rchanges uchanges - {:commit-local? true + (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it :file-id file-id}))))))) (declare sync-file-2nd-stage) @@ -597,7 +632,7 @@ state)) ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (log/info :msg "SYNC-FILE" :file (dwlh/pretty-file file-id state) :library (dwlh/pretty-file library-id state)) @@ -625,8 +660,10 @@ (rx/concat (rx/of (dm/hide-tag :sync-dialog)) (when rchanges - (rx/of (dch/commit-changes rchanges uchanges {:commit-local? true - :file-id file-id}))) + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it + :file-id file-id}))) (when (not= file-id library-id) ;; When we have just updated the library file, give some time for the ;; update to finish, before marking this file as synced. @@ -655,7 +692,7 @@ (us/assert ::us/uuid library-id) (ptk/reify ::sync-file-2nd-stage ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (log/info :msg "SYNC-FILE (2nd stage)" :file (dwlh/pretty-file file-id state) :library (dwlh/pretty-file library-id state)) @@ -668,8 +705,10 @@ (log/debug :msg "SYNC-FILE (2nd stage) finished" :js/rchanges (log-changes rchanges file)) - (rx/of (dch/commit-changes rchanges uchanges {:commit-local? true - :file-id file-id}))))))) + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it + :file-id file-id}))))))) (def ignore-sync (ptk/reify ::ignore-sync @@ -678,7 +717,7 @@ (assoc-in state [:workspace-file :ignore-sync-until] (dt/now))) ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (rp/mutation :ignore-sync {:file-id (get-in state [:workspace-file :id]) :date (dt/now)})))) @@ -688,7 +727,7 @@ (us/assert ::us/uuid file-id) (ptk/reify ::notify-sync-file ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [libraries-need-sync (filter #(> (:modified-at %) (:synced-at %)) (vals (get state :workspace-libraries))) do-update #(do (apply st/emit! (map (fn [library] diff --git a/frontend/src/app/main/data/workspace/path/changes.cljs b/frontend/src/app/main/data/workspace/path/changes.cljs index 08a86c2be..8461b2e68 100644 --- a/frontend/src/app/main/data/workspace/path/changes.cljs +++ b/frontend/src/app/main/data/workspace/path/changes.cljs @@ -84,7 +84,7 @@ (assoc-in state (st/get-path state :content) content))) ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [objects (wsh/lookup-page-objects state) page-id (:current-page-id state) id (get-in state [:workspace-local :edition]) @@ -92,7 +92,9 @@ (if (some? old-content) (let [shape (get-in state (st/get-path state)) [rch uch] (generate-path-changes objects page-id shape old-content (:content shape))] - (rx/of (dch/commit-changes rch uch))) + (rx/of (dch/commit-changes {:redo-changes rch + :undo-changes uch + :origin it}))) (rx/empty))))))) diff --git a/frontend/src/app/main/data/workspace/path/edition.cljs b/frontend/src/app/main/data/workspace/path/edition.cljs index b2217ea5e..9f5b3b639 100644 --- a/frontend/src/app/main/data/workspace/path/edition.cljs +++ b/frontend/src/app/main/data/workspace/path/edition.cljs @@ -47,7 +47,7 @@ (defn apply-content-modifiers [] (ptk/reify ::apply-content-modifiers ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [objects (wsh/lookup-page-objects state) id (st/get-path-id state) @@ -65,9 +65,13 @@ [rch uch] (changes/generate-path-changes objects page-id shape (:content shape) new-content)] (if (empty? new-content) - (rx/of (dch/commit-changes rch uch {:commit-local? true}) + (rx/of (dch/commit-changes {:redo-changes rch + :undo-changes uch + :origin it}) dwc/clear-edition-mode) - (rx/of (dch/commit-changes rch uch {:commit-local? true}) + (rx/of (dch/commit-changes {:redo-changes rch + :undo-changes uch + :origin it}) (selection/update-selection point-change) (fn [state] (update-in state [:workspace-local :edit-path id] dissoc :content-modifiers :moving-nodes :moving-handler)))))))) @@ -133,7 +137,7 @@ [position shift?] (ptk/reify ::start-move-path-point ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [id (get-in state [:workspace-local :edition]) selected-points (get-in state [:workspace-local :edit-path id :selected-points] #{}) selected? (contains? selected-points position)] @@ -147,7 +151,7 @@ [start-position] (ptk/reify ::drag-selected-points ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [stopper (->> stream (rx/filter ms/mouse-up?)) id (get-in state [:workspace-local :edition]) snap-toggled (get-in state [:workspace-local :edit-path id :snap-toggled]) @@ -202,7 +206,7 @@ state))) ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [id (get-in state [:workspace-local :edition]) current-move (get-in state [:workspace-local :edit-path id :current-move])] (if (= same-event current-move) @@ -236,7 +240,7 @@ [index prefix] (ptk/reify ::start-move-handler ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [id (get-in state [:workspace-local :edition]) cx (d/prefix-keyword prefix :x) cy (d/prefix-keyword prefix :y) @@ -292,7 +296,7 @@ (assoc-in [:workspace-local :edit-path id :edit-mode] :draw)))) ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [mode (get-in state [:workspace-local :edit-path id :edit-mode])] (rx/concat (rx/of (undo/start-path-undo)) @@ -322,5 +326,5 @@ (update-in (st/get-path state :content) upt/split-segments #{from-p to-p} t)))) ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (rx/of (changes/save-path-content {:preserve-move-to true}))))) diff --git a/frontend/src/app/main/data/workspace/path/tools.cljs b/frontend/src/app/main/data/workspace/path/tools.cljs index a6771a54f..ddd2ed3f2 100644 --- a/frontend/src/app/main/data/workspace/path/tools.cljs +++ b/frontend/src/app/main/data/workspace/path/tools.cljs @@ -25,7 +25,7 @@ ([points tool-fn] (ptk/reify ::process-path-tool ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [objects (wsh/lookup-page-objects state) id (st/get-path-id state) page-id (:current-page-id state) @@ -37,7 +37,9 @@ (let [new-content (-> (tool-fn (:content shape) points) (ups/close-subpaths)) [rch uch] (changes/generate-path-changes objects page-id shape (:content shape) new-content)] - (rx/of (dch/commit-changes rch uch {:commit-local? true}) + (rx/of (dch/commit-changes {:redo-changes rch + :undo-changes uch + :origin it}) (when (empty? new-content) dwc/clear-edition-mode))))))))) diff --git a/frontend/src/app/main/data/workspace/persistence.cljs b/frontend/src/app/main/data/workspace/persistence.cljs index d48d681bd..665547944 100644 --- a/frontend/src/app/main/data/workspace/persistence.cljs +++ b/frontend/src/app/main/data/workspace/persistence.cljs @@ -86,9 +86,11 @@ (rx/tap on-dirty) (rx/buffer-until notifier) (rx/filter (complement empty?)) - (rx/map (fn [buf] {:file-id file-id - :changes (into [] (mapcat :changes) buf)})) - (rx/map persist-changes) + (rx/map (fn [buf] + (->> (into [] (comp (map #(assoc % :id (uuid/next))) + (map #(assoc % :file-id file-id))) + buf) + (persist-changes file-id)))) (rx/tap on-saving) (rx/take-until (rx/delay 100 stoper))) (->> stream @@ -109,27 +111,25 @@ (on-saved)))))))) (defn persist-changes - [{:keys [file-id changes]}] + [file-id changes] (us/verify ::us/uuid file-id) (ptk/reify ::persist-changes ptk/UpdateEvent (update [_ state] - (let [conj (fnil conj []) - chng {:id (uuid/next) - :changes changes}] - (update-in state [:workspace-persistence :queue] conj chng))) + (let [conj (fnil conj []) + into* (fnil into [])] + (update-in state [:workspace-persistence :queue] into* changes))) ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [sid (:session-id state) file (get state :workspace-file) queue (get-in state [:workspace-persistence :queue] []) - xf-cat (comp (mapcat :changes)) params {:id (:id file) :revn (:revn file) :session-id sid - :changes (into [] xf-cat queue)} + :changes-with-metadata (into [] queue)} ids (into #{} (map :id) queue) @@ -172,7 +172,7 @@ (us/verify ::us/uuid file-id) (ptk/reify ::persist-synchronous-changes ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [sid (:session-id state) file (get-in state [:workspace-libraries file-id]) @@ -255,7 +255,7 @@ [project-id file-id] (ptk/reify ::fetch-bundle ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (->> (rx/zip (rp/query :file {:id file-id}) (rp/query :team-users {:file-id file-id}) (rp/query :project {:id project-id}) @@ -295,7 +295,7 @@ (assoc-in state [:workspace-file :is-shared] is-shared)) ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [params {:id id :is-shared is-shared}] (->> (rp/mutation :set-file-shared params) (rx/ignore)))))) @@ -330,7 +330,7 @@ [file-id library-id] (ptk/reify ::link-file-to-library ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [fetched #(assoc-in %2 [:workspace-libraries (:id %1)] %1) params {:file-id file-id :library-id library-id}] @@ -342,7 +342,7 @@ [file-id library-id] (ptk/reify ::unlink-file-from-library ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [unlinked #(d/dissoc-in % [:workspace-libraries library-id]) params {:file-id file-id :library-id library-id}] @@ -358,7 +358,7 @@ (us/verify ::us/uuid page-id) (ptk/reify ::fetch-pages ptk/WatchEvent - (watch [_ state s] + (watch [it state s] (->> (rp/query :page {:id page-id}) (rx/map page-fetched))))) @@ -498,7 +498,7 @@ (us/assert ::process-media-objects params) (ptk/reify ::process-media-objects ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (rx/concat (rx/of (dm/show {:content (tr "media.loading") :type :info @@ -545,7 +545,7 @@ (us/assert ::clone-media-objects-params params) (ptk/reify ::clone-media-objects ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [{:keys [on-success on-error] :or {on-success identity on-error identity}} (meta params) diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index f73e22467..52d36ee35 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -378,11 +378,12 @@ (def duplicate-selected (ptk/reify ::duplicate-selected ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) selected (wsh/lookup-selected state) delta (gpt/point 0 0) + unames (dwc/retrieve-used-names objects) rchanges (->> (prepare-duplicate-changes objects page-id unames selected delta) @@ -396,7 +397,9 @@ (map #(get-in % [:obj :id])) (into (d/ordered-set)))] - (rx/of (dch/commit-changes rchanges uchanges {:commit-local? true}) + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it}) (select-shapes selected)))))) (defn change-hover-state diff --git a/frontend/src/app/main/data/workspace/svg_upload.cljs b/frontend/src/app/main/data/workspace/svg_upload.cljs index 6d34597f3..f2828eb3f 100644 --- a/frontend/src/app/main/data/workspace/svg_upload.cljs +++ b/frontend/src/app/main/data/workspace/svg_upload.cljs @@ -387,7 +387,7 @@ [svg-data file-id position] (ptk/reify ::svg-uploaded ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] ;; Once the SVG is uploaded, we need to extract all the bitmap ;; images and upload them separatelly, then proceed to create ;; all shapes. @@ -414,7 +414,7 @@ [svg-data {:keys [x y] :as position}] (ptk/reify ::create-svg-shapes ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (try (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) @@ -464,7 +464,9 @@ rchanges (conj rchanges reg-objects-action)] - (rx/of (dch/commit-changes rchanges uchanges {:commit-local? true}) + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it}) (dwc/select-shapes (d/ordered-set root-id)))) (catch :default e diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index 110f5c8c7..5d431348a 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -141,7 +141,7 @@ (assoc-in [:workspace-local :transform] :resize))) ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [initial-position @ms/mouse-position stoper (rx/filter ms/mouse-up? stream) layout (:workspace-layout state) @@ -175,7 +175,7 @@ (assoc-in [:workspace-local :transform] :rotate))) ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [stoper (rx/filter ms/mouse-up? stream) group (gsh/selection-rect shapes) group-center (gsh/center-selrect group) @@ -214,7 +214,7 @@ [] (ptk/reify ::start-move-selected ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [initial (deref ms/mouse-position) selected (wsh/lookup-selected state) stopper (rx/filter ms/mouse-up? stream)] @@ -237,7 +237,7 @@ (defn start-move-duplicate [from-position] (ptk/reify ::start-move-selected ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (->> stream (rx/filter (ptk/type? ::dws/duplicate-selected)) (rx/first) @@ -246,7 +246,7 @@ (defn calculate-frame-for-move [ids] (ptk/reify ::calculate-frame-for-move ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [position @ms/mouse-position page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) @@ -273,7 +273,9 @@ (when-not (empty? uch) (rx/of dwu/pop-undo-into-transaction - (dch/commit-changes rch uch {:commit-local? true}) + (dch/commit-changes {:redo-changes rch + :undo-changes uch + :origin it}) (dwu/commit-undo-transaction) (dwc/expand-collapse frame-id))))))) @@ -287,7 +289,7 @@ (assoc-in [:workspace-local :transform] :move))) ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) ids (if (nil? ids) (wsh/lookup-selected state) ids) @@ -368,7 +370,7 @@ state)) ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (if (= same-event (get-in state [:workspace-local :current-move-selected])) (let [selected (wsh/lookup-selected state) move-events (->> stream @@ -455,7 +457,7 @@ (defn increase-rotation [ids rotation] (ptk/reify ::increase-rotation ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) @@ -471,7 +473,7 @@ (us/verify (s/coll-of uuid?) ids) (ptk/reify ::apply-modifiers ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [objects (wsh/lookup-page-objects state) children-ids (->> ids (mapcat #(cp/get-children % objects))) ids-with-children (d/concat [] children-ids ids)] @@ -517,7 +519,7 @@ #(reduce update-shape % ids)))) ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) ids (d/concat [] ids (mapcat #(cp/get-children % objects) ids))] @@ -526,7 +528,7 @@ (defn flip-horizontal-selected [] (ptk/reify ::flip-horizontal-selected ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [objects (wsh/lookup-page-objects state) selected (wsh/lookup-selected state) shapes (map #(get objects %) selected) @@ -543,7 +545,7 @@ (defn flip-vertical-selected [] (ptk/reify ::flip-vertical-selected ptk/WatchEvent - (watch [_ state stream] + (watch [it state stream] (let [objects (wsh/lookup-page-objects state) selected (wsh/lookup-selected state) shapes (map #(get objects %) selected) diff --git a/frontend/src/app/main/store.cljs b/frontend/src/app/main/store.cljs index 6a4ea6534..f4f15b941 100644 --- a/frontend/src/app/main/store.cljs +++ b/frontend/src/app/main/store.cljs @@ -23,6 +23,21 @@ (defonce state (ptk/store {:resolve ptk/resolve})) (defonce stream (ptk/input-stream state)) +(defonce last-events + (let [buffer (atom #queue []) + remove #{:potok.core/undefined + :app.main.data.workspace.notifications/handle-pointer-update}] + (->> stream + (rx/filter ptk/event?) + (rx/map ptk/type) + (rx/filter (complement remove)) + (rx/map str) + (rx/dedupe) + (rx/buffer 20 1) + (rx/subs #(reset! buffer %))) + + buffer)) + (when *assert* (defonce debug-subscription (->> stream @@ -47,6 +62,9 @@ (defn ^:export dump-state [] (logjs "state" @state)) +(defn ^:export dump-buffer [] + (logjs "state" @last-events)) + (defn ^:export get-state [str-path] (let [path (->> (str/split str-path " ") (map d/read-string))]