Ensure workspace page loading and intialization process

This commit is contained in:
Andrey Antukh 2025-04-07 06:58:53 +02:00
parent 6b3a988526
commit b8107ee497
4 changed files with 99 additions and 51 deletions

View file

@ -120,7 +120,7 @@
;; to lost team features updating ;; to lost team features updating
;; When newly computed features does not match exactly with ;; When newly computed features does not match exactly with
;; the features defined on team row, we update it. ;; the features defined on team row, we update it
(when (not= features (:features team)) (when (not= features (:features team))
(let [features (db/create-array conn "text" features)] (let [features (db/create-array conn "text" features)]
(db/update! conn :team (db/update! conn :team

View file

@ -334,7 +334,8 @@
(rx/take-until stopper-s)))))) (rx/take-until stopper-s))))))
(defn initialize-workspace (defn initialize-workspace
[file-id] [team-id file-id]
(assert (uuid? team-id) "expected valud uuid for `team-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
@ -410,7 +411,7 @@
(unchecked-set ug/global "name" name))))) (unchecked-set ug/global "name" name)))))
(defn finalize-workspace (defn finalize-workspace
[file-id] [_team-id file-id]
(ptk/reify ::finalize-workspace (ptk/reify ::finalize-workspace
ptk/UpdateEvent ptk/UpdateEvent
(update [_ state] (update [_ state]
@ -444,8 +445,9 @@
(ptk/reify ::reload-current-file (ptk/reify ::reload-current-file
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [file-id (:current-file-id state)] (let [file-id (:current-file-id state)
(rx/of (initialize-workspace file-id)))))) team-id (:current-team-id state)]
(rx/of (initialize-workspace team-id file-id))))))
;; 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))
@ -488,18 +490,25 @@
(defn initialize-page (defn initialize-page
[file-id page-id] [file-id page-id]
(assert (uuid? file-id) "expected valid uuid for `file-id`") (assert (uuid? file-id) "expected valid uuid for `file-id`")
(assert (uuid? page-id) "expected valid uuid for `page-id`")
(ptk/reify ::initialize-page (ptk/reify ::initialize-page
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(if-let [page (dsh/lookup-page state file-id page-id)] (if-let [page (dsh/lookup-page state file-id page-id)]
(rx/concat (rx/of (initialize-page* file-id page-id page) (rx/concat
(dwth/watch-state-changes file-id page-id) (rx/of (initialize-page* file-id page-id page)
(dwl/watch-component-changes)) (dwth/watch-state-changes file-id page-id)
(let [profile (:profile state) (dwl/watch-component-changes))
props (get profile :props)] (let [profile (:profile state)
(when (not (:workspace-visited props)) props (get profile :props)]
(rx/of (select-frame-tool file-id page-id))))) (when (not (:workspace-visited props))
(rx/of (select-frame-tool file-id page-id)))))
;; NOTE: this redirect is necessary for cases where user
;; explicitly passes an non-existing page-id on the url
;; params, so on check it we can detect that there are no data
;; for the page and redirect user to an existing page
(rx/of (dcm/go-to-workspace :file-id file-id ::rt/replace true)))))) (rx/of (dcm/go-to-workspace :file-id file-id ::rt/replace true))))))
(defn finalize-page (defn finalize-page

View file

@ -10,6 +10,7 @@
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.schema :as sm] [app.common.schema :as sm]
[app.main.data.event :as ev] [app.main.data.event :as ev]
[app.main.data.helpers :as dsh]
[app.main.data.persistence :as dwp] [app.main.data.persistence :as dwp]
[app.main.data.workspace :as dw] [app.main.data.workspace :as dw]
[app.main.data.workspace.thumbnails :as th] [app.main.data.workspace.thumbnails :as th]
@ -97,7 +98,8 @@
(ptk/reify ::restore-version (ptk/reify ::restore-version
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [file-id (:current-file-id state)] (let [file-id (:current-file-id state)
team-id (:current-team-id state)]
(rx/concat (rx/concat
(rx/of ::dwp/force-persist (rx/of ::dwp/force-persist
(dw/remove-layout-flag :document-history)) (dw/remove-layout-flag :document-history))
@ -106,7 +108,7 @@
(rx/take 1) (rx/take 1)
(rx/mapcat #(rp/cmd! :restore-file-snapshot {:file-id file-id :id id})) (rx/mapcat #(rp/cmd! :restore-file-snapshot {:file-id file-id :id id}))
(rx/tap #(th/clear-queue!)) (rx/tap #(th/clear-queue!))
(rx/map #(dw/initialize-workspace file-id))) (rx/map #(dw/initialize-workspace team-id file-id)))
(case origin (case origin
:version :version
(rx/of (ptk/event ::ev/event {::ev/name "restore-pin-version"})) (rx/of (ptk/event ::ev/event {::ev/name "restore-pin-version"}))
@ -200,21 +202,24 @@
(ptk/reify ::restore-version-from-plugins (ptk/reify ::restore-version-from-plugins
ptk/WatchEvent ptk/WatchEvent
(watch [_ _ _] (watch [_ state _]
(rx/concat ;; FIXME: revisit this
(rx/of (ptk/event ::ev/event {::ev/name "restore-version-plugin"}) (let [file (dsh/lookup-file state file-id)
::dwp/force-persist) team-id (:team-id file)]
(rx/concat
(rx/of (ptk/event ::ev/event {::ev/name "restore-version-plugin"})
::dwp/force-persist)
;; FIXME: we should abstract this ;; FIXME: we should abstract this
(->> (rx/from-atom refs/persistence-state {:emit-current-value? true}) (->> (rx/from-atom refs/persistence-state {:emit-current-value? true})
(rx/filter #(or (nil? %) (= :saved %))) (rx/filter #(or (nil? %) (= :saved %)))
(rx/take 1) (rx/take 1)
(rx/mapcat #(rp/cmd! :restore-file-snapshot {:file-id file-id :id id})) (rx/mapcat #(rp/cmd! :restore-file-snapshot {:file-id file-id :id id}))
(rx/map #(dw/initialize-workspace file-id))) (rx/map #(dw/initialize-workspace team-id file-id)))
(->> (rx/of 1) (->> (rx/of 1)
(rx/tap resolve) (rx/tap resolve)
(rx/ignore)))))) (rx/ignore)))))))

View file

@ -9,6 +9,7 @@
(: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]
@ -45,9 +46,10 @@
(mf/defc workspace-content* (mf/defc workspace-content*
{::mf/private true} {::mf/private true}
[{:keys [file layout page wglobal]}] [{:keys [file layout page wglobal]}]
(let [palete-size (mf/use-state nil) (let [palete-size (mf/use-state nil)
selected (mf/deref refs/selected-shapes) selected (mf/deref refs/selected-shapes)
page-id (:id page) page-id (get page :id)
{:keys [vport] :as wlocal} (mf/deref refs/workspace-local) {:keys [vport] :as wlocal} (mf/deref refs/workspace-local)
{:keys [options-mode]} wglobal {:keys [options-mode]} wglobal
@ -120,10 +122,46 @@
:overlay true :overlay true
:file-loading true}]) :file-loading true}])
(defn- make-team-ref
[team-id]
(l/derived (fn [state]
(let [teams (get state :teams)]
(get teams team-id)))
st/state))
(defn- make-file-ref
[file-id]
(l/derived (fn [state]
;; NOTE: for ensure ordering of execution, we need to
;; wait the file initialization completly success until
;; mark this file availablea and unlock the rendering
;; of the following components
(when (= (get state :current-file-id) file-id)
(let [files (get state :files)
file (get files file-id)]
(-> file
(dissoc :data)
(assoc ::has-data (contains? file :data))))))
st/state))
(defn- make-page-ref
[file-id page-id]
(l/derived (fn [state]
(let [current-page-id (get state :current-page-id)]
;; NOTE: for ensure ordering of execution, we need to
;; wait the page initialization completly success until
;; mark this file availablea and unlock the rendering
;; of the following components
(when (= current-page-id page-id)
(dsh/lookup-page state file-id page-id))))
st/state))
(mf/defc workspace-page* (mf/defc workspace-page*
{::mf/private true} {::mf/private true}
[{:keys [page-id file-id file layout wglobal]}] [{:keys [page-id file-id file layout wglobal]}]
(let [page (mf/deref refs/workspace-page)] (let [page-ref (mf/with-memo [file-id page-id]
(make-page-ref file-id page-id))
page (mf/deref page-ref)]
(mf/with-effect [] (mf/with-effect []
(let [focus-out #(st/emit! (dw/workspace-focus-lost)) (let [focus-out #(st/emit! (dw/workspace-focus-lost))
@ -133,8 +171,7 @@
(mf/with-effect [file-id page-id] (mf/with-effect [file-id page-id]
(st/emit! (dw/initialize-page file-id page-id)) (st/emit! (dw/initialize-page file-id page-id))
(fn [] (fn []
(when page-id (st/emit! (dw/finalize-page file-id 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
@ -143,18 +180,9 @@
:layout layout}] :layout layout}]
[:> workspace-loader*]))) [:> workspace-loader*])))
(def ^:private ref:file-without-data
(l/derived (fn [file]
(-> file
(dissoc :data)
(assoc ::has-data (contains? file :data))))
refs/file
=))
(mf/defc workspace* (mf/defc workspace*
{::mf/props :obj {::mf/wrap [mf/memo]}
::mf/wrap [mf/memo]} [{:keys [team-id project-id file-id page-id layout-name]}]
[{:keys [project-id file-id page-id layout-name]}]
(let [file-id (hooks/use-equal-memo file-id) (let [file-id (hooks/use-equal-memo file-id)
page-id (hooks/use-equal-memo page-id) page-id (hooks/use-equal-memo page-id)
@ -162,8 +190,15 @@
layout (mf/deref refs/workspace-layout) layout (mf/deref refs/workspace-layout)
wglobal (mf/deref refs/workspace-global) wglobal (mf/deref refs/workspace-global)
team (mf/deref refs/team) team-ref (mf/with-memo [team-id]
file (mf/deref ref:file-without-data) (make-team-ref team-id))
file-ref (mf/with-memo [file-id]
(make-file-ref file-id))
team (mf/deref team-ref)
file (mf/deref file-ref)
file-loaded? (get file ::has-data)
file-name (:name file) file-name (:name file)
permissions (:permissions team) permissions (:permissions team)
@ -187,14 +222,14 @@
(when file-name (when file-name
(dom/set-html-title (tr "title.workspace" file-name)))) (dom/set-html-title (tr "title.workspace" file-name))))
(mf/with-effect [file-id] (mf/with-effect [team-id file-id]
(st/emit! (dw/initialize-workspace file-id)) (st/emit! (dw/initialize-workspace team-id file-id))
(fn [] (fn []
(st/emit! ::dps/force-persist (st/emit! ::dps/force-persist
(dw/finalize-workspace file-id)))) (dw/finalize-workspace team-id file-id))))
(mf/with-effect [file page-id] (mf/with-effect [file-id page-id file-loaded?]
(when-not page-id (when (and file-loaded? (not page-id))
(st/emit! (dcm/go-to-workspace :file-id file-id ::rt/replace true)))) (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}
@ -208,8 +243,7 @@
:style {:background-color background-color :style {:background-color background-color
:touch-action "none"}} :touch-action "none"}}
[:> context-menu*] [:> context-menu*]
(if (and file-loaded? page-id)
(if (::has-data file)
[:> workspace-page* [:> workspace-page*
{:page-id page-id {:page-id page-id
:file-id file-id :file-id file-id