🎉 Update components leaving touched attrs

This commit is contained in:
Andrés Moya 2020-09-23 14:27:35 +02:00 committed by Andrey Antukh
parent 5e73da4bca
commit 880091a4f7
6 changed files with 167 additions and 86 deletions

View file

@ -213,6 +213,33 @@
:internal.shape/selrect :internal.shape/selrect
:internal.shape/points])) :internal.shape/points]))
(def sync-attrs {:fill-color :fill-group
:fill-color-ref-file :fill-group
:fill-color-ref-id :fill-group
:fill-opacity :fill-group
:content :text-content-group
:font-family :text-font-group
:font-size :text-font-group
:font-style :text-font-group
:font-weight :text-font-group
:letter-spacing :text-display-group
:line-height :text-display-group
:text-align :text-display-group
:stroke-color :stroke-group
:stroke-color-ref-file :stroke-group
:stroke-color-ref-id :stroke-group
:stroke-opacity :stroke-group
:stroke-style :stroke-group
:stroke-width :stroke-group
:stroke-alignment :stroke-group
:width :size-group
:height :size-group
:proportion :size-group
:rx :radius-group
:ry :radius-group
:points :points-group
:transform :transform-group})
(s/def ::minimal-shape (s/def ::minimal-shape
(s/keys :req-un [::type ::name] (s/keys :req-un [::type ::name]
:opt-un [::id])) :opt-un [::id]))
@ -286,11 +313,16 @@
(s/def :internal.operations.set/attr keyword?) (s/def :internal.operations.set/attr keyword?)
(s/def :internal.operations.set/val any?) (s/def :internal.operations.set/val any?)
(s/def :internal.operations.set/touched
(s/nilable (s/every keyword? :kind set?)))
(defmethod operation-spec :set [_] (defmethod operation-spec :set [_]
(s/keys :req-un [:internal.operations.set/attr (s/keys :req-un [:internal.operations.set/attr
:internal.operations.set/val])) :internal.operations.set/val]))
(defmethod operation-spec :set-touched [_]
(s/keys :req-un [:internal.operations.set/touched]))
(defmulti change-spec :type) (defmulti change-spec :type)
(s/def :internal.changes.set-option/option any?) (s/def :internal.changes.set-option/option any?)
@ -795,11 +827,29 @@
(defmethod process-operation :set (defmethod process-operation :set
[shape op] [shape op]
(let [attr (:attr op) (let [attr (:attr op)
val (:val op)] val (:val op)
(if (nil? val) ignore (:ignore-touched op)
(dissoc shape attr) shape-ref (:shape-ref shape)
(assoc shape attr val)))) group (get sync-attrs attr)]
(cond-> shape
(nil? val)
(dissoc attr)
(some? val)
(assoc attr val)
(and shape-ref group (not ignore))
(update :touched #(conj (or % #{}) group)))))
(defmethod process-operation :set-touched
[shape op]
(let [touched (:touched op)
shape-ref (:shape-ref shape)]
(if (or (nil? shape-ref) (nil? touched) (empty? touched))
(dissoc shape :touched)
(assoc shape :touched touched))))
(defmethod process-operation :default (defmethod process-operation :default
[shape op] [shape op]

View file

@ -186,7 +186,7 @@
updated-object (update-original-object object new-object) updated-object (update-original-object object new-object)
updated-objects (if (= object updated-object) updated-objects (if (identical? object updated-object)
updated-children updated-children
(concat [updated-object] updated-children))] (concat [updated-object] updated-children))]

View file

@ -895,7 +895,7 @@
(let [curr (first moved) (let [curr (first moved)
prev (get objects (:id curr)) prev (get objects (:id curr))
ops1 (dwc/generate-operations prev curr) ops1 (dwc/generate-operations prev curr)
ops2 (dwc/generate-operations curr prev)] ops2 (dwc/generate-operations curr prev true)]
(recur (next moved) (recur (next moved)
(conj rchanges {:type :mod-obj (conj rchanges {:type :mod-obj
:page-id page-id :page-id page-id
@ -942,7 +942,7 @@
(let [curr (first moved) (let [curr (first moved)
prev (get objects (:id curr)) prev (get objects (:id curr))
ops1 (dwc/generate-operations prev curr) ops1 (dwc/generate-operations prev curr)
ops2 (dwc/generate-operations curr prev)] ops2 (dwc/generate-operations curr prev true)]
(recur (next moved) (recur (next moved)
(conj rchanges {:type :mod-obj (conj rchanges {:type :mod-obj
:page-id page-id :page-id page-id

View file

@ -86,28 +86,33 @@
(rx/of (append-undo entry)))))))))) (rx/of (append-undo entry))))))))))
(defn generate-operations (defn generate-operations
[ma mb] ([ma mb] (generate-operations ma mb false))
(let [ma-keys (set (keys ma)) ([ma mb undo?]
mb-keys (set (keys mb)) (let [ops (let [ma-keys (set (keys ma))
added (set/difference mb-keys ma-keys) mb-keys (set (keys mb))
removed (set/difference ma-keys mb-keys) added (set/difference mb-keys ma-keys)
both (set/intersection ma-keys mb-keys)] removed (set/difference ma-keys mb-keys)
(d/concat both (set/intersection ma-keys mb-keys)]
(mapv #(array-map :type :set :attr % :val (get mb %)) added) (d/concat
(mapv #(array-map :type :set :attr % :val nil) removed) (mapv #(array-map :type :set :attr % :val (get mb %)) added)
(loop [items (seq both) (mapv #(array-map :type :set :attr % :val nil) removed)
result []] (loop [items (seq both)
(if items result []]
(let [k (first items) (if items
vma (get ma k) (let [k (first items)
vmb (get mb k)] vma (get ma k)
(if (= vma vmb) vmb (get mb k)]
(recur (next items) result) (if (= vma vmb)
(recur (next items) (recur (next items) result)
(conj result {:type :set (recur (next items)
:attr k (conj result {:type :set
:val vmb})))) :attr k
result))))) :val vmb
:ignore-touched undo?}))))
result))))]
(if undo?
(conj ops {:type :set-touched :touched (:touched mb)})
ops))))
(defn generate-changes (defn generate-changes
[page-id objects1 objects2] [page-id objects1 objects2]
@ -415,7 +420,7 @@
obj1 (get objects id) obj1 (get objects id)
obj2 (f obj1) obj2 (f obj1)
rch-operations (generate-operations obj1 obj2) rch-operations (generate-operations obj1 obj2)
uch-operations (generate-operations obj2 obj1) uch-operations (generate-operations obj2 obj1 true)
rchg {:type :mod-obj rchg {:type :mod-obj
:page-id page-id :page-id page-id
:operations rch-operations :operations rch-operations
@ -456,7 +461,7 @@
obj1 (get objects id) obj1 (get objects id)
obj2 (f obj1) obj2 (f obj1)
rops (generate-operations obj1 obj2) rops (generate-operations obj1 obj2)
uops (generate-operations obj2 obj1) uops (generate-operations obj2 obj1 true)
rchg {:type :mod-obj rchg {:type :mod-obj
:page-id page-id :page-id page-id
:operations rops :operations rops

View file

@ -366,7 +366,6 @@
(declare remove-component-and-ref) (declare remove-component-and-ref)
(declare remove-ref) (declare remove-ref)
(declare update-attrs) (declare update-attrs)
(declare sync-attrs)
(declare calc-new-pos) (declare calc-new-pos)
(defn reset-component (defn reset-component
@ -388,7 +387,7 @@
(get-in state [:workspace-libraries file-id :data :components])) (get-in state [:workspace-libraries file-id :data :components]))
[rchanges uchanges] [rchanges uchanges]
(generate-sync-shape-and-children root-shape page components)] (generate-sync-shape-and-children root-shape page components true)]
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})))))) (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))))))
@ -418,18 +417,37 @@
(some? (:shape-ref original-shape)) (some? (:shape-ref original-shape))
(assoc :id (:shape-ref original-shape)))) (assoc :id (:shape-ref original-shape))))
[new-shape new-shapes _] touch-shape (fn [original-shape _]
(cph/clone-object root-shape nil objects update-new-shape) (into {} original-shape))
rchanges [{:type :mod-component [new-shape new-shapes original-shapes]
(cph/clone-object root-shape nil objects update-new-shape touch-shape)
rchanges (concat
[{:type :mod-component
:id component-id :id component-id
:name (:name new-shape) :name (:name new-shape)
:shapes new-shapes}] :shapes new-shapes}]
(map (fn [shape]
{:type :mod-obj
:page-id page-id
:id (:id shape)
:operations [{:type :set-touched
:touched nil}]})
original-shapes))
uchanges [{:type :mod-component uchanges (concat
:id component-id [{:type :mod-component
:name (:name component-obj) :id component-id
:shapes (vals component-objs)}]] :name (:name component-obj)
:shapes (vals component-objs)}]
(map (fn [shape]
{:type :mod-obj
:page-id page-id
:id (:id shape)
:operations [{:type :set-touched
:touched (:touched shape)}]})
original-shapes))]
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})))))) (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))))))
@ -520,13 +538,13 @@
(if (nil? shape) (if (nil? shape)
[rchanges uchanges] [rchanges uchanges]
(let [[shape-rchanges shape-uchanges] (let [[shape-rchanges shape-uchanges]
(generate-sync-shape-and-children shape page components)] (generate-sync-shape-and-children shape page components false)]
(recur (next shapes) (recur (next shapes)
(concat rchanges shape-rchanges) (concat rchanges shape-rchanges)
(concat uchanges shape-uchanges)))))))) (concat uchanges shape-uchanges))))))))
(defn- generate-sync-shape-and-children (defn- generate-sync-shape-and-children
[root-shape page components] [root-shape page components reset-touched?]
(let [objects (get page :objects) (let [objects (get page :objects)
all-shapes (cph/get-object-with-children (:id root-shape) objects) all-shapes (cph/get-object-with-children (:id root-shape) objects)
component (get components (:component-id root-shape)) component (get components (:component-id root-shape))
@ -538,19 +556,24 @@
(if (nil? shape) (if (nil? shape)
[rchanges uchanges] [rchanges uchanges]
(let [[shape-rchanges shape-uchanges] (let [[shape-rchanges shape-uchanges]
(generate-sync-shape shape root-shape root-component page component)] (generate-sync-shape shape root-shape root-component page component reset-touched?)]
(recur (next shapes) (recur (next shapes)
(concat rchanges shape-rchanges) (concat rchanges shape-rchanges)
(concat uchanges shape-uchanges)))))))) (concat uchanges shape-uchanges))))))))
(defn- generate-sync-shape (defn- generate-sync-shape
[shape root-shape root-component page component] [shape root-shape root-component page component reset-touched?]
(if (nil? component) (if (nil? component)
(remove-component-and-ref shape page) (remove-component-and-ref shape page)
(let [component-shape (get (:objects component) (:shape-ref shape))] (let [component-shape (get (:objects component) (:shape-ref shape))]
(if (nil? component-shape) (if (nil? component-shape)
(remove-ref shape page) (remove-ref shape page)
(update-attrs shape component-shape root-shape root-component page))))) (update-attrs shape
component-shape
root-shape
root-component
page
reset-touched?)))))
(defn- remove-component-and-ref (defn- remove-component-and-ref
[shape page] [shape page]
@ -565,7 +588,9 @@
:val nil} :val nil}
{:type :set {:type :set
:attr :shape-ref :attr :shape-ref
:val nil}]}] :val nil}
{:type :set-touched
:touched nil}]}]
[{:type :mod-obj [{:type :mod-obj
:page-id (:id page) :page-id (:id page)
:id (:id shape) :id (:id shape)
@ -577,7 +602,9 @@
:val (:component-file shape)} :val (:component-file shape)}
{:type :set {:type :set
:attr :shape-ref :attr :shape-ref
:val (:shape-ref shape)}]}]]) :val (:shape-ref shape)}
{:type :set-touched
:touched (:touched shape)}]}]])
(defn- remove-ref (defn- remove-ref
[shape page] [shape page]
@ -586,18 +613,22 @@
:id (:id shape) :id (:id shape)
:operations [{:type :set :operations [{:type :set
:attr :shape-ref :attr :shape-ref
:val nil}]}] :val nil}
{:type :set-touched
:touched nil}]}]
[{:type :mod-obj [{:type :mod-obj
:page-id (:id page) :page-id (:id page)
:id (:id shape) :id (:id shape)
:operations [{:type :set :operations [{:type :set
:attr :shape-ref :attr :shape-ref
:val (:shape-ref shape)}]}]]) :val (:shape-ref shape)}
{:type :set-touched
:touched (:touched shape)}]}]])
(defn- update-attrs (defn- update-attrs
[shape component-shape root-shape root-component page] [shape component-shape root-shape root-component page reset-touched?]
(let [new-pos (calc-new-pos shape component-shape root-shape root-component)] (let [new-pos (calc-new-pos shape component-shape root-shape root-component)]
(loop [attrs (seq sync-attrs) (loop [attrs (seq (keys cp/sync-attrs))
roperations [{:type :set roperations [{:type :set
:attr :x :attr :x
:val (:x new-pos)} :val (:x new-pos)}
@ -613,7 +644,19 @@
(let [attr (first attrs)] (let [attr (first attrs)]
(if (nil? attr) (if (nil? attr)
(let [rchanges [{:type :mod-obj (let [roperations (if reset-touched?
(conj roperations
{:type :set-touched
:touched nil})
roperations)
uoperations (if reset-touched?
(conj uoperations
{:type :set-touched
:touched (:touched shape)})
uoperations)
rchanges [{:type :mod-obj
:page-id (:id page) :page-id (:id page)
:id (:id shape) :id (:id shape)
:operations roperations}] :operations roperations}]
@ -628,41 +671,22 @@
uoperations) uoperations)
(let [roperation {:type :set (let [roperation {:type :set
:attr attr :attr attr
:val (get component-shape attr)} :val (get component-shape attr)
:ignore-touched true}
uoperation {:type :set uoperation {:type :set
:attr attr :attr attr
:val (get shape attr)}] :val (get shape attr)
(recur (next attrs) :ignore-touched true}
(conj roperations roperation)
(conj uoperations uoperation)))))))))
(def sync-attrs [:content attr-group (get cp/sync-attrs attr)
:fill-color touched (get shape :touched #{})]
:fill-color-ref-file (if (or (not (touched attr-group)) reset-touched?)
:fill-color-ref-id (recur (next attrs)
:fill-opacity (conj roperations roperation)
:font-family (conj uoperations uoperation))
:font-size (recur (next attrs)
:font-style roperations
:font-weight uoperations)))))))))
:letter-spacing
:line-height
:proportion
:rx
:ry
:stroke-color
:stroke-color-ref-file
:stroke-color-ref-id
:stroke-opacity
:stroke-style
:stroke-width
:stroke-alignment
:text-align
:width
:height
:interactions
:points
:transform])
(defn- calc-new-pos (defn- calc-new-pos
[shape component-shape root-shape root-component] [shape component-shape root-shape root-component]

View file

@ -34,7 +34,9 @@
[:div.undo-entry-change {:key (str "change-" idx-change)} [:div.undo-entry-change {:key (str "change-" idx-change)}
[:div.undo-entry-change-data (when type (str type)) " " (when id (str (get-in objects [id :name] (subs (str id) 0 8))))] [:div.undo-entry-change-data (when type (str type)) " " (when id (str (get-in objects [id :name] (subs (str id) 0 8))))]
(when operations (when operations
[:div.undo-entry-change-data (str/join ", " (map (comp name :attr) operations))])])])) [:div.undo-entry-change-data (str/join ", "
(map (comp name :attr)
(filter #(= (:type %) :set) operations)))])])]))
(mf/defc history-toolbox [] (mf/defc history-toolbox []
(let [locale (mf/deref i18n/locale) (let [locale (mf/deref i18n/locale)