fix(desktop): keep recents when ALL-profiles scope has one profile

Grouping → Profile persists ALL even with a single profile. Recents
filtered that pool against the __all__ sentinel and emptied the list.
Cron and messaging already used filterSessionsByProfileScope; recents
now does too.

Co-authored-by: andyst-dev <150129844+andyst-dev@users.noreply.github.com>
This commit is contained in:
Brooklyn Nicholson
2026-08-19 01:32:26 -05:00
parent b5455fdd16
commit 759d320eeb
3 changed files with 22 additions and 5 deletions
+7 -4
View File
@@ -467,16 +467,19 @@ export function ChatSidebar({
// Profile scope = the "workspace switcher" context. Concrete scope shows only
// that profile's sessions (clean rows, no per-row tags); ALL fans every
// profile in, grouped by profile below. Single-profile users land here with
// scope === their only profile, so nothing is filtered out.
// profile in. Grouped rendering stays gated on `showAllProfiles` (multi-profile
// + ALL) so a single-profile user is never stranded in a grouped view with no
// rail — but the *data* still has to fan in when the persisted scope is ALL
// (Grouping → Profile). Filtering that pool against the `__all__` sentinel
// matches nothing and empties recents + pins.
// Archived rows are excluded from the sessions query, so Archived is a view of
// its own set rather than a filter over this one — a flat list of archived
// rows, no project tree, no date or status dividers.
const scopedSessions = useMemo(() => {
const pool = showArchived ? archivedSessions : sessions
return showAllProfiles ? pool : pool.filter(s => normalizeProfileKey(s.profile) === profileScope)
}, [sessions, archivedSessions, showArchived, showAllProfiles, profileScope])
return filterSessionsByProfileScope(pool, profileScope)
}, [sessions, archivedSessions, showArchived, profileScope])
// One predicate for the status/project filters, so the flat list and the
// project lanes narrow by the same rule. A project lane holds rows the loaded
@@ -27,4 +27,12 @@ describe('filterSessionsByProfileScope', () => {
expect(filterSessionsByProfileScope(rows, ALL_PROFILES)).toBe(rows)
})
it('does not empty ALL scope when every row is one profile', () => {
// Grouping → Profile persists ALL even with one profile. Filtering
// against the `__all__` sentinel would empty recents and pins.
const rows = [row('a', 'default'), row('b', 'default'), row('c', 'default')]
expect(filterSessionsByProfileScope(rows, ALL_PROFILES)).toBe(rows)
})
})
@@ -1,7 +1,13 @@
import { ALL_PROFILES, normalizeProfileKey } from '@/store/profile'
import type { SessionInfo } from '@/types/hermes'
/** Return the sessions visible in one sidebar profile scope, or the original unified list for All profiles. */
/**
* Sessions visible in one sidebar profile scope.
*
* ALL (`__all__`) returns the caller's list unchanged — including the
* single-profile case, where Grouping → Profile persists that sentinel
* while grouped rendering stays off. Never filter against `__all__`.
*/
export function filterSessionsByProfileScope(sessions: SessionInfo[], profileScope: string): SessionInfo[] {
if (profileScope === ALL_PROFILES) {
return sessions