mirror of
https://github.com/penpot/penpot.git
synced 2025-02-03 12:59:12 -05:00
🎉 Notify shared files clients for update
This commit is contained in:
parent
494cd1e96c
commit
3b516aa139
6 changed files with 80 additions and 31 deletions
|
@ -188,10 +188,6 @@
|
||||||
:library-file-id library-id}))
|
:library-file-id library-id}))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;; A generic, Changes based (granular) file update method.
|
;; A generic, Changes based (granular) file update method.
|
||||||
|
|
||||||
(s/def ::changes
|
(s/def ::changes
|
||||||
|
@ -202,6 +198,13 @@
|
||||||
(s/def ::update-file
|
(s/def ::update-file
|
||||||
(s/keys :req-un [::id ::session-id ::profile-id ::revn ::changes]))
|
(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.
|
||||||
|
(def library-changes
|
||||||
|
#{:add-color :mod-color :del-color
|
||||||
|
:add-media :mod-media :del-media
|
||||||
|
:add-component :mod-component :del-component})
|
||||||
|
|
||||||
(declare update-file)
|
(declare update-file)
|
||||||
(declare retrieve-lagged-changes)
|
(declare retrieve-lagged-changes)
|
||||||
(declare insert-change)
|
(declare insert-change)
|
||||||
|
@ -239,11 +242,27 @@
|
||||||
:file-id (:id file)
|
:file-id (:id file)
|
||||||
:session-id sid
|
:session-id sid
|
||||||
:revn (:revn file)
|
:revn (:revn file)
|
||||||
:changes changes}]
|
:changes changes}
|
||||||
|
|
||||||
|
library-changes (filter #(library-changes (:type %)) changes)]
|
||||||
|
|
||||||
@(redis/run! :publish {:channel (str (:id file))
|
@(redis/run! :publish {:channel (str (:id file))
|
||||||
:message (t/encode-str msg)})
|
:message (t/encode-str msg)})
|
||||||
|
|
||||||
|
(if (and (:is-shared file) (seq library-changes))
|
||||||
|
(let [{:keys [team-id] :as project}
|
||||||
|
(db/get-by-id conn :project (:project-id file))
|
||||||
|
|
||||||
|
msg {:type :library-change
|
||||||
|
:profile-id (:profile-id params)
|
||||||
|
:file-id (:id file)
|
||||||
|
:session-id sid
|
||||||
|
:revn (:revn file)
|
||||||
|
:changes library-changes}]
|
||||||
|
|
||||||
|
@(redis/run! :publish {:channel (str team-id)
|
||||||
|
:message (t/encode-str msg)})))
|
||||||
|
|
||||||
(db/update! conn :file
|
(db/update! conn :file
|
||||||
{:revn (:revn file)
|
{:revn (:revn file)
|
||||||
:data (:data file)}
|
:data (:data file)}
|
||||||
|
|
|
@ -368,12 +368,12 @@
|
||||||
(defmethod change-spec :add-component [_]
|
(defmethod change-spec :add-component [_]
|
||||||
(s/keys :req-un [::id ::name :internal.changes.add-component/shapes]))
|
(s/keys :req-un [::id ::name :internal.changes.add-component/shapes]))
|
||||||
|
|
||||||
|
(defmethod change-spec :mod-component [_]
|
||||||
|
(s/keys :req-un [::id ::name :internal.changes.add-component/shapes]))
|
||||||
|
|
||||||
(defmethod change-spec :del-component [_]
|
(defmethod change-spec :del-component [_]
|
||||||
(s/keys :req-un [::id]))
|
(s/keys :req-un [::id]))
|
||||||
|
|
||||||
(defmethod change-spec :update-component [_]
|
|
||||||
(s/keys :req-un [::id ::name :internal.changes.add-component/shapes]))
|
|
||||||
|
|
||||||
(s/def ::change (s/multi-spec change-spec :type))
|
(s/def ::change (s/multi-spec change-spec :type))
|
||||||
(s/def ::changes (s/coll-of ::change))
|
(s/def ::changes (s/coll-of ::change))
|
||||||
|
|
||||||
|
@ -782,17 +782,17 @@
|
||||||
:name name
|
:name name
|
||||||
:objects (d/index-by :id shapes)}))
|
:objects (d/index-by :id shapes)}))
|
||||||
|
|
||||||
(defmethod process-change :del-component
|
(defmethod process-change :mod-component
|
||||||
[data {:keys [id]}]
|
|
||||||
(d/dissoc-in data [:components id]))
|
|
||||||
|
|
||||||
(defmethod process-change :update-component
|
|
||||||
[data {:keys [id name shapes]}]
|
[data {:keys [id name shapes]}]
|
||||||
(update-in data [:components id]
|
(update-in data [:components id]
|
||||||
#(assoc %
|
#(assoc %
|
||||||
:name name
|
:name name
|
||||||
:objects (d/index-by :id shapes))))
|
:objects (d/index-by :id shapes))))
|
||||||
|
|
||||||
|
(defmethod process-change :del-component
|
||||||
|
[data {:keys [id]}]
|
||||||
|
(d/dissoc-in data [:components id]))
|
||||||
|
|
||||||
(defmethod process-operation :set
|
(defmethod process-operation :set
|
||||||
[shape op]
|
[shape op]
|
||||||
(let [attr (:attr op)
|
(let [attr (:attr op)
|
||||||
|
|
|
@ -345,6 +345,16 @@
|
||||||
qparams {:page-id (first (get-in file [:data :pages]))}]
|
qparams {:page-id (first (get-in file [:data :pages]))}]
|
||||||
(st/emit! (rt/nav-new-window :workspace pparams qparams))))))
|
(st/emit! (rt/nav-new-window :workspace pparams qparams))))))
|
||||||
|
|
||||||
|
(defn ext-library-changed
|
||||||
|
[file-id changes]
|
||||||
|
(us/assert ::us/uuid file-id)
|
||||||
|
(us/assert ::cp/changes changes)
|
||||||
|
(ptk/reify ::ext-library-changed
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(d/update-in-when state [:workspace-libraries file-id :data]
|
||||||
|
cp/process-changes changes))))
|
||||||
|
|
||||||
(declare generate-sync-file)
|
(declare generate-sync-file)
|
||||||
(declare generate-sync-page)
|
(declare generate-sync-page)
|
||||||
(declare generate-sync-shape-and-children)
|
(declare generate-sync-shape-and-children)
|
||||||
|
@ -407,12 +417,12 @@
|
||||||
[new-shape new-shapes _]
|
[new-shape new-shapes _]
|
||||||
(cph/clone-object root-shape nil objects update-new-shape)
|
(cph/clone-object root-shape nil objects update-new-shape)
|
||||||
|
|
||||||
rchanges [{:type :update-component
|
rchanges [{:type :mod-component
|
||||||
:id component-id
|
:id component-id
|
||||||
:name (:name new-shape)
|
:name (:name new-shape)
|
||||||
:shapes new-shapes}]
|
:shapes new-shapes}]
|
||||||
|
|
||||||
uchanges [{:type :update-component
|
uchanges [{:type :mod-component
|
||||||
:id component-id
|
:id component-id
|
||||||
:name (:name component-obj)
|
:name (:name component-obj)
|
||||||
:shapes (vals component-objs)}]]
|
:shapes (vals component-objs)}]]
|
||||||
|
@ -420,7 +430,7 @@
|
||||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))))))
|
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))))))
|
||||||
|
|
||||||
(defn sync-file
|
(defn sync-file
|
||||||
[{:keys [file-id] :as params}]
|
[file-id]
|
||||||
(us/assert (s/nilable ::us/uuid) file-id)
|
(us/assert (s/nilable ::us/uuid) file-id)
|
||||||
(ptk/reify ::sync-file
|
(ptk/reify ::sync-file
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
|
@ -434,6 +444,7 @@
|
||||||
(if (nil? file-id)
|
(if (nil? file-id)
|
||||||
(get-in state [:workspace-data :components])
|
(get-in state [:workspace-data :components])
|
||||||
(get-in state [:workspace-libraries file-id :data :components]))]
|
(get-in state [:workspace-libraries file-id :data :components]))]
|
||||||
|
(when (some? components)
|
||||||
(loop [pages (seq (vals (get-in state [:workspace-data :pages-index])))
|
(loop [pages (seq (vals (get-in state [:workspace-data :pages-index])))
|
||||||
rchanges []
|
rchanges []
|
||||||
uchanges []]
|
uchanges []]
|
||||||
|
@ -441,15 +452,17 @@
|
||||||
(if (nil? page)
|
(if (nil? page)
|
||||||
[rchanges uchanges]
|
[rchanges uchanges]
|
||||||
(let [[page-rchanges page-uchanges]
|
(let [[page-rchanges page-uchanges]
|
||||||
(generate-sync-page page components)]
|
(generate-sync-page file-id page components)]
|
||||||
(recur (next pages)
|
(recur (next pages)
|
||||||
(concat rchanges page-rchanges)
|
(concat rchanges page-rchanges)
|
||||||
(concat uchanges page-uchanges))))))))
|
(concat uchanges page-uchanges)))))))))
|
||||||
|
|
||||||
(defn- generate-sync-page
|
(defn- generate-sync-page
|
||||||
[page components]
|
[file-id page components]
|
||||||
(let [linked-shapes
|
(let [linked-shapes
|
||||||
(cph/select-objects #(some? (:component-id %)) page)]
|
(cph/select-objects #(and (some? (:component-id %))
|
||||||
|
(= (:component-file %) file-id))
|
||||||
|
page)]
|
||||||
(loop [shapes (seq linked-shapes)
|
(loop [shapes (seq linked-shapes)
|
||||||
rchanges []
|
rchanges []
|
||||||
uchanges []]
|
uchanges []]
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
[app.main.data.workspace.common :as dwc]
|
[app.main.data.workspace.common :as dwc]
|
||||||
[app.main.data.workspace.persistence :as dwp]
|
[app.main.data.workspace.persistence :as dwp]
|
||||||
|
[app.main.data.workspace.libraries :as dwl]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.streams :as ms]
|
[app.main.streams :as ms]
|
||||||
|
@ -31,6 +32,7 @@
|
||||||
(declare handle-presence)
|
(declare handle-presence)
|
||||||
(declare handle-pointer-update)
|
(declare handle-pointer-update)
|
||||||
(declare handle-file-change)
|
(declare handle-file-change)
|
||||||
|
(declare handle-library-change)
|
||||||
(declare handle-pointer-send)
|
(declare handle-pointer-send)
|
||||||
(declare send-keepalive)
|
(declare send-keepalive)
|
||||||
|
|
||||||
|
@ -73,6 +75,7 @@
|
||||||
:presence (handle-presence msg)
|
:presence (handle-presence msg)
|
||||||
:pointer-update (handle-pointer-update msg)
|
:pointer-update (handle-pointer-update msg)
|
||||||
:file-change (handle-file-change msg)
|
:file-change (handle-file-change msg)
|
||||||
|
:library-change (handle-library-change msg)
|
||||||
::unknown))
|
::unknown))
|
||||||
|
|
||||||
(defn- send-keepalive
|
(defn- send-keepalive
|
||||||
|
@ -197,3 +200,17 @@
|
||||||
(rx/of (dwp/shapes-changes-persisted file-id msg))
|
(rx/of (dwp/shapes-changes-persisted file-id msg))
|
||||||
(when (seq page-ids)
|
(when (seq page-ids)
|
||||||
(rx/from (map dwc/update-indices page-ids))))))))
|
(rx/from (map dwc/update-indices page-ids))))))))
|
||||||
|
|
||||||
|
(s/def ::library-change-event
|
||||||
|
(s/keys :req-un [::type ::profile-id ::file-id ::session-id ::revn ::changes]))
|
||||||
|
|
||||||
|
(defn handle-library-change
|
||||||
|
[{:keys [file-id changes] :as msg}]
|
||||||
|
(us/assert ::library-change-event msg)
|
||||||
|
(ptk/reify ::handle-library-change
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state stream]
|
||||||
|
(when (contains? (:workspace-libraries state) file-id)
|
||||||
|
(rx/of (dwl/ext-library-changed file-id changes)
|
||||||
|
(dwl/sync-file file-id))))))
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
do-reset-component #(st/emit! (dwl/reset-component id))
|
do-reset-component #(st/emit! (dwl/reset-component id))
|
||||||
do-update-component #(do
|
do-update-component #(do
|
||||||
(st/emit! (dwl/update-component id))
|
(st/emit! (dwl/update-component id))
|
||||||
(st/emit! (dwl/sync-file {:file-id nil})))
|
(st/emit! (dwl/sync-file nil)))
|
||||||
do-navigate-component-file #(st/emit! (dwl/nav-to-component-file
|
do-navigate-component-file #(st/emit! (dwl/nav-to-component-file
|
||||||
(:component-file root-shape)))]
|
(:component-file root-shape)))]
|
||||||
[:*
|
[:*
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
(mf/deps state)
|
(mf/deps state)
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (dwl/delete-component {:id (:component-id @state)}))
|
(st/emit! (dwl/delete-component {:id (:component-id @state)}))
|
||||||
(st/emit! (dwl/sync-file {:file-id nil}))))
|
(st/emit! (dwl/sync-file nil))))
|
||||||
|
|
||||||
on-context-menu
|
on-context-menu
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
|
|
Loading…
Add table
Reference in a new issue