Repository navigation
Conversation
There was a problem hiding this comment.
The model logic looks right and the change is limited to the experimental Inbox sidebar. The new tests pass and tsc -b is clean. I couldn't run the app here (the change is in packages/app, and I can only drive the TUI), so could you add before and after screenshots or a short video of the Pinned section, the project menu and grouped Recent?
Public API: unchanged. The only new persisted fields are optional additions to the local InboxState (pinned, project, groupByProject, collapsedProjects), so existing saved state still loads.
Concerns, most important first (details inline):
- With a project filter active, sessions from other projects that need attention or are working are hidden too, so it's easy to miss an approval.
- Pinned and collapsed keys are never cleaned up.
- The
InboxRowstatus markup rewrite isn't needed for this feature; please drop it to keep the diff focused.
| const project = | ||
| options.project && entries.some((entry) => inboxProjectKey(entry) === options.project) ? options.project : undefined | ||
|
|
||
| const scoped = project ? entries.filter((entry) => inboxProjectKey(entry) === project) : entries |
There was a problem hiding this comment.
This filter applies to needs and working as well as Recent. With a project selected, a session in another project that is waiting for approval or input disappears from the sidebar completely, which defeats the point of a "Needs attention" shelf. Could the filter apply only to Recent, Pinned and Archived? Or at least keep needs (and probably working) unscoped, or show how many are hidden outside the filter.
|
|
||
| const pinnedSet = createMemo(() => new Set(state.pinned ?? [])) | ||
|
|
||
| const togglePin = (key: string) => { |
There was a problem hiding this comment.
pinned (and collapsedProjects below) only ever lose a key when the user toggles it back. Keys for deleted sessions, sessions forgotten after a not-found error, or projects that no longer exist stay in persisted storage forever. Please remove a pin when its session is deleted or forgotten (e.g. in the remove and forget paths), or prune both lists against the loaded entries once they have loaded.
| const project = createMemo(() => props.entry.ctx.projects.forSession(props.entry.session)) | ||
| const status = () => props.entry.status | ||
|
|
||
| const nonReadyStatus = (): Exclude<InboxStatus, "ready"> | undefined => { |
There was a problem hiding this comment.
This status rendering refactor (nonReadyStatus plus the re-indented <Show> block) isn't part of pinning or grouping and doesn't change behaviour. Please leave it out so the diff stays about the feature.
|
+1 to this direction — grouped Recent with a project filter is what I want from the desktop sidebar. Context: Windows desktop build, two repos (
+1 on dropping the |
|
Hi! I tested this branch on Windows (built from source, bun run dev:desktop, then Settings → Preferences → Interface → Inbox) with my own sessions across several projects, and it works as described: "Group by project" gives collapsible per-project sections in Recent; the collapsed state and the toggle survive app restarts. From a daily-driver perspective I'd second the review points: with a project filter active it is easy to miss sessions in other projects that are waiting for approval, so keeping Needs attention / Working unscoped (or a hint like "N hidden outside this project") would make this safe to leave on all the time. Happy to re-test on Windows whenever you push an update. Also, this delivers most of what #55446 asks for, in Inbox mode — linking the issue might bring the right eyeballs here. Thanks for working on this! |
Issue for this PR
N/A (feature enhancement for the experimental
SidebarInboxmode)Type of change
What does this PR do?
When working across multiple repositories and worktrees, the
SidebarInbox(Recentlist) mixes sessions from every project into a single flat stream and drops older reference sessions oncesincemoves forward.This PR adds three lightweight navigation controls to
SidebarInbox(packages/app/src/shell/titlebar/inbox.tsxandpackages/app/src/shell/titlebar/inbox-model.ts):Pinned): Sessions can be pinned or unpinned from their context menu (Menu.Context). Pinned sessions stay visible in aPinnedsection aboveRecenteven if their last idle timestamp precedessince, while still moving toNeeds attentionorWorkingwhenever they become active.SidebarInboxlets you scope the inbox to a single project (aggregating worktrees under their parent project root) or switch back toAll projects. If the filtered project no longer has any sessions, the view falls back toAll projectsautomatically instead of stranding the sidebar on an empty filter.Group by projecttoggle in the same menu groupsRecentsessions into collapsible per-project sections ordered by most recent activity, keeping the currently open session visible even when its project group is collapsed (matching theWorkingshelf behavior).How did you verify your code works?
packages/app/src/shell/titlebar/inbox-model.test.tscoveringpartitionInboxEntries(pinned ordering,sincepersistence, busy/archived section precedence, and project filter fallback),inboxProjects(worktree aggregation and duplicate project name disambiguation), andgroupInboxByProject(recency-preserving project grouping):cd packages/app && bun test --conditions=solid --isolate --preload ../ui/test/solid-jsx.ts --preload ./happydom.ts src/shell/titlebar/inbox-model.test.ts --rerun-each 10(40 pass, 0 fail)cd packages/app && bun run typecheck:tsc(0 errors)bun script/lint-changed.ts origin/dev(0 problem(s) in 0 of 4 changed files)Visual
<style> .label { font: 500 8px ui-sans-serif, system-ui, sans-serif; fill: currentColor; } .muted { opacity: 0.45; } .box { fill: none; stroke: currentColor; stroke-width: 1; opacity: 0.35; rx: 4; } .row { fill: currentColor; opacity: 0.14; rx: 2; } .pin { fill: currentColor; opacity: 0.75; rx: 2; } .flow { stroke: currentColor; stroke-width: 1.2; fill: none; stroke-dasharray: 3 3; animation: dash 2.4s linear infinite; opacity: 0.6; } .pulse { animation: fade 3.2s ease-in-out infinite; } @Keyframes dash { to { stroke-dashoffset: -12; } } @Keyframes fade { 0%, 100% { opacity: 0.25; } 50% { opacity: 0.9; } } </style> Flat Recent Pinned Project AChecklist