45f663b746
A new "Inbox style" toggle in the sidebar filter menu renders the flat recents list as cards: a workspace header line (project when it resolves, else the cwd leaf, else Home) with the age at its right edge, the title grouped with a one-line last-message preview, and a model + size footer. The preview line ships on by default and has its own Show-menu toggle, offered only while Inbox style is active — the one-line row has nowhere to put it. A render variant, deliberately not a grouping — it composes with whichever grouping is active and only the flat recents list opts in; pinned, project, and messaging surfaces keep the one-line row. Spacing hangs off a single --card-gap variable; the title/preview pair is one grouped cell with its own tighter internal gap. The age and kebab sit in flow inside the header line rather than a full-height side column, so title, preview, and footer span the card's entire width. The card's project label reads through a selector that resolves the label string, so tree polls with fresh atom identity repaint only rows whose label actually changed.
41 lines
1.8 KiB
TypeScript
41 lines
1.8 KiB
TypeScript
import { liveSessionProjectId } from '@/app/chat/sidebar/projects/workspace-groups'
|
|
import { pathLeaf } from '@/lib/display-path'
|
|
import type { ProjectInfo, SessionInfo } from '@/types/hermes'
|
|
|
|
/**
|
|
* The PROJECT a session belongs to, as a label for the sidebar card.
|
|
*
|
|
* Resolution order:
|
|
* 1. `liveSessionProjectId` — the same resolver the session COLOR reads, so
|
|
* an explicitly-projected row's name and its inherited tint always agree.
|
|
* Returns an explicit project id, or a repo root for an auto-project.
|
|
* 2. the recorded `git_repo_root` leaf.
|
|
* 3. null (a chat with no workspace at all).
|
|
*
|
|
* Why step 2 exists: `liveSessionProjectId` deliberately refuses to place a
|
|
* worktree that lives OUTSIDE its repo root (`bb/<slug>` beside the checkout
|
|
* rather than in-tree `.worktrees/`), because for LANE MEMBERSHIP a sibling
|
|
* directory genuinely can't be assigned from the row alone. A label has no
|
|
* such ambiguity: the backend already recorded which repo the session belongs
|
|
* to, so we can name it. Without this, most of a sibling-worktree workflow's
|
|
* rows would paint a blank line — and naming the repo is exactly the point of
|
|
* showing the project instead of the cwd (`hermes-agent`, not
|
|
* `hermes-agent-cwd-copy`).
|
|
*
|
|
* This never widens membership — it only names a row that placement leaves
|
|
* unplaced.
|
|
*/
|
|
export function sessionProjectLabel(session: SessionInfo, projects: ProjectInfo[]): null | string {
|
|
const projectId = liveSessionProjectId(session, projects)
|
|
|
|
if (projectId) {
|
|
const explicit = projects.find(project => project.id === projectId)
|
|
|
|
// An explicit project shows its user-given name; an auto-project's id IS
|
|
// its repo root path, so it shows that folder's leaf.
|
|
return (explicit ? explicit.name.trim() : pathLeaf(projectId)) || null
|
|
}
|
|
|
|
return pathLeaf(session.git_repo_root) || null
|
|
}
|