fix(app): seed launch at login again after reinstalling the tray

The Run value was seeded once per machine. Uninstalling the desktop app
removes the tray and, with it, the Run value; reinstalling put the tray
back but the seeded flag survived in the companion settings, so launch
at login was silently off afterwards. A tray app the current launch has
just installed now seeds the value as a first run does.
This commit is contained in:
iamtoruk 2026-09-03 00:01:34 -07:00
parent f03a3133e2
commit 7d4c86bc82
2 changed files with 32 additions and 5 deletions

View file

@ -398,6 +398,25 @@ describe('MenubarCompanion', () => {
expect(JSON.parse(readFileSync(dockPrefsPath(home), 'utf8'))).toEqual({ enabled: true, scale: 1.2 })
})
it('seeds launch at login again after this app reinstalls the tray', async () => {
stageMsi()
await new MenubarCompanion(deps()).bootstrap()
expect(regCalls).toEqual([runKeyArgs(true, TRAY_EXE)])
// The tray app went away with an uninstall that took its Run value along; the exe is
// back only once the CLI has installed it again. Seeded once is no reason to leave a
// freshly placed tray app without launch at login.
regCalls = []
present.delete(TRAY_EXE)
installResult = result({ action: 'installed' })
await new MenubarCompanion(deps({
exists: (path: string) => (path === TRAY_EXE ? cliCalls.length > 1 : present.has(path)),
})).bootstrap()
expect(cliCalls).toHaveLength(2)
expect(regCalls).toEqual([runKeyArgs(true, TRAY_EXE)])
})
it('leaves an existing launch-at-login value alone', async () => {
stageMsi()
existingRunKey = `"${TRAY_EXE}"`

View file

@ -581,20 +581,27 @@ export class MenubarCompanion {
this.save({ trayExePath: exePath })
if (firstRun && existingDock === undefined && this.settings.sidebar) this.applyDockSetting(true)
await this.reconcileRunKey(firstRun)
// A tray app this launch just put on the machine has no Run value yet: the previous
// one's uninstall took it, and that was the installer's doing, not the person's choice.
await this.reconcileRunKey(firstRun || this.placedTray)
this.placedTray = false
this.launch(exePath, ['--reload-settings'], this.launchEnv())
}
/** True between an install that placed a tray app and the seeding that follows it. */
private placedTray = false
/**
* Launch at login, without overriding a choice. An existing Run value was written by the
* tray app's own toggle or by an earlier launch of this one, so it is left alone; only a
* first run seeds one. The exception is a value pointing at a file that is not there, which
* is not a preference but the old wrong path, and would fail silently at every login.
* first run, or a tray app freshly installed by this launch, seeds one. The exception is a
* value pointing at a file that is not there, which is not a preference but the old wrong
* path, and would fail silently at every login.
*/
private async reconcileRunKey(firstRun: boolean): Promise<void> {
private async reconcileRunKey(seed: boolean): Promise<void> {
const existing = await this.existingRunKey()
if (existing === null) {
if (firstRun) await this.setRunKey(true)
if (seed) await this.setRunKey(true)
return
}
if (!this.exists(runKeyTarget(existing))) await this.setRunKey(true)
@ -674,6 +681,7 @@ export class MenubarCompanion {
return null
}
const exePath = parsed.exePath || this.settings.trayExePath
this.placedTray = parsed.action === 'installed'
this.save({
installDeclinedVersion: null,
// What is actually on disk now, which is the staged version except under