0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-09 00:10:11 -05:00

🎉 Auto sync when changing main instance

This commit is contained in:
Andrés Moya 2022-07-08 16:43:37 +02:00
parent eebd596fca
commit 1ef37281e6
5 changed files with 78 additions and 5 deletions

View file

@ -17,6 +17,7 @@
[app.common.spec :as us]
[app.common.pages.changes-spec :as pcs]
[app.common.types.components-list :as ctkl]
[app.common.types.container :as ctn]
[app.common.types.colors-list :as ctcl]
[app.common.types.page :as ctp]
[app.common.types.pages-list :as ctpl]
@ -37,7 +38,7 @@
;; Page Transformation Changes
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; --- Changes Processing Impl
;; === Changes Processing Impl
(defmulti process-change (fn [_ change] (:type change)))
(defmulti process-operation (fn [_ op] (:type op)))
@ -387,7 +388,7 @@
[data {:keys [id]}]
(update data :typographies dissoc id))
;; -- Operations
;; === Operations
(defmethod process-operation :set
[shape op]
@ -451,3 +452,31 @@
(ex/raise :type :not-implemented
:code :operation-not-implemented
:context {:type (:type op)}))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Component changes detection
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Analyze one change and checks if if modifies the main instance of
;; any component, so that it needs to be synced immediately to the
;; main component. Return the ids of the components that need sync.
(defmulti components-changed (fn [_ change] (:type change)))
(defmethod components-changed :mod-obj
[file-data {:keys [id page-id component-id operations]}]
(when page-id
(let [page (ctpl/get-page file-data page-id)
shape-and-parents (map #(ctn/get-shape page %)
(into [id] (cph/get-parent-ids (:objects page) id)))
any-set? (some #(= (:type %) :set) operations)]
(when any-set?
(into #{} (->> shape-and-parents
(filter #(:main-instance? %))
(map :id)))))))
(defmethod components-changed :default
[_ _]
nil)

View file

@ -214,7 +214,8 @@
(watch [_ state _]
(if (contains? (get-in state [:workspace-data :pages-index]) page-id)
(rx/of (dwp/preload-data-uris)
(dwth/watch-state-changes))
(dwth/watch-state-changes)
(dwl/watch-component-changes))
(let [default-page-id (get-in state [:workspace-data :pages 0])]
(rx/of (go-to-page default-page-id)))))

View file

@ -10,6 +10,7 @@
[app.common.geom.point :as gpt]
[app.common.logging :as log]
[app.common.pages :as cp]
[app.common.pages.changes :as ch]
[app.common.pages.changes-builder :as pcb]
[app.common.pages.changes-spec :as pcs]
[app.common.pages.helpers :as cph]
@ -29,6 +30,7 @@
[app.main.data.workspace.selection :as dws]
[app.main.data.workspace.state-helpers :as wsh]
[app.main.data.workspace.undo :as dwu]
[app.main.refs :as refs]
[app.main.repo :as rp]
[app.main.store :as st]
[app.util.i18n :refer [tr]]
@ -615,7 +617,8 @@
(ptk/reify ::sync-file
ptk/UpdateEvent
(update [_ state]
(if (not= library-id (:current-file-id state))
(if (and (not= library-id (:current-file-id state))
(nil? asset-id))
(d/assoc-in-when state [:workspace-libraries library-id :synced-at] (dt/now))
state))
@ -743,6 +746,46 @@
:callback do-dismiss}]
:sync-dialog))))))
(defn watch-component-changes
"Watch the state for changes that affect to any main instance. If a change is detected will throw
an update-component-sync, so changes are immediately propagated to the component and copies."
[]
(ptk/reify ::watch-component-changes
ptk/WatchEvent
(watch [_ _ stream]
(let [stopper
(->> stream
(rx/filter #(or (= :app.main.data.workspace/finalize-page (ptk/type %))
(= ::watch-component-changes (ptk/type %)))))
workspace-data-str
(->> (rx/concat
(rx/of nil)
(rx/from-atom refs/workspace-data {:emit-current-value? true})))
change-str
(->> stream
(rx/filter #(or (dch/commit-changes? %)
(= (ptk/type %) :app.main.data.workspace.notifications/handle-file-change)))
(rx/observe-on :async))
check-changes
(fn [[event data]]
(let [changes (-> event deref :changes)
components-changed (reduce #(into %1 (ch/components-changed data %2))
#{}
changes)]
(js/console.log "components-changed" (clj->js components-changed))
(when (d/not-empty? components-changed)
(apply st/emit!
(map #(update-component-sync % (:id data))
components-changed)))))]
(->> change-str
(rx/with-latest-from workspace-data-str)
(rx/map check-changes)
(rx/take-until stopper))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Backend interactions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View file

@ -254,6 +254,7 @@
(and (if (nil? component-id)
(ctk/uses-library-components? shape library-id)
(ctk/instance-of? shape library-id component-id))
(not (:main-instance? shape)) ; not need to sync the main instance (avoid infinite loop)
(or (:component-root? shape) (not page?)))) ; avoid nested components inside pages
(defmethod uses-assets? :colors

View file

@ -188,7 +188,6 @@
(add-group % group-name)))))
(st/emit! (dwu/commit-undo-transaction)))
(defn- on-drop-asset
[event asset dragging? selected-assets selected-assets-full selected-assets-paths rename]
(let [create-typed-assets-group (partial create-assets-group rename)]