capture transition snapshot only on page change

This commit is contained in:
Elena Torro 2026-06-10 15:47:49 +02:00
parent d0465e3601
commit 875171ee86

View File

@ -86,10 +86,6 @@
(defonce transition-image-url* (atom nil)) (defonce transition-image-url* (atom nil))
(defonce transition-epoch* (atom 0)) (defonce transition-epoch* (atom 0))
(defonce transition-tiles-handler* (atom nil)) (defonce transition-tiles-handler* (atom nil))
(defonce snapshot-tiles-handler* (atom nil))
(def ^:private snapshot-capture-debounce-ms 250)
(defn initialized? (defn initialized?
"True when the WASM render context is ready to receive design-state "True when the WASM render context is ready to receive design-state
@ -173,31 +169,6 @@
(f)) (f))
#js {:once true})) #js {:once true}))
(defonce ^:private schedule-canvas-snapshot-capture!
(fns/debounce
(fn []
(when (and (initialized?)
(some? wasm/canvas))
(-> (webgl/capture-canvas-snapshot-url)
(p/catch (fn [_] nil)))))
snapshot-capture-debounce-ms))
(defn- start-canvas-snapshot-listener!
[]
(when-let [prev @snapshot-tiles-handler*]
(.removeEventListener ^js ug/document "penpot:wasm:tiles-complete" prev))
(let [handler (fn [_] (schedule-canvas-snapshot-capture!))]
(reset! snapshot-tiles-handler* handler)
(.addEventListener ^js ug/document "penpot:wasm:tiles-complete" handler)))
(defn- stop-canvas-snapshot-listener!
[]
(when-let [prev @snapshot-tiles-handler*]
(.removeEventListener ^js ug/document "penpot:wasm:tiles-complete" prev))
(reset! snapshot-tiles-handler* nil)
(when-let [cancel (unchecked-get schedule-canvas-snapshot-capture! "cancel")]
(cancel)))
(defn text-editor-wasm? (defn text-editor-wasm?
[] []
(or (contains? cf/flags :feature-text-editor-wasm) (or (contains? cf/flags :feature-text-editor-wasm)
@ -224,7 +195,11 @@
(def ^:const DEBOUNCE_DELAY_MS 100) (def ^:const DEBOUNCE_DELAY_MS 100)
(defonce ^:private view-interaction-active? (atom false)) ;; Public so the viewport can gate heavy overlays (flex controls, frame grid,
;; measurements) during pan/zoom — they otherwise re-render + recompute geometry
;; on every viewbox change. Set by `set-view-box` (pan AND zoom), cleared on
;; interaction end.
(defonce view-interaction-active? (atom false))
;; Time budget (ms) per chunk of shape processing before yielding to browser ;; Time budget (ms) per chunk of shape processing before yielding to browser
(def ^:private ^:const CHUNK_TIME_BUDGET_MS 8) (def ^:private ^:const CHUNK_TIME_BUDGET_MS 8)
@ -270,7 +245,6 @@
(def noop-fn (def noop-fn
(constantly nil)) (constantly nil))
;;
(def shape-wrapper-factory nil) (def shape-wrapper-factory nil)
(let [^js ch (js/MessageChannel.)] (let [^js ch (js/MessageChannel.)]
@ -1270,17 +1244,34 @@
(internal-render)))] (internal-render)))]
(fns/debounce do-render DEBOUNCE_DELAY_MS))) (fns/debounce do-render DEBOUNCE_DELAY_MS)))
(defonce ^:private pending-cache-render? (atom false))
(defn- flush-cache-render!
[]
(reset! pending-cache-render? false)
(when (initialized?)
(perf/begin-measure "render-from-cache")
(h/call wasm/internal-module "_render_from_cache" 0)
(render-finish)
(perf/end-measure "render-from-cache")))
(defn set-view-box (defn set-view-box
[zoom vbox] [zoom vbox]
(perf/begin-measure "set-view-box") (perf/begin-measure "set-view-box")
(view-interaction-start!) (view-interaction-start!)
;; `_set_view` is cheap and must run per event so the renderer always has the
;; latest viewbox.
(h/call wasm/internal-module "_set_view" zoom (- (:x vbox)) (- (:y vbox))) (h/call wasm/internal-module "_set_view" zoom (- (:x vbox)) (- (:y vbox)))
(perf/end-measure "set-view-box") (perf/end-measure "set-view-box")
(perf/begin-measure "render-from-cache") ;; Coalesce the cache-preview render to one per animation frame. Wheel/trackpad
(h/call wasm/internal-module "_render_from_cache" 0) ;; momentum (and any batched viewport updates) fire many `set-view-box` calls
(render-finish) ;; per frame; calling `_render_from_cache` synchronously on each piled up to
(perf/end-measure "render-from-cache")) ;; ~17 renders × tens-to-hundreds of ms in a single RAF (1.5s handlers that
;; froze input). One coalesced render per frame uses the latest viewbox.
(when-not @pending-cache-render?
(reset! pending-cache-render? true)
(timers/raf (fn [_] (flush-cache-render!)))))
(defn sync-workspace-local-viewport! (defn sync-workspace-local-viewport!
"Pushes `[:workspace-local :zoom]` and `:vbox` into WASM." "Pushes `[:workspace-local :zoom]` and `:vbox` into WASM."
@ -1981,7 +1972,6 @@
(set! wasm/canvas canvas) (set! wasm/canvas canvas)
(.addEventListener canvas "webglcontextlost" on-webgl-context-lost) (.addEventListener canvas "webglcontextlost" on-webgl-context-lost)
(.addEventListener canvas "webglcontextrestored" on-webgl-context-restored) (.addEventListener canvas "webglcontextrestored" on-webgl-context-restored)
(start-canvas-snapshot-listener!)
(reset! wasm/context-lost? false) (reset! wasm/context-lost? false)
(set! wasm/context-initialized? true))) (set! wasm/context-initialized? true)))
@ -2008,7 +1998,6 @@
(when wasm/canvas (when wasm/canvas
(.removeEventListener wasm/canvas "webglcontextlost" on-webgl-context-lost) (.removeEventListener wasm/canvas "webglcontextlost" on-webgl-context-lost)
(.removeEventListener wasm/canvas "webglcontextrestored" on-webgl-context-restored)) (.removeEventListener wasm/canvas "webglcontextrestored" on-webgl-context-restored))
(stop-canvas-snapshot-listener!)
(when (wasm/module-ready?) (when (wasm/module-ready?)
(free-gpu-resources) (free-gpu-resources)
@ -2083,8 +2072,10 @@
(wasm-gesture/reset-after-wasm-reload!)))) (wasm-gesture/reset-after-wasm-reload!))))
;; Ensure render surfaces are blank before replay to avoid overpainting. ;; Ensure render surfaces are blank before replay to avoid overpainting.
(p/then (fn [_] (h/call wasm/internal-module "_reset_canvas"))) (p/then (fn [_] (h/call wasm/internal-module "_reset_canvas")))
(p/then (fn [_] (replay-font-resources! fonts))) (p/then (fn [_]
(p/then (fn [_] (replay-image-resources! image-resources))) (replay-font-resources! fonts)))
(p/then (fn [_]
(replay-image-resources! image-resources)))
(p/then (p/then
(fn [] (fn []
(initialize-viewport base-objects zoom vbox (initialize-viewport base-objects zoom vbox