Skip to content

refactor: simulator panel — floating device controls, lighter chrome#260

Merged
zvadaadam merged 2 commits into
mainfrom
adam-zvada/eclipse
Apr 30, 2026
Merged

refactor: simulator panel — floating device controls, lighter chrome#260
zvadaadam merged 2 commits into
mainfrom
adam-zvada/eclipse

Conversation

@zvadaadam

@zvadaadam zvadaadam commented Apr 30, 2026

Copy link
Copy Markdown
Owner

Summary

  • Drop redundant notch overlay in the generic device frame — the MJPEG stream already shows the real Dynamic Island, so the bg-bg-base pill on top was just covering it.
  • Move Home + Screenshot to a floating pill centered above the device frame (only while streaming), so device-level actions read separately from workspace-level controls (Build & Run, Stop).
  • Reduce complexity in the simulator feature: hoist a single TooltipProvider, consolidate the two near-identical scoring functions, remove the dead getStreamInfo recovery path (the stub always returned null since recovery moved to sim:streamReady), drop the showCameraDot flag (it was just isTablet rebranded), and extract withoutWorkspace() so the three duplicated idle-deletion blocks in the store collapse to one.

Net: 110 lines removed, 46 added across 4 files in the simulator feature (plus a one-line .gitignore addition for .device-use/).

Test plan

  • Boot a simulator — the white pill is gone, real Dynamic Island shows through cleanly
  • Confirm Home + Screenshot pill appears above the frame only while streaming
  • Confirm Build & Run / Stop still live in the top toolbar
  • Switch workspaces with a sim booted in another workspace — auto-selection still avoids the in-use UDID
  • Trigger a build — log drawer still works; tooltips still appear
  • ⌘⇧S keyboard shortcut for screenshot still works

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Simulator stream recovery now relies on backend event notifications instead of periodic checks, improving reliability.
  • Refactor

    • Centralized idle-state handling for more consistent simulator behavior.
    • Simplified device frame rendering and bezel handling.
    • Adjusted simulator scoring to separate device-type weighting from booted-instance bonuses.

- Drop redundant Dynamic Island white pill from GenericDeviceFrame —
  the MJPEG stream already shows the real notch.
- Move Home + Screenshot out of the toolbar into a floating pill
  centered above the device frame (only visible while streaming) so
  device-level actions read separately from workspace controls.
- Hoist a single TooltipProvider over the whole panel (was duplicated).
- Consolidate scoreSimulator / scoreSimulatorByType — Booted bonus is
  composed onto the base score instead of duplicating the function.
- Remove dead getStreamInfo path: the service stub always returned null
  since recovery moved to the sim:streamReady event. Drop the stub and
  the dead branch in the mount effect; keep the booting-stuck reset.
- Extract withoutWorkspace() helper in the store — three identical
  idle-deletion blocks collapse to one.
- Drop showCameraDot flag from GenericShellSpec (it was just isTablet
  rebranded) and inline the conditional render.
- Add .device-use/ to gitignore.

Net: 110 lines removed, 46 added.
@coderabbitai

coderabbitai Bot commented Apr 30, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e89ce197-eacb-447f-9847-c015c723f992

📥 Commits

Reviewing files that changed from the base of the PR and between 245d6da and 27bda64.

📒 Files selected for processing (1)
  • apps/web/src/features/simulator/ui/SimulatorPanel.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/src/features/simulator/ui/SimulatorPanel.tsx

📝 Walkthrough

Walkthrough

Refactors simulator stream initialization and state management: removes polling-based stream lookup, centralizes idle workspace cleanup in the store, simplifies fallback device frame rendering, and splits/refactors simulator scoring and UI composition.

Changes

Cohort / File(s) Summary
VCS ignore
/.gitignore
Add .device-use/ to ignore local device-use artifacts.
Simulator Service API
apps/web/src/features/simulator/api/simulator.service.ts
Removed getStreamInfo() method (was always resolving to null); stream readiness is now emitted via backend sim:streamReady events.
Simulator Store
apps/web/src/features/simulator/store.ts
Centralized idle/workspace removal via a new withoutWorkspace helper; replaced duplicated deletion logic in dispatch, setSession, and clearWorkspaceSession.
Simulator UI — Device Frame
apps/web/src/features/simulator/ui/DeviceFrame.tsx
Removed showDynamicIsland and showCameraDot from GenericShellSpec; compute tablet detection from deviceType; compacted screenInsets definitions without behavior change.
Simulator UI — Panel & Scoring
apps/web/src/features/simulator/ui/SimulatorPanel.tsx
Refactored scoring into scoreSimulatorByType and scoreSimulator (reintroduced Booted bonus via wrapper); removed mount/workspace probing that used simulatorService.getStreamInfo; adjusted JSX wrapper structure and tooltip/provider placement.
sequenceDiagram
  participant UI as "SimulatorPanel (Client)"
  participant Store as "Zustand Store"
  participant Backend as "Simulator Backend"
  participant Service as "simulatorService"

  UI->>Service: startStreaming(workspaceId)
  Service->>Backend: request/start stream
  Backend-->>UI: emit sim:streamReady(workspaceId, streamUrl)
  UI->>Store: update session phase -> "streaming" with streamUrl
  Store-->>UI: state change triggers re-render (viewport shows stream)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A tiny hop, a clever tweak,
Streams now whisper when they're sleek,
Idle crumbs swept with one neat sweep,
Frames trimmed light, the toolbox deep,
I nibble bugs and bounce—rejoice!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly summarizes the main refactoring effort: moving device controls to a floating UI and simplifying the chrome. It accurately reflects the primary visual and architectural changes across the simulator panel.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch adam-zvada/eclipse

Review rate limit: 2/5 reviews remaining, refill in 25 minutes and 12 seconds.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/features/simulator/ui/SimulatorPanel.tsx`:
- Around line 756-769: The Home and Screenshot icon-only buttons lack accessible
names; update the Button elements that call handleHome and handleScreenshot (the
Button components wrapped by TooltipTrigger) to include descriptive aria-label
attributes (e.g., aria-label="Home" and aria-label="Screenshot") so screen
readers can identify the controls while keeping the existing
Tooltip/TooltipContent intact.
- Around line 196-200: The current recovery unconditionally clears a "booting"
session when layout.simulatorUdid exists, which can race with legitimate boots;
change this to track in-flight boot attempts (e.g., maintain an in-memory
set/map keyed by workspaceId or udid) and only call
simulatorStoreActions.clearWorkspaceSession(workspaceId) if there is no active
in-flight boot for that workspace/udid, updating the tracker when a boot is
initiated and when it completes/fails; also add the same add/remove bookkeeping
around the auto-reconnect path that calls startStreaming(...) so both boot entry
points consult the same in-flight tracker before clearing state.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5c36e654-b3e3-4206-a65f-45513895c9e8

📥 Commits

Reviewing files that changed from the base of the PR and between e937a50 and 245d6da.

📒 Files selected for processing (5)
  • .gitignore
  • apps/web/src/features/simulator/api/simulator.service.ts
  • apps/web/src/features/simulator/store.ts
  • apps/web/src/features/simulator/ui/DeviceFrame.tsx
  • apps/web/src/features/simulator/ui/SimulatorPanel.tsx
💤 Files with no reviewable changes (1)
  • apps/web/src/features/simulator/api/simulator.service.ts

Comment thread apps/web/src/features/simulator/ui/SimulatorPanel.tsx Outdated
Comment thread apps/web/src/features/simulator/ui/SimulatorPanel.tsx Outdated
- Remove the booting-recovery clear in the workspace-switch effect.
  The store is in-memory only (zustand, not persisted) so "stuck
  booting from app crash" can't actually happen — restart resets the
  store. The boot promise has a 30s timeout that already transitions
  to error on failure. Keeping the clear could race a real in-flight
  boot if the user revisits the workspace before STREAM_READY arrives.

- Add explicit aria-label to the Home and Screenshot icon buttons in
  the floating device-control pill (previously relied on tooltip text
  alone).
@zvadaadam

Copy link
Copy Markdown
Owner Author

Greenlight — Round 1

Fixed (2):

  • Major: removed the racy boot-recovery clear in the workspace-switch effect — the store is in-memory zustand so the "stuck booting" recovery scenario it claimed to handle can't actually happen, and the boot promise's own 30s timeout transitions to error on failure
  • Minor: added aria-label="Home" and aria-label="Screenshot" to the icon-only buttons in the new floating pill

Disagreed (0) | Deferred (0)

Pushed in 27bda64.

@zvadaadam zvadaadam merged commit 7d5d3f5 into main Apr 30, 2026
4 checks passed
@zvadaadam zvadaadam deleted the adam-zvada/eclipse branch April 30, 2026 13:12
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