Skip to content

feat(web): add combined session list filters - #1772

Open
techotaku39 wants to merge 2 commits into
tiann:mainfrom
techotaku39:investigate/draft-session-filter
Open

feat(web): add combined session list filters#1772
techotaku39 wants to merge 2 commits into
tiann:mainfrom
techotaku39:investigate/draft-session-filter

Conversation

@techotaku39

Copy link
Copy Markdown
Contributor

Summary

  • Add a namespace-scoped batch endpoint for retrieving sessions with scratchlist entries.
  • Replace the unread-only control with combined unread, date, and scratchlist filters.
  • Allow multiple session filters to be selected together using intersection semantics.
  • Unify session and machine filtering in the mobile filter menu.
  • Improve responsive menu sizing, viewport clamping, and date-picker positioning.
  • Add regression tests and update API, Web, and Hub documentation.

Problem / Motivation

Previously, filtering was split across separate controls and did not provide a shared multi-select model. Users could not directly build combined queries such as “unread sessions updated within a date range that also contain scratchlist entries”, or consistently combine session criteria with machine filtering from one filter surface.

Scratchlist data was already persisted in the Hub and synchronized across clients, but the session list had no way to identify sessions containing scratchlist entries without opening them individually. Long date ranges and filter menus also needed more reliable positioning on narrow mobile viewports.

Implementation Notes

  • Added GET /api/sessions/scratchlist-status, returning distinct scratchlist-bearing session IDs within the authenticated namespace.
  • Added Web API client, query hook, cache key, and SSE invalidation support.
  • Added independent unread, date, and scratchlist filter state with AND/intersection filtering.
  • Kept the selected session visible while applying filters.
  • Unified session and machine filters in the mobile menu while preserving the desktop machine filter bar.
  • Made filter menus size to their longest content and clamp only when viewport space is insufficient.
  • Centered the date picker within the session-list panel.
  • No new dependencies or database migration were introduced.

Validation

  • bun run typecheck — passed for CLI, Web, Hub, and Relay.
  • bun run --cwd hub test -- src/web/routes/sessions-scratchlist.test.ts src/store/migration-v12.test.ts — 38/38 passed.
  • Focused Web tests for session filters, machine filters, date filtering, and directory actions — 70/70 passed.
  • Final machine-filter label regression tests — 32/32 passed.
  • .\scripts\Invoke-HapiTaskPlaywright.ps1 -Name investigate-draft-session-filter -Suite Root e2e/terminal-wrap-fidelity.spec.ts — 2/2 passed.
  • Real browser acceptance passed for date-picker centering at 393px and 1024px, dual-runner machine filtering, and Chinese UI labels.
  • bun run build — passed.

Related Issues

None

AI Disclosure

OpenAI Codex (GPT-5.6)

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • [Major] Scratchlist status is omitted from unreplayable-reconnect resync - the new independent cache at web/src/hooks/queries/useScratchlistSessionIds.ts:13 is invalidated for live scratchlist patches, but web/src/App.tsx:256 only invalidates the sessions list and session-detail caches when resumed=false. If a scratchlist is created or deleted during an SSE gap that cannot be replayed, the active scratchlist filter can continue using old IDs; staleTime marks data stale but does not poll.
    Suggested fix:
    const invalidations = [
        queryClient.invalidateQueries({ queryKey: queryKeys.sessions }),
        queryClient.invalidateQueries({ queryKey: queryKeys.scratchlistSessionIds }),
        queryClient.invalidateQueries({ queryKey: ['session'] })
    ]

Summary

  • Review mode: initial
  • One Major correctness issue found in reconnect cache synchronization.

Testing

  • Not run (automation). Add a reconnect test where the handshake reports resumed=false after scratchlist membership changes and assert queryKeys.scratchlistSessionIds is invalidated/refetched.

HAPI Bot

} {
const queryEnabled = Boolean(api && enabled)
const query = useQuery({
queryKey: queryKeys.scratchlistSessionIds,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MAJOR] Scratchlist status survives an unreplayable reconnect

This new cache is invalidated for live scratchlistUpdatedAt patches, but the full-resync path in App.handleSseConnect (web/src/App.tsx:256) invalidates only queryKeys.sessions and ['session']. When the hub reports resumed=false, scratchlist creates/deletes during the gap are not replayed, so this query can keep driving the filter with old IDs. staleTime does not trigger polling by itself.

Suggested fix:

const invalidations = [
    queryClient.invalidateQueries({ queryKey: queryKeys.sessions }),
    queryClient.invalidateQueries({ queryKey: queryKeys.scratchlistSessionIds }),
    queryClient.invalidateQueries({ queryKey: ['session'] })
]

Please add a non-resumed reconnect regression test for this cache.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • None.

Summary

  • Review mode: follow-up after new commits
  • The prior Major reconnect-cache finding is resolved on the current head. No additional issues found in the full latest diff.
  • Residual risk: floating filter/date-picker behavior still depends on browser layout and mobile safe-area combinations beyond the pure positioning unit tests.

Testing

  • Not run locally (automation). GitHub checks test, integration, and drift-gate passed.

HAPI Bot

@heavygee heavygee added enhancement New feature or request area:web Web PWA / React client area:hub Hub server (API, sync, store) community-pr PR from non-collaborator contributor labels Sep 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:hub Hub server (API, sync, store) area:web Web PWA / React client community-pr PR from non-collaborator contributor enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants