feat(web): show session status indicators in sidebar#1701
feat(web): show session status indicators in sidebar#1701Jesse-XIE wants to merge 1 commit intoMoonshotAI:mainfrom
Conversation
Add visual dot indicators after the timestamp in the session list: - busy: green pulsing dot (animate-pulse) - unread: blue static dot (completed while user was viewing another session) - idle: no dot (default) Track unread sessions via busy→idle transitions from both WebSocket status events and API refresh polling. Clear unread on session select.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 35262d2aab
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| setUnreadSessionIds((prev) => { | ||
| if (!prev.has(sessionId)) return prev; | ||
| const next = new Set(prev); | ||
| next.delete(sessionId); | ||
| return next; |
There was a problem hiding this comment.
Clear unread when selection changes from any path
Unread state is currently cleared only in the sidebar click handler, so programmatic selection paths (for example URL restore in App, or auto-selection after deleting the current session in useSessions.deleteSession) bypass this logic. When that happens, a session can stay marked unread even while it is the active session, leaving a stale blue indicator. Clearing unread based on selectedSessionId changes (instead of only click events) would keep the indicator consistent.
Useful? React with 👍 / 👎.
| // Mark as unread when a non-selected session finishes (becomes non-busy) | ||
| if (status.state !== "busy" && status.sessionId !== selectedSessionId) { | ||
| setUnreadSessionIds((prev) => { | ||
| const next = new Set(prev); | ||
| next.add(status.sessionId); | ||
| return next; | ||
| }); | ||
| } |
There was a problem hiding this comment.
🟡 handleSessionStatus marks unread on any non-busy status instead of only busy→non-busy transitions
The unread marking logic in handleSessionStatus at line 307 marks a session as unread whenever status.state !== "busy" for a non-selected session, without checking whether the previous state was "busy". This differs from the useEffect at web/src/App.tsx:284-287 which correctly checks prevState === "busy" && state !== "busy" to detect transitions only.
In the current architecture this code is effectively dead — the WebSocket connects per-session to the selected session, so status.sessionId !== selectedSessionId is always false. However, if the backend or architecture ever changes to deliver cross-session status events through a single WebSocket, this would cause false-positive unread badges: any non-busy status (e.g., an idle status with reason: "config_update", or a stopped session that was never busy) would incorrectly mark the session as unread, and the unread dot would reappear even after the user has cleared it by clicking the session.
Prompt for agents
In web/src/App.tsx, the unread marking inside handleSessionStatus (lines 306-313) should track the previous state to only mark as unread on busy→non-busy transitions, matching the useEffect logic at lines 274-300. Since handleSessionStatus is called per-event (not on batch session updates), you'd need to consult prevSessionStatusRef to check the previous state:
1. Read the previous state from prevSessionStatusRef.current.get(status.sessionId)
2. Only add to unreadSessionIds if the previous state was "busy" AND the new state is not "busy"
3. Update prevSessionStatusRef.current with the new state
Alternatively, since this code path currently never fires (WebSocket is per-session, so status.sessionId always equals selectedSessionId), consider removing this block entirely and relying solely on the useEffect at lines 274-300 for unread detection.
Was this helpful? React with 👍 or 👎 to provide feedback.
Related Issue
no
Description
Add visual dot indicators after the timestamp in the session list:
Track unread sessions via busy→idle transitions from both WebSocket status events and API refresh polling. Clear unread on session select.
Checklist
make gen-changelogto update the changelog.make gen-docsto update the user documentation.Related Issue
no
Description
Add visual dot indicators after the timestamp in the session list:
Track unread sessions via busy→idle transitions from both WebSocket status events and API refresh polling. Clear unread on session select.
Checklist
make gen-changelogto update the changelog.make gen-docsto update the user documentation.