From c5d8de9b2d33ff435285d14d3138d310de9e2778 Mon Sep 17 00:00:00 2001 From: brennanb2025 Date: Thu, 30 Apr 2026 10:56:30 -0700 Subject: [PATCH] feat: default sidebar sort to 'recent' instead of alphabetical MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gate the legacy-recent→smart migration on the raw persisted sortBy value rather than the normalized default. Otherwise, flipping the default would sweep fresh installs (no persisted sortBy) into the migration and lock them onto 'smart' via the sticky migrated flag. Co-authored-by: Orca --- src/main/persistence.test.ts | 18 ++++++++++++++++++ src/main/persistence.ts | 8 ++++++-- src/renderer/src/App.tsx | 2 +- src/renderer/src/store/slices/ui.ts | 2 +- src/shared/constants.ts | 2 +- 5 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/main/persistence.test.ts b/src/main/persistence.test.ts index 19383a5274d..2f8081757eb 100644 --- a/src/main/persistence.test.ts +++ b/src/main/persistence.test.ts @@ -433,6 +433,24 @@ describe('Store', () => { expect(store.getUI().sortBy).toBe('recent') }) + it('uses recent as the default sort for a fresh install (no persisted sortBy)', async () => { + // Why: the legacy-recent→smart migration must gate on the *raw* persisted + // value, not the normalized default. Otherwise, changing the default sort + // to 'recent' would cause every fresh install to be mis-migrated to 'smart'. + writeDataFile({ + schemaVersion: 1, + repos: [], + worktreeMeta: {}, + settings: {}, + ui: {}, + githubCache: { pr: {}, issue: {} }, + workspaceSession: {} + }) + + const store = await createStore() + expect(store.getUI().sortBy).toBe('recent') + }) + // ── terminalMacOptionAsAlt migration (issue #903) ─────────────────── it('migrates legacy "true" terminalMacOptionAsAlt to "auto" on first load', async () => { diff --git a/src/main/persistence.ts b/src/main/persistence.ts index f663bd75ca7..6f7da5cf87b 100644 --- a/src/main/persistence.ts +++ b/src/main/persistence.ts @@ -156,9 +156,13 @@ export class Store { // Why: 'recent' used to mean the weighted smart sort. One-shot // migration moves it to 'smart'; the flag prevents re-firing after // a user intentionally selects the new last-activity 'recent' sort. + // Gate on the *raw* persisted value, not the normalized one: the + // default sortBy is now 'recent', so a fresh install with no + // persisted sortBy would otherwise be mis-migrated to 'smart'. ui: (() => { - const sort = normalizeSortBy(parsed.ui?.sortBy) - const migrate = !parsed.ui?._sortBySmartMigrated && sort === 'recent' + const rawSort = parsed.ui?.sortBy + const sort = normalizeSortBy(rawSort) + const migrate = !parsed.ui?._sortBySmartMigrated && rawSort === 'recent' return { ...defaults.ui, ...parsed.ui, diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index 35f6ac28cb1..634de343e1d 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -325,7 +325,7 @@ function App(): React.JSX.Element { sidebarWidth: 280, rightSidebarWidth: 350, groupBy: 'none', - sortBy: 'name', + sortBy: 'recent', showActiveOnly: false, filterRepoIds: [], collapsedGroups: [], diff --git a/src/renderer/src/store/slices/ui.ts b/src/renderer/src/store/slices/ui.ts index 4c87fcfe803..0888ebd0922 100644 --- a/src/renderer/src/store/slices/ui.ts +++ b/src/renderer/src/store/slices/ui.ts @@ -429,7 +429,7 @@ export const createUISlice: StateCreator = (set, get) set({ groupBy: g, collapsedGroups: new Set() }) }, - sortBy: 'name', + sortBy: 'recent', setSortBy: (s) => set({ sortBy: s }), showActiveOnly: false, diff --git a/src/shared/constants.ts b/src/shared/constants.ts index c076d70747c..04657a3bd04 100644 --- a/src/shared/constants.ts +++ b/src/shared/constants.ts @@ -227,7 +227,7 @@ export function getDefaultUIState(): PersistedUIState { sidebarWidth: 280, rightSidebarWidth: 350, groupBy: 'none', - sortBy: 'name', + sortBy: 'recent', showActiveOnly: false, filterRepoIds: [], collapsedGroups: [],