perf: unmount idle Marketplace/Admin/Docs/ApiTest views#10
Merged
Conversation
Classic layout kept every center view mounted via a CSS hidden class instead of conditionally rendering, so each view's own polling (incl. cloud-touching calls in Marketplace) ran forever in the background regardless of which tab was visible, and their state/DOM never got released, growing memory over a long session. Mount only the active view for these four, matching the pattern FocusShell already uses correctly. Widgets/Terminal/AI Chat stay always-mounted (home view / live sessions that must survive switching away and back).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
hiddenclass — so a view's own background polling ran forever regardless of which tab was actually visible, and its state/DOM never got released across a long session.Marketplace,Admin,Docs,ApiTestto conditional mounting (mount only the active view), matching the patternFocusShellalready uses correctly forlayoutMode: "focus".Problem
web/src/os/Desktop.tsx's Classic-mode block rendered every center view unconditionally, hiding inactive ones via ahiddenclass rather than not rendering them.MarketplaceAppruns three separatesetIntervals (including cloud-touching calls) andAdminAppruns a 15s poll — both continuously, even when the user is on the Widgets or Terminal tab and never looks at Marketplace/Admin again for the rest of the session.Solution
<div className={... ${view === "x" ? "" : "hidden"}}>wrapper with{view === "x" && (<div ...>...)}— React unmounts the view when its condition goes false, running its effect cleanup and releasing its state/DOM.Widgets,CenterTerminal,AiChatAppare untouched and stay always-mounted: Widgets is the default/home view, and Terminal/AI Chat hold live session state that must survive switching away and back.layoutMode: "focus"(already correct), or any mobile-specific layout (none exists in this codebase today).setIntervalin the affected views already has a matchingclearIntervalin its effect cleanup, so React's unmount lifecycle stops them automatically — this required no changes toMarketplaceApp.tsx/AdminApp.tsxthemselves.Changed files
web/src/os/Desktop.tsxNo conflict with other open PRs
This only touches
web/src/os/Desktop.tsx, which none of #6, #7, #8, or #9 touch — safe to merge in any order relative to them.Test plan
tsc -b --noEmitandoxlintpass on the changed filesetIntervalinMarketplaceApp/AdminApphas a matchingclearIntervalin the same effect's cleanup, so unmounting reliably stops them;DocsApp/ApiTestApphave no timers to clean up