Hot swap of viewport when renderer changes

This commit is contained in:
Belén Albeza 2026-04-23 16:01:19 +02:00
parent 222c0d5b73
commit 9feaac3e05
7 changed files with 109 additions and 76 deletions

View File

@ -15,6 +15,7 @@
[app.main.data.media :as di]
[app.main.data.notifications :as ntf]
[app.main.data.team :as-alias dtm]
[app.main.features :as features]
[app.main.repo :as rp]
[app.main.router :as rt]
[app.plugins.register :as plugins.register]
@ -291,8 +292,13 @@
;; FIXME
ptk/WatchEvent
(watch [_ _ _]
(->> (rp/cmd! :update-profile-props {:props props})
(rx/map (constantly (refresh-profile)))))))
(let [refresh-profile$ (->> (rp/cmd! :update-profile-props {:props props})
(rx/map (constantly (refresh-profile))))
recompute$ (when (contains? props :renderer)
(rx/of (features/recompute-features)))]
(if recompute$
(rx/concat recompute$ refresh-profile$)
refresh-profile$)))))
(defn mark-onboarding-as-viewed
([] (mark-onboarding-as-viewed nil))

View File

@ -72,6 +72,7 @@
[app.main.refs :as refs]
[app.main.repo :as rp]
[app.main.router :as rt]
[app.main.store :as st]
[app.render-wasm :as wasm]
[app.render-wasm.api :as wasm.api]
[app.util.dom :as dom]
@ -318,7 +319,7 @@
(let [stoper-s (rx/filter (ptk/type? ::finalize-workspace) stream)
rparams (rt/get-params state)
features (features/get-enabled-features state team-id)
render-wasm? (contains? features "render-wasm/v1")]
render-wasm? #(features/active-feature? @st/state "render-wasm/v1")]
(log/debug :hint "initialize-workspace"
:team-id (dm/str team-id)
@ -329,7 +330,7 @@
(rx/concat
;; Fetch all essential data that should be loaded before the file
(rx/merge
(if ^boolean render-wasm?
(if ^boolean (render-wasm?)
(->> (rx/from @wasm/module)
(rx/filter true?)
(rx/tap (fn [_]
@ -405,72 +406,72 @@
(rx/take 1)
(rx/map #(dwcm/navigate-to-comment-id comment-id))))
(when render-wasm?
(->> stream
(rx/filter dch/commit?)
(rx/map deref)
(rx/mapcat
(fn [{:keys [redo-changes]}]
(let [added (->> redo-changes
(filter #(= (:type %) :add-obj))
(map :id))]
(->> (rx/from added)
(rx/map process-wasm-object)))))))
(->> stream
(rx/filter dch/commit?)
(rx/filter (fn [_] (render-wasm?)))
(rx/map deref)
(rx/mapcat
(fn [{:keys [redo-changes]}]
(let [added (->> redo-changes
(filter #(= (:type %) :add-obj))
(map :id))]
(->> (rx/from added)
(rx/map process-wasm-object))))))
(when render-wasm?
(let [local-commits-s
(->> stream
(rx/filter dch/commit?)
(rx/map deref)
(rx/filter #(and (= :local (:source %))
(not (contains? (:tags %) :position-data))))
(rx/filter (complement empty?)))
(let [local-commits-s
(->> stream
(rx/filter dch/commit?)
(rx/filter (fn [_] (render-wasm?)))
(rx/map deref)
(rx/filter #(and (= :local (:source %))
(not (contains? (:tags %) :position-data))))
(rx/filter (complement empty?)))
notifier-s
(rx/merge
(->> local-commits-s (rx/debounce 1000))
(->> stream (rx/filter dps/force-persist?)))
notifier-s
(rx/merge
(->> local-commits-s (rx/debounce 1000))
(->> stream (rx/filter dps/force-persist?)))
objects-s
(rx/from-atom refs/workspace-page-objects {:emit-current-value? true})
objects-s
(rx/from-atom refs/workspace-page-objects {:emit-current-value? true})
current-page-id-s
(rx/from-atom refs/current-page-id {:emit-current-value? true})]
current-page-id-s
(rx/from-atom refs/current-page-id {:emit-current-value? true})]
(->> local-commits-s
(rx/buffer-until notifier-s)
(rx/with-latest-from objects-s)
(rx/map
(fn [[commits objects]]
(->> commits
(mapcat :redo-changes)
(filter #(contains? #{:mod-obj :add-obj} (:type %)))
(filter #(cfh/text-shape? objects (:id %)))
(map #(vector
(:id %)
(wasm.api/calculate-position-data (get objects (:id %))))))))
(->> local-commits-s
(rx/buffer-until notifier-s)
(rx/with-latest-from objects-s)
(rx/map
(fn [[commits objects]]
(->> commits
(mapcat :redo-changes)
(filter #(contains? #{:mod-obj :add-obj} (:type %)))
(filter #(cfh/text-shape? objects (:id %)))
(map #(vector
(:id %)
(wasm.api/calculate-position-data (get objects (:id %))))))))
(rx/with-latest-from current-page-id-s)
(rx/map
(fn [[text-position-data page-id]]
(let [changes
(->> text-position-data
(mapv (fn [[id position-data]]
{:type :mod-obj
:id id
:page-id page-id
:operations
[{:type :set
:attr :position-data
:val position-data
:ignore-touched true
:ignore-geometry true}]})))]
(when (d/not-empty? changes)
(dch/commit-changes
{:redo-changes changes :undo-changes []
:save-undo? false
:tags #{:position-data}})))))
(rx/take-until stoper-s))))
(rx/with-latest-from current-page-id-s)
(rx/map
(fn [[text-position-data page-id]]
(let [changes
(->> text-position-data
(mapv (fn [[id position-data]]
{:type :mod-obj
:id id
:page-id page-id
:operations
[{:type :set
:attr :position-data
:val position-data
:ignore-touched true
:ignore-geometry true}]})))]
(when (d/not-empty? changes)
(dch/commit-changes
{:redo-changes changes :undo-changes []
:save-undo? false
:tags #{:position-data}})))))
(rx/take-until stoper-s)))
(->> stream
(rx/filter dch/commit?)

View File

@ -30,9 +30,9 @@
[features state]
(let [params (rt/get-params state)
wasm (get params :wasm)
enable-wasm (= "true" wasm)
renderer (-> state :profile :props :renderer)
disable-wasm (or (= "false" wasm) (= renderer :svg))
enable-wasm (or (= "true" wasm) (and (= renderer :wasm) (not= "false" wasm)))
disable-wasm (or (= "false" wasm) (and (= renderer :svg) (not= "true" wasm)))
features (cond-> features
enable-wasm (conj "render-wasm/v1")
disable-wasm (disj "render-wasm/v1"))]
@ -178,3 +178,24 @@
(log/inf :hint "initialized"
:enabled (str/join " " features))))))
(defn recompute-features
[]
(ptk/reify ::recompute-features
ptk/UpdateEvent
(update [_ state]
(let [previous (or (get state :features) #{})
features (setup-wasm-features previous state)]
(if (= previous features)
state
(assoc state :features features))))
ptk/EffectEvent
(effect [_ state _]
(let [features (get state :features)]
(if (contains? features "render-wasm/v1")
(wasm/initialize true)
(wasm/initialize false))
(log/inf :hint "recomputed features"
:enabled (str/join " " features))))))

View File

@ -902,6 +902,7 @@
toggle-render
(mf/use-fn
(mf/deps profile)
(fn [event]
(dom/stop-propagation event)
(let [renderer (or (-> profile :props :renderer) :svg)

View File

@ -31,6 +31,7 @@
[app.main.ui.workspace.viewport.utils :as utils]
[app.main.worker :as mw]
[app.render-wasm.api :as wasm.api]
[app.render-wasm.wasm :as wasm]
[app.util.debug :as dbg]
[app.util.dom :as dom]
[app.util.globals :as globals]

View File

@ -375,6 +375,7 @@
(vreset! unmounted? true)
(when-let [timeout-id @timeout-id-ref]
(js/clearTimeout timeout-id))
(wasm.api/end-page-transition!)
(wasm.api/clear-canvas)))))
(mf/with-effect [show-text-editor? workspace-editor-state edition]

View File

@ -1075,16 +1075,18 @@
(defn intersect-position-in-shape
[id position]
(let [buffer (uuid/get-u32 id)
result
(h/call wasm/internal-module "_intersect_position_in_shape"
(aget buffer 0)
(aget buffer 1)
(aget buffer 2)
(aget buffer 3)
(:x position)
(:y position))]
(= result 1)))
(if (and wasm/context-initialized? (not @wasm/context-lost?))
(let [buffer (uuid/get-u32 id)
result
(h/call wasm/internal-module "_intersect_position_in_shape"
(aget buffer 0)
(aget buffer 1)
(aget buffer 2)
(aget buffer 3)
(:x position)
(:y position))]
(= result 1))
false))
(def render-finish
(letfn [(do-render []