Repository navigation
fix(desktop): adopt the early window through an explicit state machine - #61800
Conversation
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.
There was a problem hiding this comment.
The change looks sound. I traced both triggers through the diff, and the new state machine covers each path: a bad first windowIds entry, and closing the first window before adoption, whether that happens before the import("./desktop") check or after the layers start. The closed-after-adoption and macOS dock-reopen paths behave as before. early-machine.test.ts and the lifecycle and window tests pass (70/70), and tsc -b is clean. I couldn't reproduce the flash itself, since it needs a packaged Electron launch.
The public API is unchanged: all of this is internal to the desktop main process, and the stored windowIds format stays the same.
No blocking concerns.
Summary
The desktop app shows its first window before the main process loads, then adopts it when the layers restore windows. This handoff lived in a module-level
let pending, a mutableopenExternalswapped on adoption, andtakeEarlyWindow(). This PR moves it to one state machine inpackages/desktop/src/main/windows/early-machine.tsand fixes two bugs.Bugs
windowIdsinopencode.settingsstarts with a bad entry (["", "win-2"],[42, "win-2"],[""])""or a fresh UUID. The registry filters bad ids, sorestore()destroys the visible window and opens a hidden one: the window flashes away. With[""],""is registered as an id.persistedWindowIDs()and agree, so the early window is adoptedapp.quit()runs, butimport("./desktop")still runs.restoreWindows()cannot tell "closed" from "never created" and opens new windows during the quitclosed. The entry module skipsimport("./desktop"), restore plans no window, andApplicationLifecycle.restoreWindowsopens none during a quit (restoresWindows)State
external.openedopens links withshell.openExternalwhilepending, and with the logged handler from the layers onceadopted. This replaces the mutableEarlyWindow.openExternal.restoreEarlyWindow()returns theRestoreStep[]plan.windows/index.tsmaps each step tocreate(id, entry?), andreveal-machine.ts(fix(desktop): reveal hidden windows on a bounded fallback and before recovery dialogs #61743) still starts an adopted windowshown.persistedWindowIDs()inregistry.tsis the one parser of the stored list. It now takesSchema.Json | undefined, the store's own value type.Deleted
let pendingandtakeEarlyWindow()inearly.ts.EarlyWindow.openExternaland its reassignment inwindows/index.ts.Array.isArray(ids) && Predicate.isString(ids[0])id choice.usable/usable.win.destroy()branching inrestore().Deviations from the design
firstWindowID()helper: its only caller inlinespersistedWindowIDs(...)[0] ?? randomUUID().restore.requestedcarries the parsedids, not the raw stored value.restore.requestedinclosedemits no secondquit. The close already quit, and a lifecycle that is stopping finishes the quit on its own.Visual