M19: Move sidebarCollapsed from localStorage to electron-store

Sidebar collapsed state was an orphan in localStorage -- not backed up,
lost on portable installs, and inconsistent with every other preference.

Added sidebarCollapsed: boolean to the Settings type and DEFAULT_SETTINGS,
wired it through applySettings' boolean branch, and updated the renderer
store / main.tsx mock defaults. App.tsx now drives the toggle via
updateSettings({ sidebarCollapsed }) instead of localStorage.

typecheck + 242 tests + eslint green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-30 14:04:30 -04:00
parent 63a327a31c
commit 4e3b141d6d
6 changed files with 9 additions and 10 deletions
+1 -1
View File
@@ -277,7 +277,7 @@ token system + shared primitives (UI/SIMP — high value, larger effort) · i18n
- [ ] **M18 — Audio "quality" presets hard-code MP3.** `QUALITY_OPTIONS.audio` labels ("Best
(MP3)", "320 kbps") are shown even when `downloadOptions.audioFormat` is opus/flac/wav, so the
label contradicts the actual output format; `--audio-quality` is also meaningless for lossless.
- [ ] **M19 — Sidebar-collapsed pref uses `localStorage`** while every other preference uses
- [x] **M19 — Sidebar-collapsed pref uses `localStorage`** while every other preference uses
electron-store — won't back up/restore and is lost in the portable build across machines.
- [ ] **M20 — ProgressBar / native `<select>` accessibility.** QueueItem/DownloadsView
`ProgressBar`s have no accessible name; several `Select`s carry both a `<Field label>` and an
+2
View File
@@ -64,6 +64,7 @@ const DEFAULTS: Settings = {
hasCompletedOnboarding: false,
minimizeToTray: false,
launchAtStartup: false,
sidebarCollapsed: false,
updateToken: ''
}
@@ -335,6 +336,7 @@ function applySettings(s: Store<Settings>, partial: Partial<Settings>): void {
case 'autoDownloadNew':
case 'hasCompletedOnboarding':
case 'minimizeToTray':
case 'sidebarCollapsed':
if (typeof value === 'boolean') s.set(key, value)
break
case 'launchAtStartup':
+2 -9
View File
@@ -130,16 +130,9 @@ function App(): React.JSX.Element {
window.api?.getAppVersion?.().then(setVersion).catch(logError('getAppVersion'))
}, [])
// Sidebar collapse, persisted across launches in localStorage.
const [collapsed, setCollapsed] = useState(
() => localStorage.getItem('aerofetch.sidebarCollapsed') === '1'
)
const collapsed = useSettings((s) => s.sidebarCollapsed)
function toggleCollapsed(): void {
setCollapsed((c) => {
const next = !c
localStorage.setItem('aerofetch.sidebarCollapsed', next ? '1' : '0')
return next
})
updateSettings({ sidebarCollapsed: !collapsed })
}
// Gate on `loaded` so a returning user's real settings never get clobbered
// by a one-frame flash of the (default-false) onboarding state.
+1
View File
@@ -42,6 +42,7 @@ if (import.meta.env.DEV && !window.api) {
hasCompletedOnboarding: true,
minimizeToTray: false,
launchAtStartup: false,
sidebarCollapsed: false,
updateToken: ''
}
// Stands in for the cookies.txt file's mtime — lets the Cookies card's
+1
View File
@@ -40,6 +40,7 @@ const FALLBACK: Settings = {
hasCompletedOnboarding: PREVIEW,
minimizeToTray: false,
launchAtStartup: false,
sidebarCollapsed: false,
updateToken: ''
}
+2
View File
@@ -553,6 +553,8 @@ export interface Settings {
minimizeToTray: boolean
/** launch AeroFetch automatically when the user signs in to Windows */
launchAtStartup: boolean
/** whether the navigation sidebar is collapsed to icon-only mode */
sidebarCollapsed: boolean
/**
* Optional Gitea access token for the in-app updater. Empty = anonymous (works
* only where the release repo allows anonymous access). When the release repo