Skip to content

remote viewer: rebuild remote preview on every editor keystroke#11878

Open
ogoffart wants to merge 2 commits into
masterfrom
olivier/remote-viewer
Open

remote viewer: rebuild remote preview on every editor keystroke#11878
ogoffart wants to merge 2 commits into
masterfrom
olivier/remote-viewer

Conversation

@ogoffart
Copy link
Copy Markdown
Member

Previously the remote viewer only recompiled when the LSP sent ShowPreview. SetContents from intermediate keystrokes was cached but never triggered a rebuild. Emit a new ContentsChanged message from the cache update, and have the viewer re-run build_and_show when the changed file is a dependency of the currently shown component (mirroring tools/lsp/preview.rs:set_contents).

Previously the remote viewer only recompiled when the LSP sent ShowPreview.
SetContents from intermediate keystrokes was cached but never triggered a
rebuild. Emit a new ContentsChanged message from the cache update, and have
the viewer re-run build_and_show when the changed file is a dependency of
the currently shown component (mirroring tools/lsp/preview.rs:set_contents).
@ogoffart ogoffart requested review from LeonMatthes and tronical May 27, 2026 14:04
Comment thread tools/viewer/remote.rs
.set_property("message", SharedString::from("Component not found").into())
{
tracing::error!("Failed setting property: {err}");
if let Some(BuildOutcome { new_instance, watch_paths }) = build_and_show(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this will immediately recompile, right?

We should add a debounce delay here, same as for the native preview, so that if I e.g. check out a different branch we don't end up queuing a bunch of recompiles.

Comment thread tools/viewer/remote.rs

connection.send(message).ok();

return Some(BuildOutcome { new_instance: None, watch_paths: None });
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see this causing bugs, as we won't update the dependencies list on error.

So if I try to import a file which does not yet exist, we hit this path.
Then when the new file is added via SetContents, it will not be in the dependencies list and won't trigger a recompile.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even on a build with errors, the type loader should still return the correct list of files to watch. So we should just use the watch paths here I think 🤔

Comment thread tools/viewer/remote.rs

/// Compile `preview_component` (using `file_cache` for the in-memory editor buffer if available)
/// and replace the visible instance with it. Returns `None` only when the host window cannot be
/// reused, which is a fatal condition for the caller.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function mentions that returning None is a fatal condition to the caller, but the call sites don't treat this as a fatal error...

Comment thread tools/viewer/remote.rs
ConnectionMessage::ContentsChanged { url, file_cache } => {
let Some(preview_component) = current_preview.clone() else { continue };
let Ok(path) = url.to_file_path() else { continue };
if !dependencies.contains(&path) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, I think the dependency tracking should not live here. It should live in the live preview crate.

The connection message basically should just say that there are actual changes to the preview and that it needs to be reloaded in the UI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants