feat(desktop): the sidebar offers Restart to update above the account row

Merged
DA
8d ago
+228-21

What

Dean: "Let's add an update button somewhere on the left sidebar wherever it makes sense so that it's not hidden behind settings."

Until now, a newer release only showed as a dot on the account row's gear, and the controls were in Settings ▸ Updates. Now the left sidebar shows an update control just above the account row, the same spot Codex, Cursor and Linear use. It only appears when there's something to do:

Update stateSidebar
Downloaded, waiting on a restartRestart to update: a row tinted in the same working blue as the old dot (calm, not the accent fill), with a new arrow-up-in-a-circle glyph. Tooltip: "Luke 0.11.0 is ready".
DownloadingA quiet line, nothing to press: "Downloading update… 42%" (no percentage if progress isn't reported yet), with role="status".
Up to date, never checked, checking, just updatedNothing
FailedNothing. This stays in Settings, and the gear's dot still points there. The update service has no retry act (Settings' fallback is "Download" from the releases page), so I didn't invent one.
A build that can't install itself (unsigned/dev)Nothing. Settings' "Download" covers it.
  • One code path. Pressing the row calls UpdateControl.onInstall, the same ACT_KIND.UPDATE_INSTALL that Settings' "Restart to update" button sends. Whether the sidebar shows a control comes from updateRow, the same reading the Settings row uses, so the two can't disagree.
  • Gear dot: dropped while the sidebar row is showing, so the news isn't shown twice. The dot still marks a failed update (a newer version is known but couldn't be installed). The sidebar now works this out from updates itself, so the shell no longer passes settingsNote.
  • Collapsed sidebar: no title-bar control, as asked. The sidebar row comes back when you expand it.
  • Menu bar / shortcuts: the app has no "Check for Updates…" or "Restart to Update" menu item, so nothing was added.
  • Fixture: any fixture run (--fixture, so every evidence.sh capture) stages a release one minor version past the running build, downloaded and waiting on its restart (fixtureUpdate in update-row.ts). That puts the sidebar row in the evidence. Settings' Updates row in a fixture run reads the same staged state.

Screenshots (headless Chrome, the real DesktopShell and stylesheet, synthetic data)

Ready, light / dark:


Downloading (dark) and failed (light; the gear's dot is the only signal):


Tests

  • desktop-sidebar.test.ts (through DesktopSidebar):
    • A downloaded release draws Restart to update just above the account row, and pressing it runs the install act.
    • A downloading release is a status line with its rounded percentage and no button.
    • Up to date, checking, or unable to install in place: no update control.
    • The gear's dot stands down while the sidebar shows the release, and still marks a failed one with the update row's words.
  • update-row.test.ts: a fixture run stages a newer release waiting on its restart, and a live run keeps the updater's own answer.

./scripts/check.sh exits 0.

CI could not verify the Mac UI, and ./scripts/verify.sh was not run (Linux cloud VM). The screenshots are headless Chrome, not Electron. LUKE-159 is the manual Mac pass.

🤖 Generated with Claude Code