mirror of
https://github.com/penpot/penpot.git
synced 2025-05-16 06:06:13 +02:00
♻️ Refactor commit-changes and undo actions
This commit is contained in:
parent
da8a32047c
commit
59187f9ff4
30 changed files with 508 additions and 457 deletions
|
@ -7,7 +7,6 @@
|
|||
(ns app.main.data.workspace
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.geom.align :as gal]
|
||||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.geom.point :as gpt]
|
||||
|
@ -19,37 +18,31 @@
|
|||
[app.common.spec :as us]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cfg]
|
||||
[app.main.constants :as c]
|
||||
[app.main.data.workspace.colors :as mdc]
|
||||
[app.main.data.messages :as dm]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.drawing :as dwd]
|
||||
[app.main.data.workspace.path :as dwdp]
|
||||
[app.main.data.workspace.groups :as dwg]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.notifications :as dwn]
|
||||
[app.main.data.workspace.path :as dwdp]
|
||||
[app.main.data.workspace.persistence :as dwp]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.transforms :as dwt]
|
||||
[app.main.data.workspace.svg-upload :as svg]
|
||||
[app.main.data.workspace.transforms :as dwt]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.store :as st]
|
||||
[app.main.streams :as ms]
|
||||
[app.main.worker :as uw]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.http :as http]
|
||||
[app.util.i18n :refer [tr] :as i18n]
|
||||
[app.util.i18n :as i18n]
|
||||
[app.util.logging :as log]
|
||||
[app.util.object :as obj]
|
||||
[app.util.router :as rt]
|
||||
[app.util.timers :as ts]
|
||||
[app.util.transit :as t]
|
||||
[app.util.webapi :as wapi]
|
||||
[beicon.core :as rx]
|
||||
[cljs.spec.alpha :as s]
|
||||
[clojure.set :as set]
|
||||
[cuerdas.core :as str]
|
||||
[goog.string.path :as path]
|
||||
[potok.core :as ptk]))
|
||||
|
||||
;; (log/set-level! :trace)
|
||||
|
@ -269,7 +262,7 @@
|
|||
:name name}
|
||||
uchange {:type :del-page
|
||||
:id id}]
|
||||
(rx/of (dwc/commit-changes [rchange] [uchange] {:commit-local? true}))))))
|
||||
(rx/of (dch/commit-changes [rchange] [uchange] {:commit-local? true}))))))
|
||||
|
||||
(defn duplicate-page [page-id]
|
||||
(ptk/reify ::duplicate-page
|
||||
|
@ -287,7 +280,7 @@
|
|||
:page page}
|
||||
uchange {:type :del-page
|
||||
:id id}]
|
||||
(rx/of (dwc/commit-changes [rchange] [uchange] {:commit-local? true}))))))
|
||||
(rx/of (dch/commit-changes [rchange] [uchange] {:commit-local? true}))))))
|
||||
|
||||
(s/def ::rename-page
|
||||
(s/keys :req-un [::id ::name]))
|
||||
|
@ -306,7 +299,7 @@
|
|||
uchg {:type :mod-page
|
||||
:id id
|
||||
:name (:name page)}]
|
||||
(rx/of (dwc/commit-changes [rchg] [uchg] {:commit-local? true}))))))
|
||||
(rx/of (dch/commit-changes [rchg] [uchg] {:commit-local? true}))))))
|
||||
|
||||
(declare purge-page)
|
||||
(declare go-to-file)
|
||||
|
@ -323,7 +316,7 @@
|
|||
:id id}
|
||||
uchg {:type :add-page
|
||||
:page page}]
|
||||
(rx/of (dwc/commit-changes [rchg] [uchg] {:commit-local? true})
|
||||
(rx/of (dch/commit-changes [rchg] [uchg] {:commit-local? true})
|
||||
(when (= id (:current-page-id state))
|
||||
go-to-file))))))
|
||||
|
||||
|
@ -604,7 +597,7 @@
|
|||
(ptk/reify ::update-shape
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(rx/of (dwc/update-shapes [id] #(merge % attrs))))))
|
||||
(rx/of (dch/update-shapes [id] #(merge % attrs))))))
|
||||
|
||||
(defn start-rename-shape
|
||||
[id]
|
||||
|
@ -712,7 +705,7 @@
|
|||
:index (cp/position-on-parent id objects)}))
|
||||
selected)]
|
||||
;; TODO: maybe missing the :reg-objects event?
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))))))
|
||||
(rx/of (dch/commit-changes rchanges uchanges {:commit-local? true}))))))
|
||||
|
||||
|
||||
;; --- Change Shape Order (D&D Ordering)
|
||||
|
@ -986,7 +979,7 @@
|
|||
shapes-to-detach
|
||||
shapes-to-reroot
|
||||
shapes-to-deroot)]
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(rx/of (dch/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(dwc/expand-collapse parent-id))))))
|
||||
|
||||
(defn relocate-selected-shapes
|
||||
|
@ -1039,7 +1032,7 @@
|
|||
uchg {:type :mov-page
|
||||
:id id
|
||||
:index cidx}]
|
||||
(rx/of (dwc/commit-changes [rchg] [uchg] {:commit-local? true}))))))
|
||||
(rx/of (dch/commit-changes [rchg] [uchg] {:commit-local? true}))))))
|
||||
|
||||
;; --- Shape / Selection Alignment and Distribution
|
||||
|
||||
|
@ -1141,7 +1134,7 @@
|
|||
(assoc shape :proportion-lock false)
|
||||
(-> (assoc shape :proportion-lock true)
|
||||
(gpr/assign-proportions))))]
|
||||
(rx/of (dwc/update-shapes [id] assign-proportions))))))
|
||||
(rx/of (dch/update-shapes [id] assign-proportions))))))
|
||||
|
||||
;; --- Update Shape Position
|
||||
|
||||
|
@ -1183,7 +1176,7 @@
|
|||
(cond-> obj
|
||||
(boolean? blocked) (assoc :blocked blocked)
|
||||
(boolean? hidden) (assoc :hidden hidden)))]
|
||||
(rx/of (dwc/update-shapes-recursive [id] update-fn))))))
|
||||
(rx/of (dch/update-shapes-recursive [id] update-fn))))))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -1410,7 +1403,7 @@
|
|||
(catch :default e
|
||||
(let [data (ex-data e)]
|
||||
(if (:not-implemented data)
|
||||
(rx/of (dm/warn (tr "errors.clipboard-not-implemented")))
|
||||
(rx/of (dm/warn (i18n/tr "errors.clipboard-not-implemented")))
|
||||
(js/console.error "ERROR" e))))))))
|
||||
|
||||
(defn paste-from-event
|
||||
|
@ -1582,7 +1575,7 @@
|
|||
(map #(get-in % [:obj :id]))
|
||||
(into (d/ordered-set)))]
|
||||
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(rx/of (dch/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(dwc/select-shapes selected))))]
|
||||
(ptk/reify ::paste-shape
|
||||
ptk/WatchEvent
|
||||
|
@ -1629,10 +1622,10 @@
|
|||
:height height
|
||||
:grow-type (if (> (count text) 100) :auto-height :auto-width)
|
||||
:content (as-content text)})]
|
||||
(rx/of (dwc/start-undo-transaction)
|
||||
(rx/of (dwu/start-undo-transaction)
|
||||
(dws/deselect-all)
|
||||
(dwc/add-shape shape)
|
||||
(dwc/commit-undo-transaction))))))
|
||||
(dwu/commit-undo-transaction))))))
|
||||
|
||||
(defn- paste-svg
|
||||
[text]
|
||||
|
@ -1743,7 +1736,7 @@
|
|||
(let [page-id (get state :current-page-id)
|
||||
options (dwc/lookup-page-options state page-id)
|
||||
previus-color (:background options)]
|
||||
(rx/of (dwc/commit-changes
|
||||
(rx/of (dch/commit-changes
|
||||
[{:type :set-option
|
||||
:page-id page-id
|
||||
:option :background
|
||||
|
|
219
frontend/src/app/main/data/workspace/changes.cljs
Normal file
219
frontend/src/app/main/data/workspace/changes.cljs
Normal file
|
@ -0,0 +1,219 @@
|
|||
;; 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.changes
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.pages.spec :as spec]
|
||||
[app.common.spec :as us]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.worker :as uw]
|
||||
[app.util.logging :as log]
|
||||
[beicon.core :as rx]
|
||||
[cljs.spec.alpha :as s]
|
||||
[clojure.set :as set]
|
||||
[potok.core :as ptk]))
|
||||
|
||||
;; Change this to :info :debug or :trace to debug this module
|
||||
(log/set-level! :warn)
|
||||
|
||||
(s/def ::coll-of-uuid
|
||||
(s/every ::us/uuid))
|
||||
|
||||
(defonce page-change? #{:add-page :mod-page :del-page :mov-page})
|
||||
|
||||
(declare commit-changes)
|
||||
|
||||
(def commit-changes? (ptk/type? ::commit-changes))
|
||||
|
||||
(defn- generate-operations
|
||||
([ma mb] (generate-operations ma mb false))
|
||||
([ma mb undo?]
|
||||
(let [ops (let [ma-keys (set (keys ma))
|
||||
mb-keys (set (keys mb))
|
||||
added (set/difference mb-keys ma-keys)
|
||||
removed (set/difference ma-keys mb-keys)
|
||||
both (set/intersection ma-keys mb-keys)]
|
||||
(d/concat
|
||||
(mapv #(array-map :type :set :attr % :val (get mb %)) added)
|
||||
(mapv #(array-map :type :set :attr % :val nil) removed)
|
||||
(loop [items (seq both)
|
||||
result []]
|
||||
(if items
|
||||
(let [k (first items)
|
||||
vma (get ma k)
|
||||
vmb (get mb k)]
|
||||
(if (= vma vmb)
|
||||
(recur (next items) result)
|
||||
(recur (next items)
|
||||
(conj result {:type :set
|
||||
:attr k
|
||||
:val vmb
|
||||
:ignore-touched undo?}))))
|
||||
result))))]
|
||||
(if undo?
|
||||
(conj ops {:type :set-touched :touched (:touched mb)})
|
||||
ops))))
|
||||
|
||||
(defn update-shapes
|
||||
([ids f] (update-shapes ids f nil))
|
||||
([ids f {:keys [reg-objects?] :or {reg-objects? false}}]
|
||||
(us/assert ::coll-of-uuid ids)
|
||||
(us/assert fn? f)
|
||||
(ptk/reify ::update-shapes
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (get-in state [:workspace-data :pages-index page-id :objects])]
|
||||
(loop [ids (seq ids)
|
||||
rch []
|
||||
uch []]
|
||||
(if (nil? ids)
|
||||
(rx/of (commit-changes
|
||||
(cond-> rch reg-objects? (conj {:type :reg-objects :page-id page-id :shapes (vec ids)}))
|
||||
(cond-> uch reg-objects? (conj {:type :reg-objects :page-id page-id :shapes (vec ids)}))
|
||||
{:commit-local? true}))
|
||||
|
||||
(let [id (first ids)
|
||||
obj1 (get objects id)
|
||||
obj2 (f obj1)
|
||||
rch-operations (generate-operations obj1 obj2)
|
||||
uch-operations (generate-operations obj2 obj1 true)
|
||||
rchg {:type :mod-obj
|
||||
:page-id page-id
|
||||
:operations rch-operations
|
||||
:id id}
|
||||
uchg {:type :mod-obj
|
||||
:page-id page-id
|
||||
:operations uch-operations
|
||||
:id id}]
|
||||
(recur (next ids)
|
||||
(if (empty? rch-operations) rch (conj rch rchg))
|
||||
(if (empty? uch-operations) uch (conj uch uchg)))))))))))
|
||||
|
||||
(defn update-shapes-recursive
|
||||
[ids f]
|
||||
(us/assert ::coll-of-uuid ids)
|
||||
(us/assert fn? f)
|
||||
(letfn [(impl-get-children [objects id]
|
||||
(cons id (cp/get-children id objects)))
|
||||
|
||||
(impl-gen-changes [objects page-id ids]
|
||||
(loop [sids (seq ids)
|
||||
cids (seq (impl-get-children objects (first sids)))
|
||||
rchanges []
|
||||
uchanges []]
|
||||
(cond
|
||||
(nil? sids)
|
||||
[rchanges uchanges]
|
||||
|
||||
(nil? cids)
|
||||
(recur (next sids)
|
||||
(seq (impl-get-children objects (first (next sids))))
|
||||
rchanges
|
||||
uchanges)
|
||||
|
||||
:else
|
||||
(let [id (first cids)
|
||||
obj1 (get objects id)
|
||||
obj2 (f obj1)
|
||||
rops (generate-operations obj1 obj2)
|
||||
uops (generate-operations obj2 obj1 true)
|
||||
rchg {:type :mod-obj
|
||||
:page-id page-id
|
||||
:operations rops
|
||||
:id id}
|
||||
uchg {:type :mod-obj
|
||||
:page-id page-id
|
||||
:operations uops
|
||||
:id id}]
|
||||
(recur sids
|
||||
(next cids)
|
||||
(conj rchanges rchg)
|
||||
(conj uchanges uchg))))))]
|
||||
(ptk/reify ::update-shapes-recursive
|
||||
ptk/WatchEvent
|
||||
(watch [_ 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})))))))
|
||||
|
||||
(defn update-indices
|
||||
[page-id changes]
|
||||
(ptk/reify ::update-indices
|
||||
ptk/EffectEvent
|
||||
(effect [_ state stream]
|
||||
(uw/ask! {:cmd :update-page-indices
|
||||
:page-id page-id
|
||||
:changes changes}))))
|
||||
|
||||
(defn commit-changes
|
||||
([changes undo-changes]
|
||||
(commit-changes changes undo-changes {}))
|
||||
([changes undo-changes {:keys [save-undo?
|
||||
commit-local?
|
||||
file-id]
|
||||
:or {save-undo? true
|
||||
commit-local? false}
|
||||
:as opts}]
|
||||
(us/verify ::cp/changes changes)
|
||||
(us/verify ::cp/changes undo-changes)
|
||||
(log/debug :msg "commit-changes"
|
||||
:js/changes changes
|
||||
:js/undo-changes undo-changes)
|
||||
|
||||
(let [error (volatile! nil)]
|
||||
(ptk/reify ::commit-changes
|
||||
cljs.core/IDeref
|
||||
(-deref [_] {:file-id file-id :changes changes})
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [current-file-id (get state :current-file-id)
|
||||
file-id (or file-id current-file-id)
|
||||
path1 (if (= file-id current-file-id)
|
||||
[:workspace-file :data]
|
||||
[:workspace-libraries file-id :data])
|
||||
path2 (if (= file-id current-file-id)
|
||||
[:workspace-data]
|
||||
[:workspace-libraries file-id :data])]
|
||||
(try
|
||||
(us/verify ::spec/changes changes)
|
||||
(let [state (update-in state path1 cp/process-changes changes false)]
|
||||
(cond-> state
|
||||
commit-local? (update-in path2 cp/process-changes 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)))))
|
||||
|
||||
changes-by-pages
|
||||
(->> 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))
|
||||
|
||||
(when (and save-undo? (seq undo-changes))
|
||||
(let [entry {:undo-changes undo-changes
|
||||
:redo-changes changes}]
|
||||
(rx/of (dwu/append-undo entry))))))))))))
|
|
@ -13,6 +13,7 @@
|
|||
[app.main.data.modal :as md]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.texts :as dwt]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.store :as st]
|
||||
[app.main.streams :as ms]
|
||||
|
@ -150,7 +151,7 @@
|
|||
|
||||
(rx/concat
|
||||
(rx/from (map #(dwt/update-text-attrs {:id % :attrs attrs}) text-ids))
|
||||
(rx/of (dwc/update-shapes shape-ids (fn [shape] (d/merge shape attrs)))))))))
|
||||
(rx/of (dch/update-shapes shape-ids (fn [shape] (d/merge shape attrs)))))))))
|
||||
|
||||
(defn change-stroke
|
||||
[ids color]
|
||||
|
@ -176,7 +177,7 @@
|
|||
(contains? color :opacity)
|
||||
(assoc :stroke-opacity (:opacity color)))]
|
||||
|
||||
(rx/of (dwc/update-shapes ids (fn [shape]
|
||||
(rx/of (dch/update-shapes ids (fn [shape]
|
||||
(cond-> (d/merge shape attrs)
|
||||
(= (:stroke-style shape) :none)
|
||||
(assoc :stroke-style :solid
|
||||
|
|
|
@ -10,17 +10,15 @@
|
|||
[app.common.geom.proportions :as gpr]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.pages.spec :as spec]
|
||||
[app.common.spec :as us]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.worker :as uw]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.streams :as ms]
|
||||
[app.main.worker :as uw]
|
||||
[app.util.logging :as log]
|
||||
[app.util.timers :as ts]
|
||||
[beicon.core :as rx]
|
||||
[cljs.spec.alpha :as s]
|
||||
[clojure.set :as set]
|
||||
[cuerdas.core :as str]
|
||||
[potok.core :as ptk]))
|
||||
|
||||
;; Change this to :info :debug or :trace to debug this module
|
||||
|
@ -58,121 +56,6 @@
|
|||
(get-in state [:workspace-data :components component-id :objects])))
|
||||
|
||||
|
||||
;; --- Changes Handling
|
||||
|
||||
(defonce page-change? #{:add-page :mod-page :del-page :mov-page})
|
||||
|
||||
(defn commit-changes
|
||||
([changes undo-changes]
|
||||
(commit-changes changes undo-changes {}))
|
||||
([changes undo-changes {:keys [save-undo?
|
||||
commit-local?
|
||||
file-id]
|
||||
:or {save-undo? true
|
||||
commit-local? false}
|
||||
:as opts}]
|
||||
(us/verify ::cp/changes changes)
|
||||
(us/verify ::cp/changes undo-changes)
|
||||
(log/debug :msg "commit-changes"
|
||||
:js/changes changes
|
||||
:js/undo-changes undo-changes)
|
||||
|
||||
(let [error (volatile! nil)]
|
||||
(ptk/reify ::commit-changes
|
||||
cljs.core/IDeref
|
||||
(-deref [_] {:file-id file-id :changes changes})
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [current-file-id (get state :current-file-id)
|
||||
file-id (or file-id current-file-id)
|
||||
path1 (if (= file-id current-file-id)
|
||||
[:workspace-file :data]
|
||||
[:workspace-libraries file-id :data])
|
||||
path2 (if (= file-id current-file-id)
|
||||
[:workspace-data]
|
||||
[:workspace-libraries file-id :data])]
|
||||
(try
|
||||
(us/verify ::spec/changes changes)
|
||||
(let [state (update-in state path1 cp/process-changes changes false)]
|
||||
(cond-> state
|
||||
commit-local? (update-in path2 cp/process-changes 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)))))
|
||||
|
||||
changes-by-pages
|
||||
(->> 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))
|
||||
|
||||
(when (and save-undo? (seq undo-changes))
|
||||
(let [entry {:undo-changes undo-changes
|
||||
:redo-changes changes}]
|
||||
(rx/of (append-undo entry))))))))))))
|
||||
|
||||
(defn generate-operations
|
||||
([ma mb] (generate-operations ma mb false))
|
||||
([ma mb undo?]
|
||||
(let [ops (let [ma-keys (set (keys ma))
|
||||
mb-keys (set (keys mb))
|
||||
added (set/difference mb-keys ma-keys)
|
||||
removed (set/difference ma-keys mb-keys)
|
||||
both (set/intersection ma-keys mb-keys)]
|
||||
(d/concat
|
||||
(mapv #(array-map :type :set :attr % :val (get mb %)) added)
|
||||
(mapv #(array-map :type :set :attr % :val nil) removed)
|
||||
(loop [items (seq both)
|
||||
result []]
|
||||
(if items
|
||||
(let [k (first items)
|
||||
vma (get ma k)
|
||||
vmb (get mb k)]
|
||||
(if (= vma vmb)
|
||||
(recur (next items) result)
|
||||
(recur (next items)
|
||||
(conj result {:type :set
|
||||
:attr k
|
||||
:val vmb
|
||||
:ignore-touched undo?}))))
|
||||
result))))]
|
||||
(if undo?
|
||||
(conj ops {:type :set-touched :touched (:touched mb)})
|
||||
ops))))
|
||||
|
||||
(defn generate-changes
|
||||
[page-id objects1 objects2]
|
||||
(letfn [(impl-diff [res id]
|
||||
(let [obj1 (get objects1 id)
|
||||
obj2 (get objects2 id)
|
||||
ops (generate-operations (dissoc obj1 :shapes :frame-id)
|
||||
(dissoc obj2 :shapes :frame-id))]
|
||||
(if (empty? ops)
|
||||
res
|
||||
(conj res {:type :mod-obj
|
||||
:page-id page-id
|
||||
:operations ops
|
||||
:id id}))))]
|
||||
(reduce impl-diff [] (set/union (set (keys objects1))
|
||||
(set (keys objects2))))))
|
||||
|
||||
;; --- Selection Index Handling
|
||||
|
||||
(defn initialize-indices
|
||||
|
@ -186,14 +69,7 @@
|
|||
(->> (uw/ask! msg)
|
||||
(rx/map (constantly ::index-initialized)))))))
|
||||
|
||||
(defn update-indices
|
||||
[page-id changes]
|
||||
(ptk/reify ::update-indices
|
||||
ptk/EffectEvent
|
||||
(effect [_ state stream]
|
||||
(uw/ask! {:cmd :update-page-indices
|
||||
:page-id page-id
|
||||
:changes changes}))))
|
||||
|
||||
|
||||
;; --- Common Helpers & Events
|
||||
|
||||
|
@ -253,110 +129,8 @@
|
|||
(update state :workspace-local dissoc :expanded))))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Undo / Redo
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(s/def ::undo-changes ::cp/changes)
|
||||
(s/def ::redo-changes ::cp/changes)
|
||||
(s/def ::undo-entry
|
||||
(s/keys :req-un [::undo-changes ::redo-changes]))
|
||||
|
||||
(def MAX-UNDO-SIZE 50)
|
||||
|
||||
(defn- conj-undo-entry
|
||||
[undo data]
|
||||
(let [undo (conj undo data)
|
||||
cnt (count undo)]
|
||||
(if (> cnt MAX-UNDO-SIZE)
|
||||
(subvec undo (- cnt MAX-UNDO-SIZE))
|
||||
undo)))
|
||||
|
||||
(defn- materialize-undo
|
||||
[changes index]
|
||||
(ptk/reify ::materialize-undo
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(update :workspace-data cp/process-changes changes)
|
||||
(assoc-in [:workspace-undo :index] index)))))
|
||||
|
||||
(defn- reset-undo
|
||||
[index]
|
||||
(ptk/reify ::reset-undo
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(update :workspace-undo dissoc :undo-index)
|
||||
(update-in [:workspace-undo :items] (fn [queue] (into [] (take (inc index) queue))))))))
|
||||
|
||||
(defn- add-undo-entry
|
||||
[state entry]
|
||||
(if (and entry
|
||||
(not-empty (:undo-changes entry))
|
||||
(not-empty (:redo-changes entry)))
|
||||
(let [index (get-in state [:workspace-undo :index] -1)
|
||||
items (get-in state [:workspace-undo :items] [])
|
||||
items (->> items (take (inc index)) (into []))
|
||||
items (conj-undo-entry items entry)]
|
||||
(-> state
|
||||
(update :workspace-undo assoc :items items
|
||||
:index (min (inc index)
|
||||
(dec MAX-UNDO-SIZE)))))
|
||||
state))
|
||||
|
||||
(defn- accumulate-undo-entry
|
||||
[state {:keys [undo-changes redo-changes]}]
|
||||
(-> state
|
||||
(update-in [:workspace-undo :transaction :undo-changes] #(into undo-changes %))
|
||||
(update-in [:workspace-undo :transaction :redo-changes] #(into % redo-changes))))
|
||||
|
||||
(defn- append-undo
|
||||
[entry]
|
||||
(us/verify ::undo-entry entry)
|
||||
(ptk/reify ::append-undo
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(if (get-in state [:workspace-undo :transaction])
|
||||
(accumulate-undo-entry state entry)
|
||||
(add-undo-entry state entry)))))
|
||||
|
||||
(defonce empty-tx {:undo-changes [] :redo-changes []})
|
||||
|
||||
(defn start-undo-transaction []
|
||||
(ptk/reify ::start-undo-transaction
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
;; We commit the old transaction before starting the new one
|
||||
(let [current-tx (get-in state [:workspace-undo :transaction])]
|
||||
(cond-> state
|
||||
(nil? current-tx) (assoc-in [:workspace-undo :transaction] empty-tx))))))
|
||||
|
||||
(defn discard-undo-transaction []
|
||||
(ptk/reify ::discard-undo-transaction
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :workspace-undo dissoc :transaction))))
|
||||
|
||||
(defn commit-undo-transaction []
|
||||
(ptk/reify ::commit-undo-transaction
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(add-undo-entry (get-in state [:workspace-undo :transaction]))
|
||||
(update :workspace-undo dissoc :transaction)))))
|
||||
|
||||
(def pop-undo-into-transaction
|
||||
(ptk/reify ::last-undo-into-transaction
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [index (get-in state [:workspace-undo :index] -1)]
|
||||
|
||||
(cond-> state
|
||||
(>= index 0) (accumulate-undo-entry (get-in state [:workspace-undo :items index]))
|
||||
(>= index 0) (update-in [:workspace-undo :index] dec))))))
|
||||
|
||||
;; If these functions change modules review /src/app/main/data/workspace/path/undo.cljs
|
||||
;; These functions should've been in `src/app/main/data/workspace/undo.cljs` but doing that causes
|
||||
;; a circular dependency with `src/app/main/data/workspace/changes.cljs`
|
||||
(def undo
|
||||
(ptk/reify ::undo
|
||||
ptk/WatchEvent
|
||||
|
@ -370,8 +144,8 @@
|
|||
index (or (:index undo) (dec (count items)))]
|
||||
(when-not (or (empty? items) (= index -1))
|
||||
(let [changes (get-in items [index :undo-changes])]
|
||||
(rx/of (materialize-undo changes (dec index))
|
||||
(commit-changes changes [] {:save-undo? false}))))))))))
|
||||
(rx/of (dwu/materialize-undo changes (dec index))
|
||||
(dch/commit-changes changes [] {:save-undo? false}))))))))))
|
||||
|
||||
(def redo
|
||||
(ptk/reify ::redo
|
||||
|
@ -385,16 +159,8 @@
|
|||
index (or (:index undo) (dec (count items)))]
|
||||
(when-not (or (empty? items) (= index (dec (count items))))
|
||||
(let [changes (get-in items [(inc index) :redo-changes])]
|
||||
(rx/of (materialize-undo changes (inc index))
|
||||
(commit-changes changes [] {:save-undo? false}))))))))))
|
||||
|
||||
(def reinitialize-undo
|
||||
(ptk/reify ::reset-undo
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc state :workspace-undo {}))))
|
||||
|
||||
|
||||
(rx/of (dwu/materialize-undo changes (inc index))
|
||||
(dch/commit-changes changes [] {:save-undo? false}))))))))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Shapes
|
||||
|
@ -420,93 +186,6 @@
|
|||
;; NOTE: This is a generic implementation for update multiple shapes
|
||||
;; in one single commit/undo entry.
|
||||
|
||||
(s/def ::coll-of-uuid
|
||||
(s/every ::us/uuid))
|
||||
|
||||
(defn update-shapes
|
||||
([ids f] (update-shapes ids f nil))
|
||||
([ids f {:keys [reg-objects?] :or {reg-objects? false}}]
|
||||
(us/assert ::coll-of-uuid ids)
|
||||
(us/assert fn? f)
|
||||
(ptk/reify ::update-shapes
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (lookup-page-objects state page-id)]
|
||||
(loop [ids (seq ids)
|
||||
rch []
|
||||
uch []]
|
||||
(if (nil? ids)
|
||||
(rx/of (commit-changes
|
||||
(cond-> rch reg-objects? (conj {:type :reg-objects :page-id page-id :shapes (vec ids)}))
|
||||
(cond-> uch reg-objects? (conj {:type :reg-objects :page-id page-id :shapes (vec ids)}))
|
||||
{:commit-local? true}))
|
||||
|
||||
(let [id (first ids)
|
||||
obj1 (get objects id)
|
||||
obj2 (f obj1)
|
||||
rch-operations (generate-operations obj1 obj2)
|
||||
uch-operations (generate-operations obj2 obj1 true)
|
||||
rchg {:type :mod-obj
|
||||
:page-id page-id
|
||||
:operations rch-operations
|
||||
:id id}
|
||||
uchg {:type :mod-obj
|
||||
:page-id page-id
|
||||
:operations uch-operations
|
||||
:id id}]
|
||||
(recur (next ids)
|
||||
(if (empty? rch-operations) rch (conj rch rchg))
|
||||
(if (empty? uch-operations) uch (conj uch uchg)))))))))))
|
||||
|
||||
(defn update-shapes-recursive
|
||||
[ids f]
|
||||
(us/assert ::coll-of-uuid ids)
|
||||
(us/assert fn? f)
|
||||
(letfn [(impl-get-children [objects id]
|
||||
(cons id (cp/get-children id objects)))
|
||||
|
||||
(impl-gen-changes [objects page-id ids]
|
||||
(loop [sids (seq ids)
|
||||
cids (seq (impl-get-children objects (first sids)))
|
||||
rchanges []
|
||||
uchanges []]
|
||||
(cond
|
||||
(nil? sids)
|
||||
[rchanges uchanges]
|
||||
|
||||
(nil? cids)
|
||||
(recur (next sids)
|
||||
(seq (impl-get-children objects (first (next sids))))
|
||||
rchanges
|
||||
uchanges)
|
||||
|
||||
:else
|
||||
(let [id (first cids)
|
||||
obj1 (get objects id)
|
||||
obj2 (f obj1)
|
||||
rops (generate-operations obj1 obj2)
|
||||
uops (generate-operations obj2 obj1 true)
|
||||
rchg {:type :mod-obj
|
||||
:page-id page-id
|
||||
:operations rops
|
||||
:id id}
|
||||
uchg {:type :mod-obj
|
||||
:page-id page-id
|
||||
:operations uops
|
||||
:id id}]
|
||||
(recur sids
|
||||
(next cids)
|
||||
(conj rchanges rchg)
|
||||
(conj uchanges uchg))))))]
|
||||
(ptk/reify ::update-shapes-recursive
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (lookup-page-objects state page-id)
|
||||
[rchanges uchanges] (impl-gen-changes objects page-id (seq ids))]
|
||||
(rx/of (commit-changes rchanges uchanges {:commit-local? true})))))))
|
||||
|
||||
|
||||
(defn select-shapes
|
||||
[ids]
|
||||
|
@ -639,7 +318,7 @@
|
|||
(assoc :name name)))]
|
||||
|
||||
(rx/concat
|
||||
(rx/of (commit-changes rchanges uchanges {:commit-local? true})
|
||||
(rx/of (dch/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(select-shapes (d/ordered-set id)))
|
||||
(when (= :text (:type attrs))
|
||||
(->> (rx/of (start-edition-mode id))
|
||||
|
@ -672,7 +351,7 @@
|
|||
:page-id page-id
|
||||
:index index
|
||||
:shapes [shape-id]})))]
|
||||
(rx/of (commit-changes rchanges uchanges {:commit-local? true}))))))
|
||||
(rx/of (dch/commit-changes rchanges uchanges {:commit-local? true}))))))
|
||||
|
||||
|
||||
(defn delete-shapes
|
||||
|
@ -779,7 +458,7 @@
|
|||
;; (cljs.pprint/pprint rchanges)
|
||||
;; (println "================ uchanges")
|
||||
;; (cljs.pprint/pprint uchanges)
|
||||
(rx/of (commit-changes rchanges uchanges {:commit-local? true}))))))
|
||||
(rx/of (dch/commit-changes rchanges uchanges {:commit-local? true}))))))
|
||||
|
||||
|
||||
;; --- Add shape to Workspace
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
[app.common.geom.shapes :as gsh]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.streams :as ms]
|
||||
[app.main.worker :as uw]))
|
||||
|
||||
|
@ -54,7 +55,7 @@
|
|||
;; Add & select the created shape to the workspace
|
||||
(rx/concat
|
||||
(if (= :text (:type shape))
|
||||
(rx/of (dwc/start-undo-transaction))
|
||||
(rx/of (dwu/start-undo-transaction))
|
||||
(rx/empty))
|
||||
|
||||
(rx/of (dwc/add-shape shape))
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
[potok.core :as ptk]
|
||||
[app.common.data :as d]
|
||||
[app.common.spec :as us]
|
||||
[app.main.data.workspace.common :as dwc]))
|
||||
[app.main.data.workspace.changes :as dch]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Grid
|
||||
|
@ -48,7 +48,7 @@
|
|||
grid {:type :square
|
||||
:params params
|
||||
:display true}]
|
||||
(rx/of (dwc/update-shapes [frame-id]
|
||||
(rx/of (dch/update-shapes [frame-id]
|
||||
(fn [obj] (update obj :grids (fnil #(conj % grid) [])))))))))
|
||||
|
||||
|
||||
|
@ -57,14 +57,14 @@
|
|||
(ptk/reify ::set-frame-grid
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(rx/of (dwc/update-shapes [frame-id] (fn [o] (update o :grids (fnil #(d/remove-at-index % index) []))))))))
|
||||
(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]
|
||||
(rx/of (dwc/update-shapes [frame-id] #(assoc-in % [:grids index] data))))))
|
||||
(rx/of (dch/update-shapes [frame-id] #(assoc-in % [:grids index] data))))))
|
||||
|
||||
(defn set-default-grid
|
||||
[type params]
|
||||
|
@ -73,7 +73,7 @@
|
|||
(watch [_ state stream]
|
||||
(let [pid (:current-page-id state)
|
||||
prev-value (get-in state [:workspace-data :pages-index pid :options :saved-grids type])]
|
||||
(rx/of (dwc/commit-changes [{:type :set-option
|
||||
(rx/of (dch/commit-changes [{:type :set-option
|
||||
:page-id pid
|
||||
:option [:saved-grids type]
|
||||
:value params}]
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.pages :as cp]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[beicon.core :as rx]
|
||||
[potok.core :as ptk]))
|
||||
|
@ -106,7 +107,7 @@
|
|||
shapes (shapes-for-grouping objects selected)]
|
||||
(when-not (empty? shapes)
|
||||
(let [[group rchanges uchanges] (prepare-create-group page-id shapes "Group-" false)]
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(rx/of (dch/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(dwc/select-shapes (d/ordered-set (:id group))))))))))
|
||||
|
||||
(def ungroup-selected
|
||||
|
@ -122,7 +123,7 @@
|
|||
(= (:type group) :group))
|
||||
(let [[rchanges uchanges]
|
||||
(prepare-remove-group page-id group objects)]
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))))))))
|
||||
(rx/of (dch/commit-changes rchanges uchanges {:commit-local? true}))))))))
|
||||
|
||||
(def mask-group
|
||||
(ptk/reify ::mask-group
|
||||
|
@ -176,7 +177,7 @@
|
|||
:page-id page-id
|
||||
:shapes [(:id group)]})]
|
||||
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(rx/of (dch/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(dwc/select-shapes (d/ordered-set (:id group))))))))))
|
||||
|
||||
(def unmask-group
|
||||
|
@ -209,7 +210,7 @@
|
|||
:page-id page-id
|
||||
:shapes [(:id group)]}]]
|
||||
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(rx/of (dch/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(dwc/select-shapes (d/ordered-set (:id group))))))))))
|
||||
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
[app.common.geom.shapes :as geom]
|
||||
[app.main.data.messages :as dm]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.libraries-helpers :as dwlh]
|
||||
[app.common.pages :as cp]
|
||||
[app.main.repo :as rp]
|
||||
|
@ -90,7 +91,7 @@
|
|||
uchg {:type :del-color
|
||||
:id id}]
|
||||
(rx/of #(assoc-in % [:workspace-local :color-for-rename] id)
|
||||
(dwc/commit-changes [rchg] [uchg] {:commit-local? true})))))))
|
||||
(dch/commit-changes [rchg] [uchg] {:commit-local? true})))))))
|
||||
|
||||
(defn add-recent-color
|
||||
[color]
|
||||
|
@ -100,7 +101,7 @@
|
|||
(watch [_ state s]
|
||||
(let [rchg {:type :add-recent-color
|
||||
:color color}]
|
||||
(rx/of (dwc/commit-changes [rchg] [] {:commit-local? true}))))))
|
||||
(rx/of (dch/commit-changes [rchg] [] {:commit-local? true}))))))
|
||||
|
||||
(def clear-color-for-rename
|
||||
(ptk/reify ::clear-color-for-rename
|
||||
|
@ -120,7 +121,7 @@
|
|||
:color color}
|
||||
uchg {:type :mod-color
|
||||
:color prev}]
|
||||
(rx/of (dwc/commit-changes [rchg] [uchg] {:commit-local? true})
|
||||
(rx/of (dch/commit-changes [rchg] [uchg] {:commit-local? true})
|
||||
(sync-file (:current-file-id state) file-id))))))
|
||||
|
||||
(defn delete-color
|
||||
|
@ -134,7 +135,7 @@
|
|||
:id id}
|
||||
uchg {:type :add-color
|
||||
:color prev}]
|
||||
(rx/of (dwc/commit-changes [rchg] [uchg] {:commit-local? true}))))))
|
||||
(rx/of (dch/commit-changes [rchg] [uchg] {:commit-local? true}))))))
|
||||
|
||||
(defn add-media
|
||||
[{:keys [id] :as media}]
|
||||
|
@ -147,7 +148,7 @@
|
|||
:object obj}
|
||||
uchg {:type :del-media
|
||||
:id id}]
|
||||
(rx/of (dwc/commit-changes [rchg] [uchg] {:commit-local? true}))))))
|
||||
(rx/of (dch/commit-changes [rchg] [uchg] {:commit-local? true}))))))
|
||||
|
||||
(defn rename-media
|
||||
[id new-name]
|
||||
|
@ -169,7 +170,7 @@
|
|||
:name (:name object)
|
||||
:path (:path object)}}]]
|
||||
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))))))
|
||||
(rx/of (dch/commit-changes rchanges uchanges {:commit-local? true}))))))
|
||||
|
||||
(defn delete-media
|
||||
[{:keys [id] :as params}]
|
||||
|
@ -182,7 +183,7 @@
|
|||
:id id}
|
||||
uchg {:type :add-media
|
||||
:object prev}]
|
||||
(rx/of (dwc/commit-changes [rchg] [uchg] {:commit-local? true}))))))
|
||||
(rx/of (dch/commit-changes [rchg] [uchg] {:commit-local? true}))))))
|
||||
|
||||
(defn add-typography
|
||||
([typography] (add-typography typography true))
|
||||
|
@ -196,7 +197,7 @@
|
|||
:typography typography}
|
||||
uchg {:type :del-typography
|
||||
:id (:id typography)}]
|
||||
(rx/of (dwc/commit-changes [rchg] [uchg] {:commit-local? true})
|
||||
(rx/of (dch/commit-changes [rchg] [uchg] {:commit-local? true})
|
||||
#(cond-> %
|
||||
edit?
|
||||
(assoc-in [:workspace-local :rename-typography] (:id typography))))))))))
|
||||
|
@ -213,7 +214,7 @@
|
|||
:typography typography}
|
||||
uchg {:type :mod-typography
|
||||
:typography prev}]
|
||||
(rx/of (dwc/commit-changes [rchg] [uchg] {:commit-local? true})
|
||||
(rx/of (dch/commit-changes [rchg] [uchg] {:commit-local? true})
|
||||
(sync-file (:current-file-id state) file-id))))))
|
||||
|
||||
(defn delete-typography
|
||||
|
@ -227,7 +228,7 @@
|
|||
:id id}
|
||||
uchg {:type :add-typography
|
||||
:typography prev}]
|
||||
(rx/of (dwc/commit-changes [rchg] [uchg] {:commit-local? true}))))))
|
||||
(rx/of (dch/commit-changes [rchg] [uchg] {:commit-local? true}))))))
|
||||
|
||||
(def add-component
|
||||
"Add a new component to current file library, from the currently selected shapes."
|
||||
|
@ -242,7 +243,7 @@
|
|||
(let [[group rchanges uchanges]
|
||||
(dwlh/generate-add-component selected objects page-id file-id)]
|
||||
(when-not (empty? rchanges)
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(rx/of (dch/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(dwc/select-shapes (d/ordered-set (:id group))))))))))
|
||||
|
||||
(defn rename-component
|
||||
|
@ -273,7 +274,7 @@
|
|||
:path (:path component)
|
||||
:objects objects}]]
|
||||
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))))))
|
||||
(rx/of (dch/commit-changes rchanges uchanges {:commit-local? true}))))))
|
||||
|
||||
(defn duplicate-component
|
||||
"Create a new component copied from the one with the given id."
|
||||
|
@ -301,7 +302,7 @@
|
|||
uchanges [{:type :del-component
|
||||
:id (:id new-shape)}]]
|
||||
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))))))
|
||||
(rx/of (dch/commit-changes rchanges uchanges {:commit-local? true}))))))
|
||||
|
||||
(defn delete-component
|
||||
"Delete the component with the given id, from the current file library."
|
||||
|
@ -321,7 +322,7 @@
|
|||
:path (:path component)
|
||||
:shapes (vals (:objects component))}]]
|
||||
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))))))
|
||||
(rx/of (dch/commit-changes rchanges uchanges {:commit-local? true}))))))
|
||||
|
||||
(defn instantiate-component
|
||||
"Create a new shape in the current page, from the component with the given id
|
||||
|
@ -398,7 +399,7 @@
|
|||
:ignore-touched true})
|
||||
new-shapes)]
|
||||
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(rx/of (dch/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(dwc/select-shapes (d/ordered-set (:id new-shape))))))))
|
||||
|
||||
(defn detach-component
|
||||
|
@ -461,7 +462,7 @@
|
|||
:val (:touched obj)}]})
|
||||
shapes)]
|
||||
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))))))
|
||||
(rx/of (dch/commit-changes rchanges uchanges {:commit-local? true}))))))
|
||||
|
||||
(defn nav-to-component-file
|
||||
[file-id]
|
||||
|
@ -514,7 +515,7 @@
|
|||
rchanges
|
||||
local-library))
|
||||
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))))))
|
||||
(rx/of (dch/commit-changes rchanges uchanges {:commit-local? true}))))))
|
||||
|
||||
(defn update-component
|
||||
"Modify the component linked to the shape with the given id, in the
|
||||
|
@ -569,11 +570,11 @@
|
|||
file))
|
||||
|
||||
(rx/of (when (seq local-rchanges)
|
||||
(dwc/commit-changes local-rchanges local-uchanges
|
||||
(dch/commit-changes local-rchanges local-uchanges
|
||||
{:commit-local? true
|
||||
:file-id (:id local-library)}))
|
||||
(when (seq rchanges)
|
||||
(dwc/commit-changes rchanges uchanges
|
||||
(dch/commit-changes rchanges uchanges
|
||||
{:commit-local? true
|
||||
:file-id file-id})))))))
|
||||
|
||||
|
@ -623,7 +624,7 @@
|
|||
(rx/concat
|
||||
(rx/of (dm/hide-tag :sync-dialog))
|
||||
(when rchanges
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true
|
||||
(rx/of (dch/commit-changes rchanges uchanges {:commit-local? true
|
||||
:file-id file-id})))
|
||||
(when (not= file-id library-id)
|
||||
;; When we have just updated the library file, give some time for the
|
||||
|
@ -666,7 +667,7 @@
|
|||
(log/debug :msg "SYNC-FILE (2nd stage) finished" :js/rchanges (log-changes
|
||||
rchanges
|
||||
file))
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true
|
||||
(rx/of (dch/commit-changes rchanges uchanges {:commit-local? true
|
||||
:file-id file-id})))))))
|
||||
|
||||
(def ignore-sync
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
(ns app.main.data.workspace.path.changes
|
||||
(:require
|
||||
[app.common.spec :as us]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.path.helpers :as helpers]
|
||||
[app.main.data.workspace.path.spec :as spec]
|
||||
[app.main.data.workspace.path.state :as st]
|
||||
|
@ -67,7 +67,7 @@
|
|||
(let [shape (get-in state (st/get-path state))
|
||||
page-id (:current-page-id state)
|
||||
[rch uch] (generate-path-changes page-id shape old-content (:content shape))]
|
||||
(rx/of (dwc/commit-changes rch uch {:commit-local? true})))
|
||||
(rx/of (dch/commit-changes rch uch {:commit-local? true})))
|
||||
(rx/empty)))))))
|
||||
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.math :as mth]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.path.changes :as changes]
|
||||
[app.main.data.workspace.path.common :as common]
|
||||
[app.main.data.workspace.path.helpers :as helpers]
|
||||
|
@ -60,7 +60,7 @@
|
|||
|
||||
[rch uch] (changes/generate-path-changes page-id shape (:content shape) new-content)]
|
||||
|
||||
(rx/of (dwc/commit-changes rch uch {:commit-local? true})
|
||||
(rx/of (dch/commit-changes rch uch {:commit-local? true})
|
||||
(selection/update-selection point-change)
|
||||
(fn [state] (update-in state [:workspace-local :edit-path id] dissoc :content-modifiers :moving-nodes :moving-handler)))))))
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
(ns app.main.data.workspace.path.tools
|
||||
(:require
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.path.changes :as changes]
|
||||
[app.main.data.workspace.path.common :as common]
|
||||
[app.main.data.workspace.path.state :as st]
|
||||
|
@ -32,7 +32,7 @@
|
|||
new-content (-> (tool-fn (:content shape) points)
|
||||
(ups/close-subpaths))
|
||||
[rch uch] (changes/generate-path-changes page-id shape (:content shape) new-content)]
|
||||
(rx/of (dwc/commit-changes rch uch {:commit-local? true})))))))
|
||||
(rx/of (dch/commit-changes rch uch {:commit-local? true})))))))
|
||||
|
||||
(defn make-corner
|
||||
([]
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
[app.main.data.media :as di]
|
||||
[app.main.data.messages :as dm]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.svg-upload :as svg]
|
||||
|
@ -51,7 +52,7 @@
|
|||
(let [stoper (rx/filter #(= ::finalize %) stream)
|
||||
forcer (rx/filter #(= ::force-persist %) stream)
|
||||
notifier (->> stream
|
||||
(rx/filter (ptk/type? ::dwc/commit-changes))
|
||||
(rx/filter dch/commit-changes?)
|
||||
(rx/debounce 2000)
|
||||
(rx/merge stoper forcer))
|
||||
|
||||
|
@ -79,7 +80,7 @@
|
|||
(st/emit! (update-persistence-status {:status :saved})))]
|
||||
(->> (rx/merge
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::dwc/commit-changes))
|
||||
(rx/filter dch/commit-changes?)
|
||||
(rx/map deref)
|
||||
(rx/filter local-file?)
|
||||
(rx/tap on-dirty)
|
||||
|
@ -91,7 +92,7 @@
|
|||
(rx/tap on-saving)
|
||||
(rx/take-until (rx/delay 100 stoper)))
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::dwc/commit-changes))
|
||||
(rx/filter dch/commit-changes?)
|
||||
(rx/map deref)
|
||||
(rx/filter library-file?)
|
||||
(rx/filter (complement #(empty? (:changes %))))
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
[app.common.spec :as us]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.modal :as md]
|
||||
[app.main.streams :as ms]
|
||||
[app.main.worker :as uw]))
|
||||
|
@ -395,7 +396,7 @@
|
|||
(map #(get-in % [:obj :id]))
|
||||
(into (d/ordered-set)))]
|
||||
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(rx/of (dch/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(select-shapes selected))))))
|
||||
|
||||
(defn change-hover-state
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.colors :as mdc]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.data.workspace.drawing :as dwd]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.texts :as dwtxt]
|
||||
|
@ -123,7 +124,7 @@
|
|||
|
||||
:clear-undo {:tooltip (ds/meta "Q")
|
||||
:command (ds/c-mod "q")
|
||||
:fn #(st/emit! dwc/reinitialize-undo)}
|
||||
:fn #(st/emit! dwu/reinitialize-undo)}
|
||||
|
||||
:draw-frame {:tooltip "A"
|
||||
:command "a"
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
[app.common.pages :as cp]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.repo :as rp]
|
||||
[app.util.color :as uc]
|
||||
[app.util.path.parser :as upp]
|
||||
|
@ -462,7 +463,7 @@
|
|||
|
||||
rchanges (conj rchanges reg-objects-action)]
|
||||
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(rx/of (dch/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(dwc/select-shapes (d/ordered-set root-id))))
|
||||
|
||||
(catch :default e
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.transforms :as dwt]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.fonts :as fonts]
|
||||
[app.util.object :as obj]
|
||||
[app.util.text-editor :as ted]
|
||||
|
@ -77,8 +79,8 @@
|
|||
(when (and (not= content (:content shape))
|
||||
(some? (:current-page-id state)))
|
||||
(rx/of
|
||||
(dwc/update-shapes [id] #(assoc % :content content))
|
||||
(dwc/commit-undo-transaction)))))
|
||||
(dch/update-shapes [id] #(assoc % :content content))
|
||||
(dwu/commit-undo-transaction)))))
|
||||
(rx/of (dws/deselect-shape id)
|
||||
(dwc/delete-shapes [id])))))))
|
||||
|
||||
|
@ -141,7 +143,7 @@
|
|||
shape-ids (cond (= (:type shape) :text) [id]
|
||||
(= (:type shape) :group) (cp/get-children id objects))]
|
||||
|
||||
(rx/of (dwc/update-shapes shape-ids update-fn))))))
|
||||
(rx/of (dch/update-shapes shape-ids update-fn))))))
|
||||
|
||||
(defn update-paragraph-attrs
|
||||
[{:keys [id attrs]}]
|
||||
|
@ -169,7 +171,7 @@
|
|||
shape-ids (cond (= (:type shape) :text) [id]
|
||||
(= (:type shape) :group) (cp/get-children id objects))]
|
||||
|
||||
(rx/of (dwc/update-shapes shape-ids update-fn))))))))
|
||||
(rx/of (dch/update-shapes shape-ids update-fn))))))))
|
||||
|
||||
(defn update-text-attrs
|
||||
[{:keys [id attrs]}]
|
||||
|
@ -187,7 +189,7 @@
|
|||
update-fn #(update-shape % txt/is-text-node? attrs/merge attrs)
|
||||
shape-ids (cond (= (:type shape) :text) [id]
|
||||
(= (:type shape) :group) (cp/get-children id objects))]
|
||||
(rx/of (dwc/update-shapes shape-ids update-fn)))))))
|
||||
(rx/of (dch/update-shapes shape-ids update-fn)))))))
|
||||
|
||||
;; --- RESIZE UTILS
|
||||
|
||||
|
|
|
@ -14,7 +14,9 @@
|
|||
[app.common.pages :as cp]
|
||||
[app.common.spec :as us]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.snap :as snap]
|
||||
[app.main.store :as st]
|
||||
|
@ -140,7 +142,7 @@
|
|||
(filter #(= :text (:type %)))
|
||||
(map :id))]
|
||||
(rx/concat
|
||||
(rx/of (dwc/update-shapes text-shapes-ids #(assoc % :grow-type :fixed)))
|
||||
(rx/of (dch/update-shapes text-shapes-ids #(assoc % :grow-type :fixed)))
|
||||
(->> ms/mouse-position
|
||||
(rx/with-latest vector ms/mouse-position-shift)
|
||||
(rx/map normalize-proportion-lock)
|
||||
|
@ -259,9 +261,9 @@
|
|||
:shapes [(:id shape)]})))]
|
||||
|
||||
(when-not (empty? rch)
|
||||
(rx/of dwc/pop-undo-into-transaction
|
||||
(dwc/commit-changes rch uch {:commit-local? true})
|
||||
(dwc/commit-undo-transaction)
|
||||
(rx/of dwu/pop-undo-into-transaction
|
||||
(dch/commit-changes rch uch {:commit-local? true})
|
||||
(dwu/commit-undo-transaction)
|
||||
(dwc/expand-collapse frame-id)))))))
|
||||
|
||||
(defn start-move
|
||||
|
|
134
frontend/src/app/main/data/workspace/undo.cljs
Normal file
134
frontend/src/app/main/data/workspace/undo.cljs
Normal file
|
@ -0,0 +1,134 @@
|
|||
;; 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.undo
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.proportions :as gpr]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.pages.spec :as spec]
|
||||
[app.common.spec :as us]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.worker :as uw]
|
||||
[app.main.streams :as ms]
|
||||
[app.util.logging :as log]
|
||||
[app.util.timers :as ts]
|
||||
[beicon.core :as rx]
|
||||
[cljs.spec.alpha :as s]
|
||||
[clojure.set :as set]
|
||||
[cuerdas.core :as str]
|
||||
[potok.core :as ptk]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Undo / Redo
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(s/def ::undo-changes ::cp/changes)
|
||||
(s/def ::redo-changes ::cp/changes)
|
||||
(s/def ::undo-entry
|
||||
(s/keys :req-un [::undo-changes ::redo-changes]))
|
||||
|
||||
(def MAX-UNDO-SIZE 50)
|
||||
|
||||
(defn- conj-undo-entry
|
||||
[undo data]
|
||||
(let [undo (conj undo data)
|
||||
cnt (count undo)]
|
||||
(if (> cnt MAX-UNDO-SIZE)
|
||||
(subvec undo (- cnt MAX-UNDO-SIZE))
|
||||
undo)))
|
||||
|
||||
(defn- materialize-undo
|
||||
[changes index]
|
||||
(ptk/reify ::materialize-undo
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(update :workspace-data cp/process-changes changes)
|
||||
(assoc-in [:workspace-undo :index] index)))))
|
||||
|
||||
(defn- reset-undo
|
||||
[index]
|
||||
(ptk/reify ::reset-undo
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(update :workspace-undo dissoc :undo-index)
|
||||
(update-in [:workspace-undo :items] (fn [queue] (into [] (take (inc index) queue))))))))
|
||||
|
||||
(defn- add-undo-entry
|
||||
[state entry]
|
||||
(if (and entry
|
||||
(not-empty (:undo-changes entry))
|
||||
(not-empty (:redo-changes entry)))
|
||||
(let [index (get-in state [:workspace-undo :index] -1)
|
||||
items (get-in state [:workspace-undo :items] [])
|
||||
items (->> items (take (inc index)) (into []))
|
||||
items (conj-undo-entry items entry)]
|
||||
(-> state
|
||||
(update :workspace-undo assoc :items items
|
||||
:index (min (inc index)
|
||||
(dec MAX-UNDO-SIZE)))))
|
||||
state))
|
||||
|
||||
(defn- accumulate-undo-entry
|
||||
[state {:keys [undo-changes redo-changes]}]
|
||||
(-> state
|
||||
(update-in [:workspace-undo :transaction :undo-changes] #(into undo-changes %))
|
||||
(update-in [:workspace-undo :transaction :redo-changes] #(into % redo-changes))))
|
||||
|
||||
(defn- append-undo
|
||||
[entry]
|
||||
(us/verify ::undo-entry entry)
|
||||
(ptk/reify ::append-undo
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(if (get-in state [:workspace-undo :transaction])
|
||||
(accumulate-undo-entry state entry)
|
||||
(add-undo-entry state entry)))))
|
||||
|
||||
(defonce empty-tx {:undo-changes [] :redo-changes []})
|
||||
|
||||
(defn start-undo-transaction []
|
||||
(ptk/reify ::start-undo-transaction
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
;; We commit the old transaction before starting the new one
|
||||
(let [current-tx (get-in state [:workspace-undo :transaction])]
|
||||
(cond-> state
|
||||
(nil? current-tx) (assoc-in [:workspace-undo :transaction] empty-tx))))))
|
||||
|
||||
(defn discard-undo-transaction []
|
||||
(ptk/reify ::discard-undo-transaction
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :workspace-undo dissoc :transaction))))
|
||||
|
||||
(defn commit-undo-transaction []
|
||||
(ptk/reify ::commit-undo-transaction
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(add-undo-entry (get-in state [:workspace-undo :transaction]))
|
||||
(update :workspace-undo dissoc :transaction)))))
|
||||
|
||||
(def pop-undo-into-transaction
|
||||
(ptk/reify ::last-undo-into-transaction
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [index (get-in state [:workspace-undo :index] -1)]
|
||||
|
||||
(cond-> state
|
||||
(>= index 0) (accumulate-undo-entry (get-in state [:workspace-undo :items index]))
|
||||
(>= index 0) (update-in [:workspace-undo :index] dec))))))
|
||||
|
||||
(def reinitialize-undo
|
||||
(ptk/reify ::reset-undo
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc state :workspace-undo {}))))
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.shortcuts :as sc]
|
||||
[app.main.refs :as refs]
|
||||
|
@ -83,10 +84,10 @@
|
|||
;; We defer the execution so the mouse event won't close the editor
|
||||
(timers/schedule #(st/emit! (dw/start-editing-selected))))
|
||||
do-update-component (st/emitf
|
||||
(dwc/start-undo-transaction)
|
||||
(dwu/start-undo-transaction)
|
||||
(dwl/update-component id)
|
||||
(dwl/sync-file current-file-id (:component-file shape))
|
||||
(dwc/commit-undo-transaction))
|
||||
(dwu/commit-undo-transaction))
|
||||
confirm-update-remote-component (st/emitf
|
||||
(dwl/update-component id)
|
||||
(dwl/sync-file current-file-id
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.texts :as dwt]
|
||||
[app.main.exports :as exports]
|
||||
|
@ -142,9 +143,9 @@
|
|||
(if (empty? selected-components)
|
||||
(st/emit! (dwl/duplicate-component {:id (:component-id @state)}))
|
||||
(do
|
||||
(st/emit! (dwc/start-undo-transaction))
|
||||
(st/emit! (dwu/start-undo-transaction))
|
||||
(apply st/emit! (map #(dwl/duplicate-component {:id %}) selected-components))
|
||||
(st/emit! (dwc/commit-undo-transaction))))))
|
||||
(st/emit! (dwu/commit-undo-transaction))))))
|
||||
|
||||
on-delete
|
||||
(mf/use-callback
|
||||
|
@ -195,7 +196,7 @@
|
|||
(mf/deps components selected-components on-clear-selection)
|
||||
(fn [name]
|
||||
(on-clear-selection)
|
||||
(st/emit! (dwc/start-undo-transaction))
|
||||
(st/emit! (dwu/start-undo-transaction))
|
||||
(apply st/emit!
|
||||
(->> components
|
||||
(filter #(contains? selected-components (:id %)))
|
||||
|
@ -203,7 +204,7 @@
|
|||
(:id %)
|
||||
(str name " / "
|
||||
(cp/merge-path-item (:path %) (:name %)))))))
|
||||
(st/emit! (dwc/commit-undo-transaction))))
|
||||
(st/emit! (dwu/commit-undo-transaction))))
|
||||
|
||||
on-fold-group
|
||||
(mf/use-callback
|
||||
|
@ -383,7 +384,7 @@
|
|||
(mf/deps objects selected-objects on-clear-selection)
|
||||
(fn [name]
|
||||
(on-clear-selection)
|
||||
(st/emit! (dwc/start-undo-transaction))
|
||||
(st/emit! (dwu/start-undo-transaction))
|
||||
(apply st/emit!
|
||||
(->> objects
|
||||
(filter #(contains? selected-objects (:id %)))
|
||||
|
@ -391,7 +392,7 @@
|
|||
(:id %)
|
||||
(str name " / "
|
||||
(cp/merge-path-item (:path %) (:name %)))))))
|
||||
(st/emit! (dwc/commit-undo-transaction))))
|
||||
(st/emit! (dwu/commit-undo-transaction))))
|
||||
|
||||
on-fold-group
|
||||
(mf/use-callback
|
||||
|
@ -975,7 +976,7 @@
|
|||
(mf/deps @selected-assets)
|
||||
(fn []
|
||||
(do
|
||||
(st/emit! (dwc/start-undo-transaction))
|
||||
(st/emit! (dwu/start-undo-transaction))
|
||||
(apply st/emit! (map #(dwl/delete-component {:id %})
|
||||
(:components @selected-assets)))
|
||||
(apply st/emit! (map #(dwl/delete-media {:id %})
|
||||
|
@ -984,7 +985,7 @@
|
|||
(:colors @selected-assets)))
|
||||
(apply st/emit! (map #(dwl/delete-typography %)
|
||||
(:typographies @selected-assets)))
|
||||
(st/emit! (dwc/commit-undo-transaction)))))]
|
||||
(st/emit! (dwu/commit-undo-transaction)))))]
|
||||
|
||||
[:div.tool-window {:on-context-menu #(dom/prevent-default %)
|
||||
:on-click unselect-all}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.options.common :refer [advanced-options]]
|
||||
|
@ -32,7 +33,7 @@
|
|||
has-value? (not (nil? blur))
|
||||
multiple? (= blur :multiple)
|
||||
|
||||
change! (fn [update-fn] (st/emit! (dwc/update-shapes ids update-fn)))
|
||||
change! (fn [update-fn] (st/emit! (dch/update-shapes ids update-fn)))
|
||||
|
||||
handle-add
|
||||
(fn []
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
[app.main.ui.components.context-menu :refer [context-menu]]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.util.i18n :as i18n :refer [t]]
|
||||
[app.util.dom :as dom]))
|
||||
|
@ -50,10 +51,10 @@
|
|||
do-detach-component (st/emitf (dwl/detach-component id))
|
||||
do-reset-component (st/emitf (dwl/reset-component id))
|
||||
do-update-component (st/emitf
|
||||
(dwc/start-undo-transaction)
|
||||
(dwu/start-undo-transaction)
|
||||
(dwl/update-component id)
|
||||
(dwl/sync-file current-file-id current-file-id)
|
||||
(dwc/commit-undo-transaction))
|
||||
(dwu/commit-undo-transaction))
|
||||
confirm-update-remote-component (st/emitf
|
||||
(dwl/update-component id)
|
||||
(dwl/sync-file current-file-id
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
[app.common.pages :as cp]
|
||||
[app.main.data.workspace.colors :as dc]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.data.workspace.texts :as dwt]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
|
@ -78,13 +79,13 @@
|
|||
(mf/use-callback
|
||||
(mf/deps ids)
|
||||
(fn [value opacity id file-id]
|
||||
(st/emit! (dwc/start-undo-transaction))))
|
||||
(st/emit! (dwu/start-undo-transaction))))
|
||||
|
||||
on-close-picker
|
||||
(mf/use-callback
|
||||
(mf/deps ids)
|
||||
(fn [value opacity id file-id]
|
||||
(st/emit! (dwc/commit-undo-transaction))))]
|
||||
(st/emit! (dwu/commit-undo-transaction))))]
|
||||
|
||||
(if show?
|
||||
[:div.element-set
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.math :as mth]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.numeric-input :refer [numeric-input]]
|
||||
[app.main.ui.icons :as i]
|
||||
|
@ -34,7 +35,7 @@
|
|||
(mf/use-callback
|
||||
(mf/deps ids)
|
||||
(fn [prop value]
|
||||
(st/emit! (dwc/update-shapes ids #(assoc % prop value)))))
|
||||
(st/emit! (dch/update-shapes ids #(assoc % prop value)))))
|
||||
|
||||
handle-change-blend-mode
|
||||
(mf/use-callback
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
[app.common.geom.point :as gpt]
|
||||
[app.main.data.workspace :as udw]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.ui.components.numeric-input :refer [numeric-input]]
|
||||
[app.common.math :as math]
|
||||
[app.util.i18n :refer [t] :as i18n]))
|
||||
|
@ -106,7 +107,7 @@
|
|||
(:r1 shape)
|
||||
(-> (assoc :rx 0 :ry 0)
|
||||
(dissoc :r1 :r2 :r3 :r4))))]
|
||||
(st/emit! (dwc/update-shapes ids-with-children radius-update)))))
|
||||
(st/emit! (dch/update-shapes ids-with-children radius-update)))))
|
||||
|
||||
on-switch-to-radius-4
|
||||
(mf/use-callback
|
||||
|
@ -118,7 +119,7 @@
|
|||
(:rx shape)
|
||||
(-> (assoc :r1 0 :r2 0 :r3 0 :r4 0)
|
||||
(dissoc :rx :ry))))]
|
||||
(st/emit! (dwc/update-shapes ids-with-children radius-update)))))
|
||||
(st/emit! (dch/update-shapes ids-with-children radius-update)))))
|
||||
|
||||
on-radius-1-change
|
||||
(mf/use-callback
|
||||
|
@ -134,7 +135,7 @@
|
|||
(or (:rx shape) (:r1 shape))
|
||||
(assoc :rx value :ry value)))]
|
||||
|
||||
(st/emit! (dwc/update-shapes ids-with-children radius-update)))))
|
||||
(st/emit! (dch/update-shapes ids-with-children radius-update)))))
|
||||
|
||||
on-radius-4-change
|
||||
(mf/use-callback
|
||||
|
@ -150,7 +151,7 @@
|
|||
(attr shape)
|
||||
(assoc attr value)))]
|
||||
|
||||
(st/emit! (dwc/update-shapes ids-with-children radius-update)))))
|
||||
(st/emit! (dch/update-shapes ids-with-children radius-update)))))
|
||||
|
||||
on-width-change #(on-size-change % :width)
|
||||
on-height-change #(on-size-change % :height)
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.components.numeric-input :refer [numeric-input]]
|
||||
|
@ -56,7 +58,7 @@
|
|||
on-remove-shadow
|
||||
(fn [index]
|
||||
(fn []
|
||||
(st/emit! (dwc/update-shapes ids #(update % :shadow remove-shadow-by-index index) ))))
|
||||
(st/emit! (dch/update-shapes ids #(update % :shadow remove-shadow-by-index index) ))))
|
||||
|
||||
select-text
|
||||
(fn [ref] (fn [event] (dom/select-text! (mf/ref-val ref))))
|
||||
|
@ -69,14 +71,14 @@
|
|||
([index attr valid? update-ref]
|
||||
(fn [value]
|
||||
(when (or (not valid?) (valid? value))
|
||||
(do (st/emit! (dwc/update-shapes ids #(assoc-in % [:shadow index attr] value)))
|
||||
(do (st/emit! (dch/update-shapes ids #(assoc-in % [:shadow index attr] value)))
|
||||
(when update-ref (dom/set-value! (mf/ref-val update-ref) value)))))))
|
||||
|
||||
update-color
|
||||
(fn [index]
|
||||
(fn [color opacity]
|
||||
(let [color (d/without-keys color [:id :file-id :gradient])]
|
||||
(st/emit! (dwc/update-shapes
|
||||
(st/emit! (dch/update-shapes
|
||||
ids
|
||||
#(-> %
|
||||
(assoc-in [:shadow index :color] color)
|
||||
|
@ -86,7 +88,7 @@
|
|||
(fn [index]
|
||||
(fn [color opacity]
|
||||
(if-not (string? (:color value))
|
||||
(st/emit! (dwc/update-shapes
|
||||
(st/emit! (dch/update-shapes
|
||||
ids
|
||||
#(assoc-in % [:shadow index :color]
|
||||
(dissoc (:color value) :id :file-id)))))))
|
||||
|
@ -94,7 +96,7 @@
|
|||
toggle-visibility
|
||||
(fn [index]
|
||||
(fn []
|
||||
(st/emit! (dwc/update-shapes ids #(update-in % [:shadow index :hidden] not)))))]
|
||||
(st/emit! (dch/update-shapes ids #(update-in % [:shadow index :hidden] not)))))]
|
||||
[:*
|
||||
[:div.element-set-options-group
|
||||
|
||||
|
@ -129,7 +131,7 @@
|
|||
{:default-value (str (:style value))
|
||||
:on-change (fn [event]
|
||||
(let [value (-> event dom/get-target dom/get-value d/read-string)]
|
||||
(st/emit! (dwc/update-shapes ids #(assoc-in % [:shadow index :style] value)))))}
|
||||
(st/emit! (dch/update-shapes ids #(assoc-in % [:shadow index :style] value)))))}
|
||||
[:option {:value ":drop-shadow"} (t locale "workspace.options.shadow-options.drop-shadow")]
|
||||
[:option {:value ":inner-shadow"} (t locale "workspace.options.shadow-options.inner-shadow")]]]
|
||||
|
||||
|
@ -181,18 +183,18 @@
|
|||
:disable-gradient true
|
||||
:on-change (update-color index)
|
||||
:on-detach (detach-color index)
|
||||
:on-open #(st/emit! (dwc/start-undo-transaction))
|
||||
:on-close #(st/emit! (dwc/commit-undo-transaction))}]]]]))
|
||||
:on-open #(st/emit! (dwu/start-undo-transaction))
|
||||
:on-close #(st/emit! (dwu/commit-undo-transaction))}]]]]))
|
||||
(mf/defc shadow-menu
|
||||
[{:keys [ids type values] :as props}]
|
||||
(let [locale (i18n/use-locale)
|
||||
on-remove-all-shadows
|
||||
(fn [event]
|
||||
(st/emit! (dwc/update-shapes ids #(dissoc % :shadow) )))
|
||||
(st/emit! (dch/update-shapes ids #(dissoc % :shadow) )))
|
||||
|
||||
on-add-shadow
|
||||
(fn []
|
||||
(st/emit! (dwc/update-shapes ids #(update % :shadow (fnil conj []) (create-shadow)) )))]
|
||||
(st/emit! (dch/update-shapes ids #(update % :shadow (fnil conj []) (create-shadow)) )))]
|
||||
[:div.element-set.shadow-options
|
||||
[:div.element-set-title
|
||||
[:span
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.math :as math]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.colors :as dc]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.icons :as i]
|
||||
|
@ -78,7 +80,7 @@
|
|||
(let [value (-> (dom/get-target event)
|
||||
(dom/get-value)
|
||||
(d/read-string))]
|
||||
(st/emit! (dwc/update-shapes ids #(assoc % :stroke-style value)))))
|
||||
(st/emit! (dch/update-shapes ids #(assoc % :stroke-style value)))))
|
||||
|
||||
on-stroke-alignment-change
|
||||
(fn [event]
|
||||
|
@ -86,7 +88,7 @@
|
|||
(dom/get-value)
|
||||
(d/read-string))]
|
||||
(when-not (str/empty? value)
|
||||
(st/emit! (dwc/update-shapes ids #(assoc % :stroke-alignment value))))))
|
||||
(st/emit! (dch/update-shapes ids #(assoc % :stroke-alignment value))))))
|
||||
|
||||
on-stroke-width-change
|
||||
(fn [event]
|
||||
|
@ -94,11 +96,11 @@
|
|||
(dom/get-value)
|
||||
(d/parse-integer 0))]
|
||||
(when-not (str/empty? value)
|
||||
(st/emit! (dwc/update-shapes ids #(assoc % :stroke-width value))))))
|
||||
(st/emit! (dch/update-shapes ids #(assoc % :stroke-width value))))))
|
||||
|
||||
on-add-stroke
|
||||
(fn [event]
|
||||
(st/emit! (dwc/update-shapes ids #(assoc %
|
||||
(st/emit! (dch/update-shapes ids #(assoc %
|
||||
:stroke-style :solid
|
||||
:stroke-color "#000000"
|
||||
:stroke-opacity 1
|
||||
|
@ -106,19 +108,19 @@
|
|||
|
||||
on-del-stroke
|
||||
(fn [event]
|
||||
(st/emit! (dwc/update-shapes ids #(assoc % :stroke-style :none))))
|
||||
(st/emit! (dch/update-shapes ids #(assoc % :stroke-style :none))))
|
||||
|
||||
on-open-picker
|
||||
(mf/use-callback
|
||||
(mf/deps ids)
|
||||
(fn [value opacity id file-id]
|
||||
(st/emit! (dwc/start-undo-transaction))))
|
||||
(st/emit! (dwu/start-undo-transaction))))
|
||||
|
||||
on-close-picker
|
||||
(mf/use-callback
|
||||
(mf/deps ids)
|
||||
(fn [value opacity id file-id]
|
||||
(st/emit! (dwc/commit-undo-transaction))))]
|
||||
(st/emit! (dwu/commit-undo-transaction))))]
|
||||
|
||||
(if show-options
|
||||
[:div.element-set
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
[cuerdas.core :as str]
|
||||
[app.common.data :as d]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.workspace.sidebar.options.rows.input-row :refer [input-row]]
|
||||
[app.util.dom :as dom]
|
||||
|
@ -61,7 +62,7 @@
|
|||
(fn [attr value]
|
||||
(let [update-fn
|
||||
(fn [shape] (assoc-in shape (concat [:svg-attrs] attr) value))]
|
||||
(st/emit! (dwc/update-shapes ids update-fn)))))
|
||||
(st/emit! (dch/update-shapes ids update-fn)))))
|
||||
|
||||
handle-delete
|
||||
(mf/use-callback
|
||||
|
@ -76,7 +77,7 @@
|
|||
(empty? (get-in shape [:svg-attrs :style]))
|
||||
(update :svg-attrs dissoc :style))]
|
||||
shape))]
|
||||
(st/emit! (dwc/update-shapes ids update-fn)))))
|
||||
(st/emit! (dch/update-shapes ids update-fn)))))
|
||||
|
||||
]
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
[app.common.uuid :as uuid]
|
||||
[app.common.text :as txt]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.texts :as dwt]
|
||||
[app.main.fonts :as fonts]
|
||||
|
@ -159,7 +160,7 @@
|
|||
grow-type (->> values :grow-type)
|
||||
handle-change-grow
|
||||
(fn [event grow-type]
|
||||
(st/emit! (dwc/update-shapes ids #(assoc % :grow-type grow-type))))]
|
||||
(st/emit! (dch/update-shapes ids #(assoc % :grow-type grow-type))))]
|
||||
|
||||
[:div.align-icons
|
||||
[:span.tooltip.tooltip-bottom
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
[app.main.store :as st]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.util.i18n :as i18n :refer [t]]
|
||||
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]))
|
||||
|
||||
|
@ -31,12 +32,12 @@
|
|||
on-open
|
||||
(mf/use-callback
|
||||
(mf/deps page-id)
|
||||
#(st/emit! (dwc/start-undo-transaction)))
|
||||
#(st/emit! (dwu/start-undo-transaction)))
|
||||
|
||||
on-close
|
||||
(mf/use-callback
|
||||
(mf/deps page-id)
|
||||
#(st/emit! (dwc/commit-undo-transaction)))]
|
||||
#(st/emit! (dwu/commit-undo-transaction)))]
|
||||
|
||||
[:div.element-set
|
||||
[:div.element-set-title (t locale "workspace.options.canvas-background")]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue