mirror of
https://github.com/penpot/penpot.git
synced 2025-06-07 11:31:40 +02:00
🐛 Fix workspace hot reload race condtion
This reverts commit 8139ee3ef9
.
This commit is contained in:
parent
807b8d82e3
commit
fe3fec7a50
6 changed files with 77 additions and 86 deletions
|
@ -460,10 +460,11 @@
|
||||||
|
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(-> state
|
(let [file (dissoc file :data)]
|
||||||
(assoc-in [:files id] file)
|
(-> state
|
||||||
(assoc-in [:recent-files id] file)
|
(assoc-in [:files id] file)
|
||||||
(update-in [:projects project-id :count] inc)))))
|
(assoc-in [:recent-files id] file)
|
||||||
|
(update-in [:projects project-id :count] inc))))))
|
||||||
|
|
||||||
(defn create-file
|
(defn create-file
|
||||||
[{:keys [project-id name] :as params}]
|
[{:keys [project-id name] :as params}]
|
||||||
|
|
|
@ -108,9 +108,6 @@
|
||||||
(declare ^:private workspace-initialized)
|
(declare ^:private workspace-initialized)
|
||||||
(declare ^:private fetch-libraries)
|
(declare ^:private fetch-libraries)
|
||||||
(declare ^:private libraries-fetched)
|
(declare ^:private libraries-fetched)
|
||||||
(declare ^:private preload-data-uris)
|
|
||||||
|
|
||||||
;; (declare go-to-layout)
|
|
||||||
|
|
||||||
;; --- Initialize Workspace
|
;; --- Initialize Workspace
|
||||||
|
|
||||||
|
@ -314,13 +311,10 @@
|
||||||
(defn initialize-workspace
|
(defn initialize-workspace
|
||||||
[file-id]
|
[file-id]
|
||||||
(assert (uuid? file-id) "expected valud uuid for `file-id`")
|
(assert (uuid? file-id) "expected valud uuid for `file-id`")
|
||||||
|
|
||||||
(ptk/reify ::initialize-workspace
|
(ptk/reify ::initialize-workspace
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(-> state
|
(-> state
|
||||||
(dissoc :files)
|
|
||||||
(dissoc :workspace-ready)
|
|
||||||
(assoc :recent-colors (:recent-colors storage/user))
|
(assoc :recent-colors (:recent-colors storage/user))
|
||||||
(assoc :recent-fonts (:recent-fonts storage/user))
|
(assoc :recent-fonts (:recent-fonts storage/user))
|
||||||
(assoc :current-file-id file-id)
|
(assoc :current-file-id file-id)
|
||||||
|
@ -395,11 +389,9 @@
|
||||||
(dissoc
|
(dissoc
|
||||||
:current-file-id
|
:current-file-id
|
||||||
:workspace-editor-state
|
:workspace-editor-state
|
||||||
:files
|
|
||||||
:workspace-media-objects
|
:workspace-media-objects
|
||||||
:workspace-persistence
|
:workspace-persistence
|
||||||
:workspace-presence
|
:workspace-presence
|
||||||
:workspace-ready
|
|
||||||
:workspace-undo)
|
:workspace-undo)
|
||||||
(update :workspace-global dissoc :read-only?)
|
(update :workspace-global dissoc :read-only?)
|
||||||
(assoc-in [:workspace-global :options-mode] :design)))
|
(assoc-in [:workspace-global :options-mode] :design)))
|
||||||
|
@ -426,48 +418,67 @@
|
||||||
;; Make this event callable through dynamic resolution
|
;; Make this event callable through dynamic resolution
|
||||||
(defmethod ptk/resolve ::reload-current-file [_ _] (reload-current-file))
|
(defmethod ptk/resolve ::reload-current-file [_ _] (reload-current-file))
|
||||||
|
|
||||||
(defn initialize-page
|
|
||||||
[page-id]
|
|
||||||
(assert (uuid? page-id) "expected valid uuid for `page-id`")
|
|
||||||
|
|
||||||
(ptk/reify ::initialize-page
|
|
||||||
|
(def ^:private xf:collect-file-media
|
||||||
|
"Resolve and collect all file media on page objects"
|
||||||
|
(comp (map second)
|
||||||
|
(keep (fn [{:keys [metadata fill-image]}]
|
||||||
|
(cond
|
||||||
|
(some? metadata) (cf/resolve-file-media metadata)
|
||||||
|
(some? fill-image) (cf/resolve-file-media fill-image))))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn- initialize-page*
|
||||||
|
"Second phase of page initialization, once we know the page is
|
||||||
|
available on the sate"
|
||||||
|
[file-id page-id page]
|
||||||
|
(ptk/reify ::initialize-page*
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(if-let [{:keys [id] :as page} (dsh/lookup-page state page-id)]
|
;; selection; when user abandon the current page, the selection is lost
|
||||||
;; we maintain a cache of page state for user convenience with the exception of the
|
(let [local (dm/get-in state [:workspace-cache [file-id page-id]] default-workspace-local)]
|
||||||
;; selection; when user abandon the current page, the selection is lost
|
(-> state
|
||||||
(let [local (dm/get-in state [:workspace-cache id] default-workspace-local)]
|
(assoc :current-page-id page-id)
|
||||||
(-> state
|
(assoc :workspace-local (assoc local :selected (d/ordered-set)))
|
||||||
(assoc :current-page-id id)
|
(assoc :workspace-trimmed-page (dm/select-keys page [:id :name]))
|
||||||
(assoc :workspace-local (assoc local :selected (d/ordered-set)))
|
|
||||||
(assoc :workspace-trimmed-page (dm/select-keys page [:id :name]))
|
|
||||||
|
|
||||||
;; FIXME: this should be done on `initialize-layout` (?)
|
;; FIXME: this should be done on `initialize-layout` (?)
|
||||||
(update :workspace-layout layout/load-layout-flags)
|
(update :workspace-layout layout/load-layout-flags)
|
||||||
(update :workspace-global layout/load-layout-state)))
|
(update :workspace-global layout/load-layout-state))))
|
||||||
|
|
||||||
state))
|
ptk/EffectEvent
|
||||||
|
(effect [_ _ _]
|
||||||
|
(let [uris (into #{} xf:collect-file-media (:objects page))]
|
||||||
|
(->> (rx/from uris)
|
||||||
|
(rx/subs! #(http/fetch-data-uri % false)))))))
|
||||||
|
|
||||||
|
(defn initialize-page
|
||||||
|
[file-id page-id]
|
||||||
|
(assert (uuid? file-id) "expected valid uuid for `file-id`")
|
||||||
|
|
||||||
|
(ptk/reify ::initialize-page
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(if (dsh/lookup-page state page-id)
|
(if-let [page (dsh/lookup-page state file-id page-id)]
|
||||||
(let [file-id (:current-file-id state)]
|
(rx/of (initialize-page* file-id page-id page)
|
||||||
(rx/of (preload-data-uris page-id)
|
(dwth/watch-state-changes file-id page-id)
|
||||||
(dwth/watch-state-changes file-id page-id)
|
(dwl/watch-component-changes))
|
||||||
(dwl/watch-component-changes)))
|
(rx/of (dcm/go-to-workspace :file-id file-id ::rt/replace true))))))
|
||||||
(rx/of (dcm/go-to-workspace))))))
|
|
||||||
|
|
||||||
(defn finalize-page
|
(defn finalize-page
|
||||||
[page-id]
|
[file-id page-id]
|
||||||
|
(assert (uuid? file-id) "expected valid uuid for `file-id`")
|
||||||
(assert (uuid? page-id) "expected valid uuid for `page-id`")
|
(assert (uuid? page-id) "expected valid uuid for `page-id`")
|
||||||
|
|
||||||
(ptk/reify ::finalize-page
|
(ptk/reify ::finalize-page
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(let [local (-> (:workspace-local state)
|
(let [local (-> (:workspace-local state)
|
||||||
(dissoc :edition :edit-path :selected))
|
(dissoc :edition :edit-path :selected))
|
||||||
exit? (not= :workspace (dm/get-in state [:route :data :name]))
|
exit? (not= :workspace (rt/lookup-name state))
|
||||||
state (-> state
|
state (-> state
|
||||||
(update :workspace-cache assoc page-id local)
|
(update :workspace-cache assoc [file-id page-id] local)
|
||||||
(dissoc :current-page-id
|
(dissoc :current-page-id
|
||||||
:workspace-local
|
:workspace-local
|
||||||
:workspace-trimmed-page
|
:workspace-trimmed-page
|
||||||
|
@ -476,22 +487,6 @@
|
||||||
(cond-> state
|
(cond-> state
|
||||||
exit? (dissoc :workspace-drawing))))))
|
exit? (dissoc :workspace-drawing))))))
|
||||||
|
|
||||||
(defn- preload-data-uris
|
|
||||||
"Preloads the image data so it's ready when necessary"
|
|
||||||
[page-id]
|
|
||||||
(ptk/reify ::preload-data-uris
|
|
||||||
ptk/EffectEvent
|
|
||||||
(effect [_ state _]
|
|
||||||
(let [xform (comp (map second)
|
|
||||||
(keep (fn [{:keys [metadata fill-image]}]
|
|
||||||
(cond
|
|
||||||
(some? metadata) (cf/resolve-file-media metadata)
|
|
||||||
(some? fill-image) (cf/resolve-file-media fill-image)))))
|
|
||||||
uris (into #{} xform (dsh/lookup-page-objects state page-id))]
|
|
||||||
|
|
||||||
(->> (rx/from uris)
|
|
||||||
(rx/subs! #(http/fetch-data-uri % false)))))))
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Workspace Page CRUD
|
;; Workspace Page CRUD
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
|
@ -120,6 +120,11 @@
|
||||||
([id params & {:as options}]
|
([id params & {:as options}]
|
||||||
(navigate id params options)))
|
(navigate id params options)))
|
||||||
|
|
||||||
|
(defn lookup-name
|
||||||
|
[state]
|
||||||
|
(dm/get-in state [:route :data :name]))
|
||||||
|
|
||||||
|
;; FIXME: rename to lookup-params
|
||||||
(defn get-params
|
(defn get-params
|
||||||
[state]
|
[state]
|
||||||
(dm/get-in state [:route :params :query]))
|
(dm/get-in state [:route :params :query]))
|
||||||
|
|
|
@ -127,7 +127,6 @@
|
||||||
{::mf/props :obj
|
{::mf/props :obj
|
||||||
::mf/private true}
|
::mf/private true}
|
||||||
[{:keys [team-id children]}]
|
[{:keys [team-id children]}]
|
||||||
|
|
||||||
(mf/with-effect [team-id]
|
(mf/with-effect [team-id]
|
||||||
(st/emit! (dtm/initialize-team team-id))
|
(st/emit! (dtm/initialize-team team-id))
|
||||||
(fn []
|
(fn []
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.main.data.common :as dcm]
|
[app.main.data.common :as dcm]
|
||||||
[app.main.data.helpers :as dsh]
|
|
||||||
[app.main.data.persistence :as dps]
|
[app.main.data.persistence :as dps]
|
||||||
[app.main.data.plugins :as dpl]
|
[app.main.data.plugins :as dpl]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
|
@ -43,13 +42,6 @@
|
||||||
[okulary.core :as l]
|
[okulary.core :as l]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
(defn- make-workspace-ready-ref
|
|
||||||
[file-id]
|
|
||||||
(l/derived (fn [state]
|
|
||||||
(and (= file-id (:workspace-ready state))
|
|
||||||
(some? (dsh/lookup-file-data state file-id))))
|
|
||||||
st/state))
|
|
||||||
|
|
||||||
(mf/defc workspace-content*
|
(mf/defc workspace-content*
|
||||||
{::mf/private true}
|
{::mf/private true}
|
||||||
[{:keys [file layout page wglobal]}]
|
[{:keys [file layout page wglobal]}]
|
||||||
|
@ -129,35 +121,32 @@
|
||||||
|
|
||||||
(mf/defc workspace-page*
|
(mf/defc workspace-page*
|
||||||
{::mf/private true}
|
{::mf/private true}
|
||||||
[{:keys [page-id file layout wglobal]}]
|
[{:keys [page-id file-id file layout wglobal]}]
|
||||||
(let [page-id (hooks/use-equal-memo page-id)
|
(let [page (mf/deref refs/workspace-page)]
|
||||||
page (mf/deref refs/workspace-page)]
|
|
||||||
|
|
||||||
(mf/with-effect []
|
(mf/with-effect []
|
||||||
(let [focus-out #(st/emit! (dw/workspace-focus-lost))
|
(let [focus-out #(st/emit! (dw/workspace-focus-lost))
|
||||||
key (events/listen globals/window "blur" focus-out)]
|
key (events/listen globals/window "blur" focus-out)]
|
||||||
(partial events/unlistenByKey key)))
|
(partial events/unlistenByKey key)))
|
||||||
|
|
||||||
(mf/with-effect [page-id]
|
(mf/with-effect [file-id page-id]
|
||||||
(if (some? page-id)
|
(st/emit! (dw/initialize-page file-id page-id))
|
||||||
(st/emit! (dw/initialize-page page-id))
|
|
||||||
(st/emit! (dcm/go-to-workspace ::rt/replace true)))
|
|
||||||
|
|
||||||
(fn []
|
(fn []
|
||||||
(when (some? page-id)
|
(when page-id
|
||||||
(st/emit! (dw/finalize-page page-id)))))
|
(st/emit! (dw/finalize-page file-id page-id)))))
|
||||||
|
|
||||||
(if (some? page)
|
(if (some? page)
|
||||||
[:> workspace-content* {:file file
|
[:> workspace-content* {:file file
|
||||||
:page page
|
:page page
|
||||||
:wglobal wglobal
|
:wglobal wglobal
|
||||||
:layout layout}]
|
:layout layout}]
|
||||||
[:& workspace-loader*])))
|
[:> workspace-loader*])))
|
||||||
|
|
||||||
|
|
||||||
(def ^:private ref:file-without-data
|
(def ^:private ref:file-without-data
|
||||||
(l/derived (fn [file]
|
(l/derived (fn [file]
|
||||||
(dissoc file :data))
|
(-> file
|
||||||
|
(dissoc :data)
|
||||||
|
(assoc ::has-data (contains? file :data))))
|
||||||
refs/file
|
refs/file
|
||||||
=))
|
=))
|
||||||
|
|
||||||
|
@ -181,10 +170,6 @@
|
||||||
read-only? (mf/deref refs/workspace-read-only?)
|
read-only? (mf/deref refs/workspace-read-only?)
|
||||||
read-only? (or read-only? (not (:can-edit permissions)))
|
read-only? (or read-only? (not (:can-edit permissions)))
|
||||||
|
|
||||||
ready* (mf/with-memo [file-id]
|
|
||||||
(make-workspace-ready-ref file-id))
|
|
||||||
ready? (mf/deref ready*)
|
|
||||||
|
|
||||||
design-tokens? (features/use-feature "design-tokens/v1")
|
design-tokens? (features/use-feature "design-tokens/v1")
|
||||||
|
|
||||||
background-color (:background-color wglobal)]
|
background-color (:background-color wglobal)]
|
||||||
|
@ -207,6 +192,10 @@
|
||||||
(st/emit! ::dps/force-persist
|
(st/emit! ::dps/force-persist
|
||||||
(dw/finalize-workspace file-id))))
|
(dw/finalize-workspace file-id))))
|
||||||
|
|
||||||
|
(mf/with-effect [file page-id]
|
||||||
|
(when-not page-id
|
||||||
|
(st/emit! (dcm/go-to-workspace :file-id file-id ::rt/replace true))))
|
||||||
|
|
||||||
[:> (mf/provider ctx/current-project-id) {:value project-id}
|
[:> (mf/provider ctx/current-project-id) {:value project-id}
|
||||||
[:> (mf/provider ctx/current-file-id) {:value file-id}
|
[:> (mf/provider ctx/current-file-id) {:value file-id}
|
||||||
[:> (mf/provider ctx/current-page-id) {:value page-id}
|
[:> (mf/provider ctx/current-page-id) {:value page-id}
|
||||||
|
@ -219,9 +208,11 @@
|
||||||
:touch-action "none"}}
|
:touch-action "none"}}
|
||||||
[:> context-menu*]
|
[:> context-menu*]
|
||||||
|
|
||||||
(if ^boolean ready?
|
(if (::has-data file)
|
||||||
[:> workspace-page* {:page-id page-id
|
[:> workspace-page*
|
||||||
:file file
|
{:page-id page-id
|
||||||
:wglobal wglobal
|
:file-id file-id
|
||||||
:layout layout}]
|
:file file
|
||||||
|
:wglobal wglobal
|
||||||
|
:layout layout}]
|
||||||
[:> workspace-loader*])]]]]]]]))
|
[:> workspace-loader*])]]]]]]]))
|
||||||
|
|
|
@ -63,10 +63,10 @@
|
||||||
target-container-id (or target-container-id (:parent-id shape))]
|
target-container-id (or target-container-id (:parent-id shape))]
|
||||||
|
|
||||||
(filter some?
|
(filter some?
|
||||||
[(when target-page-id (dw/initialize-page target-page-id))
|
[(when target-page-id (dw/initialize-page (:id file) target-page-id))
|
||||||
(dws/select-shape target-container-id)
|
(dws/select-shape target-container-id)
|
||||||
(dw/paste-shapes pdata)
|
(dw/paste-shapes pdata)
|
||||||
(when target-page-id (dw/initialize-page (:id page)))])))
|
(when target-page-id (dw/initialize-page (:id file) (:id page)))])))
|
||||||
|
|
||||||
(defn- sync-file [file]
|
(defn- sync-file [file]
|
||||||
(map (fn [component-tag]
|
(map (fn [component-tag]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue