feat(session-status): mobile session quick switch with running/unread indicators (#340)
* feat(session-status): implement server-authoritative session status tracking - Add server-side session states and attention tracking with Map storage - Implement SSE event broadcasting (openchamber:session-status) - Add REST API endpoints for status/attention queries - Replace client-side polling with HTTP polling + SSE push - Track needsAttention based on user message + completion + unviewed - Add MobileSessionStatusBar for mobile UI - Handle session view/unview/message-sent state transitions - Add 24h cleanup for old session states * feat(session-status): add unread indicator to mobile session status bar * refactor(session-status): extract SessionStatusHeader component Extract the session status header into a reusable component and improve layout structure in CollapsedView and ExpandedView. * feat(session-status): optimize mobile session status bar UI * refactor(session-status): remove interval polling, use snapshot sync on reconnect/visibility - unifies session status/attention sync with existing SSE lifecycle, fixes no-op store churn bug, and drops duplicated client activity state while preserving mobile unread/running UX. --------- Co-authored-by: Jovines <jovines@qq.com> Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
This commit is contained in:
committed by
GitHub
co-authored by
Jovines
Bohdan Triapitsyn
parent
aa85e31420
commit
d5a2e49ae8
@@ -8,6 +8,7 @@ import { getWorktreeStatus } from "@/lib/worktrees/worktreeStatus";
|
||||
import { listProjectWorktrees, removeProjectWorktree } from "@/lib/worktrees/worktreeManager";
|
||||
import { useDirectoryStore } from "./useDirectoryStore";
|
||||
import { useProjectsStore } from "./useProjectsStore";
|
||||
import { triggerSessionStatusPoll } from "@/hooks/useServerSessionStatus";
|
||||
import type { ProjectEntry } from "@/lib/api/types";
|
||||
import { checkIsGitRepository } from "@/lib/gitApi";
|
||||
import { streamDebugEnabled } from "@/stores/utils/streamDebug";
|
||||
@@ -1237,7 +1238,26 @@ export const useSessionStore = create<SessionStore>()(
|
||||
},
|
||||
|
||||
setCurrentSession: (id: string | null) => {
|
||||
const prevSessionId = get().currentSessionId;
|
||||
set({ currentSessionId: id, error: null });
|
||||
|
||||
// Notify server of view state changes
|
||||
// This enables server-side needs_attention tracking
|
||||
if (prevSessionId && prevSessionId !== id) {
|
||||
// Leaving previous session
|
||||
fetch(`/api/sessions/${prevSessionId}/unview`, { method: 'POST' })
|
||||
.catch(() => { /* ignore */ });
|
||||
}
|
||||
if (id) {
|
||||
// Entering new session
|
||||
fetch(`/api/sessions/${id}/view`, { method: 'POST' })
|
||||
.catch(() => { /* ignore */ });
|
||||
}
|
||||
|
||||
// Trigger immediate poll to get latest attention states
|
||||
// This prevents stale state when switching sessions
|
||||
triggerSessionStatusPoll();
|
||||
|
||||
const directory = opencodeClient.getDirectory() ?? null;
|
||||
storeSessionForDirectory(directory, id);
|
||||
},
|
||||
@@ -1513,7 +1533,7 @@ export const useSessionStore = create<SessionStore>()(
|
||||
|
||||
const mergedSessions = dedupeSessionsById(persistedSessions);
|
||||
|
||||
return {
|
||||
const mergedResult = {
|
||||
...currentState,
|
||||
...persistedState,
|
||||
sessions: mergedSessions,
|
||||
@@ -1527,6 +1547,7 @@ export const useSessionStore = create<SessionStore>()(
|
||||
: currentState.availableWorktreesByProject,
|
||||
lastLoadedDirectory,
|
||||
};
|
||||
return mergedResult;
|
||||
},
|
||||
}
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user