diff --git a/frontend/src/app/render_wasm/api.cljs b/frontend/src/app/render_wasm/api.cljs
index e42afc9e25..aba6fc7970 100644
--- a/frontend/src/app/render_wasm/api.cljs
+++ b/frontend/src/app/render_wasm/api.cljs
@@ -317,46 +317,23 @@
(aget buffer 3))
(set! wasm/internal-frame-id nil))))
-(defn render-preview!
- "Render a lightweight preview without tile caching.
- Used during progressive loading for fast feedback."
- []
- (when (and wasm/context-initialized? (not @wasm/context-lost?))
- (h/call wasm/internal-module "_render_preview")))
-
-
-(defonce pending-render (atom false))
(defonce shapes-loading? (atom false))
(defonce deferred-render? (atom false))
-(defn- register-deferred-render!
- []
- (reset! deferred-render? true))
-
(defn request-render
[_requester]
- (when (and wasm/context-initialized? (not @wasm/context-lost?) (not @wasm/disable-request-render?))
+ (when (and wasm/context-initialized?
+ (not @wasm/context-lost?)
+ (not @wasm/disable-request-render?))
(if @shapes-loading?
- (register-deferred-render!)
- (when-not @pending-render
- (reset! pending-render true)
- (let [frame-id
- (js/requestAnimationFrame
- (fn [ts]
- (reset! pending-render false)
- (set! wasm/internal-frame-id nil)
- (render ts)))]
- (set! wasm/internal-frame-id frame-id))))))
+ (reset! deferred-render? true)
+ (wasm/request-frame render))))
(defn- begin-shapes-loading!
[]
(reset! shapes-loading? true)
- (let [frame-id wasm/internal-frame-id
- was-pending @pending-render]
- (when frame-id
- (js/cancelAnimationFrame frame-id)
- (set! wasm/internal-frame-id nil))
- (reset! pending-render false)
+ (let [was-pending (wasm/frame-requested?)]
+ (wasm/cancel-frame)
(reset! deferred-render? was-pending)))
(defn- end-shapes-loading!
@@ -1708,12 +1685,9 @@
(set! wasm/context-initialized? false)
;; Cancel any pending animation frame to prevent race conditions
- (when wasm/internal-frame-id
- (js/cancelAnimationFrame wasm/internal-frame-id)
- (set! wasm/internal-frame-id nil))
+ (wasm/cancel-frame)
;; Reset render flags to prevent new renders from being scheduled
- (reset! pending-render false)
(reset! shapes-loading? false)
(reset! deferred-render? false)
diff --git a/frontend/src/app/render_wasm/wasm.cljs b/frontend/src/app/render_wasm/wasm.cljs
index 25c2908575..d5d6b9aeaf 100644
--- a/frontend/src/app/render_wasm/wasm.cljs
+++ b/frontend/src/app/render_wasm/wasm.cljs
@@ -10,6 +10,36 @@
(defonce internal-frame-id nil)
(defonce internal-module #js {})
+;; Is a frame requested?
+(defn frame-requested?
+ "Returns true if a frame was requested"
+ []
+ (not (nil? internal-frame-id)))
+
+;; Cancels a frame
+(defn cancel-frame
+ "Cancels the current requested frame"
+ []
+ (when-not (nil? internal-frame-id)
+ (js/cancelAnimationFrame internal-frame-id)
+ (set! internal-frame-id nil)
+ true)
+ false)
+
+(defn create-frame-delegate
+ "Creates a new frame delegate"
+ [f]
+ (fn frame-delegate [timestamp]
+ (let [frame-id internal-frame-id]
+ (set! internal-frame-id nil)
+ (f timestamp frame-id))))
+
+;; Requests a frame
+(defn request-frame
+ "Requests a new frame"
+ [f]
+ (set! internal-frame-id (js/requestAnimationFrame (create-frame-delegate f))))
+
;; Reference to the HTML canvas element.
(defonce canvas nil)
;; Snapshot of the current canvas suitable for `
` overlays.
@@ -29,7 +59,6 @@
;; When we're rendering in a sync way we want to stop the asynchrous `request-render`
(defonce disable-request-render? (atom false))
-
(defonce serializers
#js {:blur-type shared/RawBlurType
:blend-mode shared/RawBlendMode
diff --git a/render-wasm/src/main.rs b/render-wasm/src/main.rs
index ee53f8a98c..962462216e 100644
--- a/render-wasm/src/main.rs
+++ b/render-wasm/src/main.rs
@@ -306,15 +306,6 @@ pub extern "C" fn set_preview_mode(enabled: bool) -> Result<()> {
Ok(())
}
-#[no_mangle]
-#[wasm_error]
-pub extern "C" fn render_preview() -> Result<()> {
- with_state_mut!(state, {
- state.render_preview(performance::get_time());
- });
- Ok(())
-}
-
/// Enter bulk-loading mode. While active, `state.loading` is `true`.
#[no_mangle]
#[wasm_error]
diff --git a/render-wasm/src/render.rs b/render-wasm/src/render.rs
index 897fb733af..c1f08e76e6 100644
--- a/render-wasm/src/render.rs
+++ b/render-wasm/src/render.rs
@@ -1864,33 +1864,7 @@ impl RenderState {
performance::end_measure!("render_from_cache");
performance::end_timed_log!("render_from_cache", _start);
- }
- /// Render a preview of the shapes during loading.
- /// This rebuilds tiles for touched shapes and renders synchronously.
- pub fn render_preview(&mut self, tree: ShapesPoolRef, timestamp: i32) -> Result<()> {
- let _start = performance::begin_timed_log!("render_preview");
- performance::begin_measure!("render_preview");
-
- // Enable fast_mode during preview to skip expensive effects (blur, shadows).
- // Restore the previous state afterward so the final render is full quality.
- let current_fast_mode = self.options.is_fast_mode();
- self.options.set_fast_mode(true);
-
- // Skip tile rebuilding during preview - we'll do it at the end
- // Just rebuild tiles for touched shapes and render synchronously
- self.rebuild_touched_tiles(tree);
-
- // Use the sync render path
- self.start_render_loop(None, tree, timestamp, true)?;
-
- self.options.set_fast_mode(current_fast_mode);
-
- performance::end_measure!("render_preview");
- performance::end_timed_log!("render_preview", _start);
-
- Ok(())
- }
pub fn start_render_loop(
&mut self,
diff --git a/render-wasm/src/state.rs b/render-wasm/src/state.rs
index c624dad43d..0f666fe0b0 100644
--- a/render-wasm/src/state.rs
+++ b/render-wasm/src/state.rs
@@ -253,10 +253,6 @@ impl State {
self.render_state.rebuild_touched_tiles(&self.shapes);
}
- pub fn render_preview(&mut self, timestamp: i32) {
- let _ = self.render_state.render_preview(&self.shapes, timestamp);
- }
-
pub fn rebuild_modifier_tiles(&mut self, ids: Vec) -> Result<()> {
// Index-based storage is safe
self.render_state