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
@@ -99,6 +99,7 @@ export const useSessionStore = create<SessionStore>()(
|
||||
abortPromptSessionId: null,
|
||||
abortPromptExpiresAt: null,
|
||||
sessionStatus: new Map(),
|
||||
sessionAttentionStates: new Map(),
|
||||
userSummaryTitles: new Map(),
|
||||
pendingInputText: null,
|
||||
pendingInputMode: 'replace',
|
||||
@@ -423,6 +424,26 @@ export const useSessionStore = create<SessionStore>()(
|
||||
|
||||
if (currentSessionId) {
|
||||
setStatus(currentSessionId, 'busy');
|
||||
|
||||
const memoryState = get().sessionMemoryState.get(currentSessionId);
|
||||
if (!memoryState || !memoryState.lastUserMessageAt) {
|
||||
const currentMemoryState = get().sessionMemoryState;
|
||||
const newMemoryState = new Map(currentMemoryState);
|
||||
newMemoryState.set(currentSessionId, {
|
||||
viewportAnchor: memoryState?.viewportAnchor ?? 0,
|
||||
isStreaming: memoryState?.isStreaming ?? false,
|
||||
lastAccessedAt: Date.now(),
|
||||
backgroundMessageCount: memoryState?.backgroundMessageCount ?? 0,
|
||||
lastUserMessageAt: Date.now(),
|
||||
});
|
||||
set({ sessionMemoryState: newMemoryState });
|
||||
}
|
||||
}
|
||||
|
||||
// Notify server that user sent a message in this session
|
||||
if (currentSessionId) {
|
||||
fetch(`/api/sessions/${currentSessionId}/message-sent`, { method: 'POST' })
|
||||
.catch(() => { /* ignore */ });
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user