0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-30 00:21:19 -05:00

Improve workspace initialization flow

This commit is contained in:
Andrey Antukh 2023-05-18 17:04:21 +02:00 committed by Alejandro Alonso
parent 8ca6055935
commit ff00043811
4 changed files with 114 additions and 142 deletions
frontend/src/app/main

View file

@ -142,116 +142,86 @@
(let [data (d/removem (comp t/pointer? val) data)] (let [data (d/removem (comp t/pointer? val) data)]
(assoc state :workspace-data data))))) (assoc state :workspace-data data)))))
(defn- workspace-data-pointers-loaded (defn- resolve-file-data
[pdata] [file-id {:keys [pages-index] :as data}]
(ptk/reify ::workspace-data-pointers-loaded (letfn [(resolve-pointer [[key val :as kv]]
ptk/UpdateEvent (if (t/pointer? val)
(update [_ state] (->> (rp/cmd! :get-file-fragment {:file-id file-id :fragment-id @val})
(update state :workspace-data merge pdata)))) (rx/map #(get % :content))
(rx/map #(vector key %)))
(rx/of kv)))
(resolve-pointers [coll]
(->> (rx/from (seq coll))
(rx/merge-map resolve-pointer)
(rx/reduce conj {})))]
(->> (rx/zip (resolve-pointers data)
(resolve-pointers pages-index))
(rx/take 1)
(rx/map (fn [[data pages-index]]
(assoc data :pages-index pages-index))))))
(defn- bundle-fetched (defn- bundle-fetched
[features [{:keys [id data] :as file} thumbnails project users comments-users]] [features [{:keys [id data] :as file} thumbnails project users comments-users]]
(letfn [(resolve-pointer [file-id [key pointer]] (ptk/reify ::bundle-fetched
(->> (rp/cmd! :get-file-fragment {:file-id file-id :fragment-id @pointer}) ptk/UpdateEvent
(rx/map :content) (update [_ state]
(rx/map #(vector key %)))) (-> state
(assoc :workspace-thumbnails thumbnails)
(assoc :workspace-file (dissoc file :data))
(assoc :workspace-project project)
(assoc :current-team-id (:team-id project))
(assoc :users (d/index-by :id users))
(assoc :current-file-comments-users (d/index-by :id comments-users))))
(resolve-pointers [file-id coll] ptk/WatchEvent
(->> (rx/from (seq coll)) (watch [_ _ stream]
(rx/merge-map (partial resolve-pointer file-id)) (let [team-id (:team-id project)
(rx/reduce conj {})))] stoper (rx/filter (ptk/type? ::bundle-fetched) stream)]
(->> (rx/concat
;; Initialize notifications
(rx/of (dwn/initialize team-id id)
(dwsl/initialize))
(ptk/reify ::bundle-fetched ;; Load team fonts. We must ensure custom fonts are
ptk/UpdateEvent ;; fully loadad before mark workspace as initialized
(update [_ state] (rx/merge
(-> state (->> stream
(assoc :workspace-thumbnails thumbnails) (rx/filter (ptk/type? :app.main.data.fonts/team-fonts-loaded))
(assoc :workspace-file (dissoc file :data)) (rx/take 1)
(assoc :workspace-project project) (rx/ignore))
(assoc :current-team-id (:team-id project))
(assoc :users (d/index-by :id users))
(assoc :current-file-comments-users (d/index-by :id comments-users))))
ptk/WatchEvent (rx/of (df/load-team-fonts team-id))
(watch [_ _ stream]
(let [team-id (:team-id project)
stoper (rx/filter (ptk/type? ::bundle-fetched) stream)]
(->> (rx/concat
;; Initialize notifications
(rx/of (dwn/initialize team-id id)
(dwsl/initialize))
;; Load team fonts. We must ensure custom fonts are fully loadad ;; Load main file
;; before starting the workspace load. (->> (resolve-file-data id data)
(rx/merge (rx/mapcat (fn [{:keys [pages-index] :as data}]
(rx/of (df/load-team-fonts team-id)) (->> (rx/from (seq pages-index))
(->> stream (rx/mapcat
(rx/filter (ptk/type? :app.main.data.fonts/team-fonts-loaded)) (fn [[id page]]
(rx/take 1) (let [page (update page :objects ctst/start-page-index)]
(rx/ignore))) (->> (uw/ask! {:cmd :initialize-page-index :page page})
(rx/map (fn [_] [id page]))))))
(rx/reduce conj {})
(rx/map (fn [pages-index]
(assoc data :pages-index pages-index))))))
(rx/map workspace-data-loaded))
(rx/merge ;; Load libraries
;; Load all pages, independently if they are pointers or already (->> (rp/cmd! :get-file-libraries {:file-id id})
;; resolved values. (rx/mapcat identity)
(->> (rx/from (seq (:pages-index data))) (rx/merge-map
(rx/merge-map (fn [{:keys [id]}]
(fn [[_ page :as kp]] (rp/cmd! :get-file {:id id :features features})))
(if (t/pointer? page) (rx/merge-map
(resolve-pointer id kp) (fn [{:keys [id data] :as file}]
(rx/of kp)))) (->> (resolve-file-data id data)
(rx/merge-map (rx/map (fn [data] (assoc file :data data))))))
(fn [[id page]] (rx/reduce conj [])
(let [page (update page :objects ctst/start-page-index)] (rx/map libraries-fetched)))
(->> (uw/ask! {:cmd :initialize-page-index :page page}) (rx/of (workspace-initialized)))
(rx/map (constantly [id page])))))) (rx/take-until stoper))))))
(rx/reduce conj {})
(rx/map (fn [pages-index]
(-> data
(assoc :pages-index pages-index)
(workspace-data-loaded)))))
;; Once workspace data is loaded, proceed asynchronously load
;; the local library and all referenced libraries, without
;; blocking the main workspace load process.
(->> stream
(rx/filter (ptk/type? ::workspace-data-loaded))
(rx/take 1)
(rx/merge-map
(fn [_]
(rx/merge
(->> data
(filter (comp t/pointer? val))
(resolve-pointers id)
(rx/map workspace-data-pointers-loaded))
(->> (rp/cmd! :get-file-libraries {:file-id id})
(rx/mapcat identity)
(rx/merge-map
(fn [{:keys [id]}]
(rp/cmd! :get-file {:id id :features features})))
(rx/merge-map
(fn [{:keys [id data] :as file}]
(->> (filter (comp t/pointer? val) data)
(resolve-pointers id)
(rx/map #(update file :data merge %)))))
(rx/merge-map
(fn [{:keys [id data] :as file}]
;; Resolve all pages of each library, if needed
(->> (rx/from (seq (:pages-index data)))
(rx/merge-map
(fn [[_ page :as kp]]
(if (t/pointer? page)
(resolve-pointer id kp)
(rx/of kp))))
(rx/reduce conj {})
(rx/map
(fn [pages-index]
(assoc-in file [:data :pages-index] pages-index))))))
(rx/reduce conj [])
(rx/map libraries-fetched)))))))
(rx/of (workspace-initialized)))
(rx/take-until stoper)))))))
(defn- libraries-fetched (defn- libraries-fetched
[libraries] [libraries]
@ -329,6 +299,7 @@
ptk/UpdateEvent ptk/UpdateEvent
(update [_ state] (update [_ state]
(assoc state (assoc state
:workspace-ready? false
:current-file-id file-id :current-file-id file-id
:current-project-id project-id :current-project-id project-id
:workspace-presence {})) :workspace-presence {}))

View file

@ -105,7 +105,11 @@
(l/derived :workspace-drawing st/state)) (l/derived :workspace-drawing st/state))
(def workspace-ready? (def workspace-ready?
(l/derived :workspace-ready? st/state)) (l/derived (fn [state]
(and (:workspace-ready? state)
(:current-file-id state)
(:current-project-id state)))
st/state))
;; TODO: rename to workspace-selected (?) ;; TODO: rename to workspace-selected (?)
;; Don't use directly from components, this is a proxy to improve performance of selected-shapes ;; Don't use directly from components, this is a proxy to improve performance of selected-shapes

View file

@ -131,8 +131,7 @@
i/loader-pencil]) i/loader-pencil])
(mf/defc workspace (mf/defc workspace
{::mf/wrap [mf/memo] {::mf/wrap-props false}
::mf/wrap-props false}
[{:keys [project-id file-id page-id layout-name]}] [{:keys [project-id file-id page-id layout-name]}]
(let [file (mf/deref refs/workspace-file) (let [file (mf/deref refs/workspace-file)
project (mf/deref refs/workspace-project) project (mf/deref refs/workspace-project)

View file

@ -39,7 +39,6 @@
[app.util.dom.dnd :as dnd] [app.util.dom.dnd :as dnd]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[app.util.keyboard :as kbd] [app.util.keyboard :as kbd]
[app.util.perf :as perf]
[app.util.router :as rt] [app.util.router :as rt]
[app.util.strings :refer [matches-search]] [app.util.strings :refer [matches-search]]
[app.util.timers :as ts] [app.util.timers :as ts]
@ -2490,44 +2489,43 @@
show-libraries-dialog show-libraries-dialog
(mf/use-fn #(modal/show! :libraries-dialog {}))] (mf/use-fn #(modal/show! :libraries-dialog {}))]
[:& perf/profiler {:enabled true :label "sidebar/assets"} [:div.assets-bar
[:div.assets-bar [:div.tool-window
[:div.tool-window [:div.tool-window-content
[:div.tool-window-content [:div.assets-bar-title
[:div.assets-bar-title (tr "workspace.assets.assets")
(tr "workspace.assets.assets")
(when-not ^boolean read-only? (when-not ^boolean read-only?
[:div.libraries-button {:on-click show-libraries-dialog} [:div.libraries-button {:on-click show-libraries-dialog}
i/text-align-justify i/text-align-justify
(tr "workspace.assets.libraries")])] (tr "workspace.assets.libraries")])]
[:div.search-block [:div.search-block
[:input.search-input [:input.search-input
{:placeholder (tr "workspace.assets.search") {:placeholder (tr "workspace.assets.search")
:type "text" :type "text"
:value (:term filters) :value (:term filters)
:on-change on-search-term-change :on-change on-search-term-change
:on-key-down handle-key-down}] :on-key-down handle-key-down}]
(if ^boolean (str/empty? (:term filters)) (if ^boolean (str/empty? (:term filters))
[:div.search-icon [:div.search-icon
i/search] i/search]
[:div.search-icon.close [:div.search-icon.close
{:on-click on-search-clear-click} {:on-click on-search-clear-click}
i/close])] i/close])]
[:select.input-select {:value (:section filters) [:select.input-select {:value (:section filters)
:on-change on-section-filter-change} :on-change on-section-filter-change}
[:option {:value ":all"} (tr "workspace.assets.box-filter-all")] [:option {:value ":all"} (tr "workspace.assets.box-filter-all")]
[:option {:value ":components"} (tr "workspace.assets.components")] [:option {:value ":components"} (tr "workspace.assets.components")]
[:option {:value ":graphics"} (tr "workspace.assets.graphics")] [:option {:value ":graphics"} (tr "workspace.assets.graphics")]
[:option {:value ":colors"} (tr "workspace.assets.colors")] [:option {:value ":colors"} (tr "workspace.assets.colors")]
[:option {:value ":typographies"} (tr "workspace.assets.typography")]]]] [:option {:value ":typographies"} (tr "workspace.assets.typography")]]]]
[:& (mf/provider ctx:filters) {:value filters} [:& (mf/provider ctx:filters) {:value filters}
[:& (mf/provider ctx:toggle-ordering) {:value toggle-ordering} [:& (mf/provider ctx:toggle-ordering) {:value toggle-ordering}
[:& (mf/provider ctx:toggle-list-style) {:value toggle-list-style} [:& (mf/provider ctx:toggle-list-style) {:value toggle-list-style}
[:div.libraries-wrapper [:div.libraries-wrapper
[:& assets-local-library {:filters filters}] [:& assets-local-library {:filters filters}]
[:& assets-libraries {:filters filters}]]]]]]])) [:& assets-libraries {:filters filters}]]]]]]))