Skip to content

fix(ui): preserve Studio layer controls across scene updates - #282

Merged
hyperb1iss merged 1 commit into
mainfrom
nova/studio-control-stability
Sep 10, 2026
Merged

fix(ui): preserve Studio layer controls across scene updates#282
hyperb1iss merged 1 commit into
mainfrom
nova/studio-control-stability

Conversation

@hyperb1iss

@hyperb1iss hyperb1iss commented Sep 10, 2026

Copy link
Copy Markdown
Owner

What this changes

Studio keeps effect controls mounted when their values change, preserving scroll position and keyboard focus. Layer replacements reuse cached effect schemas and retain the expanded Transform & Color section, so opacity and advanced settings no longer collapse the inspector while loading.

Why

A single control edit refreshed unrelated face and primary-effect data, then rebuilt the layer controls. In the live Neon Clock inspector, changing Glow moved the scroll position from 650px to 424px and triggered eight requests. The corrected control path keeps the same focused input at 650px and sends two requests: the patch and one authoritative scene read.

Rows follow stable layer/source identity and read current values and revisions reactively. Pending and in-flight edits take precedence over server snapshots; failed writes explicitly restore canonical values. Event epochs preserve invalidations across batched notifications while avoiding duplicate refreshes. Replacements still retire the old write authority.

Verification

  • Added or updated tests: five browser regressions plus Rust identity, queue, and event tests.
  • Added or updated docs: not applicable.
  • just verify passes locally, including allocation contracts.
  • just deny: not applicable; dependencies and licenses unchanged.
  • Standalone UI tests (473 passed) and just ui-build pass.
  • SDK checks: not applicable; SDK source unchanged.
  • Python checks: not applicable.
  • Compatibility database checks: not applicable.
  • Documentation build and link checks: not applicable.
  • Packaging syntax checks: not applicable.
  • Full Servo e2e build/suite: not run; the targeted five-case browser suite passes against the production UI artifact with all test writes mocked or blocked.
  • CPU smoke build: not applicable.
  • Live Neon Clock check with agent-browser: stable 650px scroll, preserved input identity/focus, requests reduced from eight to two. The temporary Glow change was restored.

Also passed: workspace type-check, strict UI library Clippy, and independent adversarial review. The extra all-target UI Clippy check hits an existing Tauri test-module ordering warning, reproduced on untouched main and tracked separately.

Notes for reviewers

Preview frame rates and debounce intervals are unchanged. The measured improvement is fewer requests and preserved editor state; this PR does not claim to resolve the browser's overall CPU usage. A separate disclosure-preference edge after reordering is tracked for follow-up.

Summary by CodeRabbit

  • New Features

    • Layer editor controls now update live while preserving focus, scroll position, and expanded sections.
    • Replacing a layer source automatically targets the new source’s controls.
    • Remote updates remain synchronized without discarding unsubmitted local edits.
  • Bug Fixes

    • Rejected or failed control changes now restore the correct saved values.
    • Scene and effect updates refresh more accurately, avoiding unnecessary reloads.
    • Layer changes retain the correct identity and revision during editing.

Keep effect widgets mounted while authoritative scene values refresh so
edits retain scroll position and focus. Reconcile snapshots beneath
pending writes, restore rejected values, and cache schemas across layer
replacements without retaining retired mutation targets.

Coalesce scene invalidations and avoid unrelated face and primary-effect
reloads. Cover control edits, remote updates, replacement revisions,
failed writes, and advanced-panel scrolling with browser regressions.

Co-Authored-By: Nova (Codex) <noreply@openai.com>
@coderabbitai

coderabbitai Bot commented Sep 10, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: ccd43061-75eb-46c4-9476-f63b942acfad

📥 Commits

Reviewing files that changed from the base of the PR and between 5902542 and e5612b9.

📒 Files selected for processing (12)
  • crates/hypercolor-ui/src/app.rs
  • crates/hypercolor-ui/src/components/layer_panel/controls.rs
  • crates/hypercolor-ui/src/components/layer_panel/mod.rs
  • crates/hypercolor-ui/src/components/layer_panel/row.rs
  • crates/hypercolor-ui/src/control_session.rs
  • crates/hypercolor-ui/src/optimistic_controls.rs
  • crates/hypercolor-ui/src/pages/studio/mod.rs
  • crates/hypercolor-ui/src/ws/messages.rs
  • crates/hypercolor-ui/src/zones.rs
  • crates/hypercolor-ui/tests/layer_panel_tests.rs
  • crates/hypercolor-ui/tests/ws_messages_tests.rs
  • e2e/tests/studio-controls.spec.mjs

📝 Walkthrough

Walkthrough

The PR adds generation-aware scene refresh tracking, optimistic control reconciliation, and reactive layer-panel rendering. It preserves layer controls across value updates, refreshes effect metadata when sources change, and adds unit and Playwright coverage for control-edit behavior.

Changes

Studio control consistency

Layer / File(s) Summary
Scene refresh generation tracking
crates/hypercolor-ui/src/ws/messages.rs, crates/hypercolor-ui/src/zones.rs, crates/hypercolor-ui/src/pages/studio/mod.rs, crates/hypercolor-ui/src/app.rs, crates/hypercolor-ui/tests/ws_messages_tests.rs
Scene events now track scene, structural, active-effect, and per-zone control generations. Refresh consumers use these values to avoid repeated scene and face loads while selecting effect refreshes by target zone.
Optimistic control reconciliation
crates/hypercolor-ui/src/optimistic_controls.rs, crates/hypercolor-ui/src/control_session.rs
The mutation queue retains in-flight batches and merges in-flight and pending values with server snapshots. Failure recovery clears in-flight state and accepts authoritative values.
Reactive layer panel rendering
crates/hypercolor-ui/src/components/layer_panel/mod.rs, crates/hypercolor-ui/src/components/layer_panel/row.rs, crates/hypercolor-ui/src/components/layer_panel/controls.rs, crates/hypercolor-ui/tests/layer_panel_tests.rs
Layer rows and controls now use reactive signals. Keyed mount identities preserve controls and disclosures across value changes while replacing rows when layer sources or identities change. Effect details use an epoch-aware cache.
Studio control interaction validation
e2e/tests/studio-controls.spec.mjs
Playwright tests cover focus and scroll preservation, revision-aware layer updates, source replacement, rejected patches, remote snapshots, and disclosure state.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant LayerPanel
  participant LayerRow
  participant ControlPatchSession
  participant SceneAPI
  participant WebSocket
  LayerPanel->>LayerRow: provide reactive layer and revision
  LayerRow->>ControlPatchSession: submit control mutation
  ControlPatchSession->>SceneAPI: patch layer controls
  SceneAPI->>WebSocket: emit scene control events
  WebSocket->>LayerPanel: update scene values and generations
  LayerPanel->>LayerRow: reconcile values without remounting
Loading
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands.

@hyperb1iss
hyperb1iss merged commit d8f10d4 into main Sep 10, 2026
23 of 24 checks passed
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.

1 participant