Skip to content

Fix UI lifecycle leaks and crashes in the Windows app#8436

Open
ZachL111 wants to merge 11 commits into
BasedHardware:mainfrom
ZachL111:win-ui-hooks-fixes
Open

Fix UI lifecycle leaks and crashes in the Windows app#8436
ZachL111 wants to merge 11 commits into
BasedHardware:mainfrom
ZachL111:win-ui-hooks-fixes

Conversation

@ZachL111

@ZachL111 ZachL111 commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes for renderer-side UI lifecycle bugs in the Windows app: effect/timer/stream leaks, two timers that never stop because an effect depends on the wrong value, and a few crashes and stuck-state issues. Found while reading the code; no filed issue, no happy-path behavior change.

What this fixes

  • The recording view never tore down on unmount. All teardown (stopping the mic and system transcription handles and the screen-capture stream) lived only in stop(), so navigating away from a live recording left the microphone hot, the transcription socket open, and the screen stream running. An unmount effect now mirrors stop(). start() also had no in-flight guard, so a rapid double-click opened a second mic session whose handle leaked, and re-picking a screen source leaked the previous stream. Both are now guarded.
  • Conversation playback ran slow during live capture. The Rewind player's 700ms advance effect depended on the whole frames array, but live capture replaces that array about once a second, so every append tore down and recreated the timer, restarting its countdown. It now depends only on whether frames exist.
  • Conversation detail polling never stopped. While a conversation was still processing, the poll effect depended on display, which the poll itself updates every tick, so the interval was rebuilt each tick and its ticks > 20 (about 60s) cap was dead code, polling forever. It now depends on a stable isProcessing flag. The same screen also had a stale-response race where navigating from conversation A to B while A's request was in flight could paint A's data under B; loads are now guarded against a stale id.
  • The error boundary never recovered. After a transient failure (a WebGL context loss on sleep/wake, or a one-time lazy-chunk rejection) it showed its fallback forever, even once new data arrived, until a full app reload. It now resets when its children change.
  • The Rewind thumbnail strip had an unhandled rejection and a stuck scroll flag. A thumbnail whose frame file had been pruned rejected its lazy-load IPC with no catch; and the centering effect could leave its programmatic-scroll flag stuck true (so scrolling the strip no longer moved the cursor) when a width change interrupted the reset. Both are fixed.
  • Two onboarding steps misbehaved on an early exit. The shared permission step's auto-advance setTimeout was not cleared on unmount, so pressing Skip within the one-second window advanced the wizard twice and silently skipped a step. The shortcut-setup step suspended the global summon shortcut while recording and only resumed it on specific paths, so leaving mid-record (Skip) left the hotkey dead for the rest of the session. Both now clean up on unmount.
  • The overlay height tween could hang or never reach its target. Its only degenerate guard was steps <= 1, which is false for both NaN and Infinity, so a non-finite step count either looped forever or returned an empty sequence. It now guards Number.isFinite.
  • Obsidian and Bloomberg were silently excluded from Rewind. The built-in capture exclusion list matched the bare token OBS as a case-insensitive substring against the foreground app and process name, so obsidian matched. OBS Studio is now matched by its process name (obs64 / obs32) instead.

Testing

  • Extended/added vitest tests for the pure-logic fixes (heightTween, rewindExclusions, insightActivity, plus the existing graph/usage suites), verified red to green.
  • npm run typecheck passes for both projects. The React hook and component lifecycle fixes are verified by typecheck and inspection (the project has no React Testing Library / jsdom harness).

PR status check

Touches desktop/windows/src/main/overlay/heightTween.ts, desktop/windows/src/shared/rewindExclusions.ts, and several desktop/windows/src/renderer/src/{lib,hooks,pages,components} files plus tests. I checked the open Windows PRs and none of them modify these files.

Review in cubic

@cubic-dev-ai cubic-dev-ai 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.

1 issue found across 13 files

Confidence score: 3/5

  • In desktop/windows/src/renderer/src/components/ui/ErrorBoundary.tsx, the recovery logic appears tied to children identity, so any parent re-render can trigger retries even when the UI is effectively unchanged; for persistent errors this can create repeated throw/catch cycles and noisy logging in production. Before merging, gate retries on a stable error-reset signal (not raw element identity) and add a regression test that verifies a persistent error does not re-retry on unrelated parent renders.

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread desktop/windows/src/renderer/src/components/ui/ErrorBoundary.tsx
@ZachL111

Copy link
Copy Markdown
Contributor Author

Addressed cubic's P1: the error boundary no longer resets on children identity, which changes on every render and churned throw/catch/log for a persistent error. It now resets on an explicit resetKeys prop, and LazyBrainGraph passes the graph node/edge counts plus shuffleKey. So a transient GPU failure recovers when the data or layout next changes, without retrying on every unrelated re-render. A caller that passes no resetKeys keeps the original contain-and-stay behavior.

@Git-on-my-level Git-on-my-level added needs-maintainer-review Needs a human maintainer to review/approve (e.g. stacked, product, or architecture judgment) security-review Needs security/privacy review labels Jun 27, 2026
@Git-on-my-level

Copy link
Copy Markdown
Collaborator

Thanks for the careful pass on these Windows lifecycle issues. This looks directionally strong to me: the fixes are scoped around stability/privacy cleanup (recording teardown on unmount, preventing duplicate recorder starts, stopping replaced screen streams, bounding polling/timers, handling pruned rewind thumbnails, and avoiding the OBS/Obsidian exclusion trap), and the added targeted tests for the pure helpers are helpful.

I’m not formally approving because this touches recording/screen-capture and Rewind exclusion behavior, so I’d like a human maintainer to make the final call on the privacy-sensitive desktop surfaces before merge. A couple of manual checks would be especially useful: navigate away during an active recording and while picking/re-picking screen capture, verify the global shortcut resumes after leaving shortcut setup mid-record, and confirm Rewind still excludes OBS while no longer excluding Obsidian.

No blocking code issue found in static review from me; this is a positive signal pending maintainer review.

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

Labels

needs-maintainer-review Needs a human maintainer to review/approve (e.g. stacked, product, or architecture judgment) security-review Needs security/privacy review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants