resolve /chat/<id> by scanning project groups and make session rows real links
deep-linking or refreshing /chat/<id> only has the id, so add loadClaudeSessionById to scan every project group for the transcript and return its real cwd. the session list page resolves on load from that, setting the cwd picker and resuming. session rows are now <Link to=/chat/<id>> so clicking updates the url and flows through the same resolve path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import { useEffect, useMemo, useRef } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router';
|
||||
import type { LayoutNode, SelectedSession } from 'officerdev';
|
||||
import { WorkspaceView } from 'officerdev';
|
||||
import { useIsMobile } from 'hooks/useIsMobile';
|
||||
import { useClient } from 'hooks/useClient';
|
||||
import { useDashboardState } from 'state/useDashboardState';
|
||||
import type { ClaudeSessionDetail } from 'state/useClaudeSessions';
|
||||
import { usePanelChannel } from 'hooks/usePanelChannel';
|
||||
import { defaultLayout } from './defaultLayout';
|
||||
|
||||
@@ -32,7 +34,11 @@ type SessionListPageProps = {
|
||||
|
||||
export const SessionListPage = ({ isNew }: SessionListPageProps) => {
|
||||
const { sessionId } = useParams<{ sessionId: string }>();
|
||||
const [, setSelected] = usePanelChannel<SelectedSession>('chat:selected-session', null);
|
||||
const [selected, setSelected] = usePanelChannel<SelectedSession>('chat:selected-session', null);
|
||||
const [, setActiveCwd] = usePanelChannel<string | null>('chat:active-cwd', null);
|
||||
const client = useClient();
|
||||
const selectedRef = useRef(selected);
|
||||
selectedRef.current = selected;
|
||||
const rawWorkspace = useDashboardState<LayoutNode>('screens/chat', defaultLayout);
|
||||
const isMobile = useIsMobile();
|
||||
const navigate = useNavigate();
|
||||
@@ -52,13 +58,36 @@ export const SessionListPage = ({ isNew }: SessionListPageProps) => {
|
||||
}
|
||||
}, [rawWorkspace.isLoaded, workspace.value, rawWorkspace.value]);
|
||||
|
||||
// Fresh /chat/<id> (deep-link or refresh): all we have is the id. Resolve the session by id — the
|
||||
// backend scans project groups — so the cwd picker lands on its real dir AND the chat resumes, exactly
|
||||
// as clicking it from the list would. Guarded so it never clobbers an already-loaded selection.
|
||||
useEffect(() => {
|
||||
if (isNew) {
|
||||
setSelected({ id: `new:${Date.now()}` });
|
||||
return;
|
||||
}
|
||||
if (!sessionId) return;
|
||||
setSelected({ id: sessionId });
|
||||
if (selectedRef.current?.id === sessionId && selectedRef.current.resumeSessionId) return;
|
||||
let cancelled = false;
|
||||
(async () => {
|
||||
try {
|
||||
const detail = await client.get<ClaudeSessionDetail>(`/chat/sessions/${sessionId}`);
|
||||
if (cancelled) return;
|
||||
setActiveCwd(detail.cwd || null);
|
||||
setSelected({
|
||||
id: sessionId,
|
||||
model: detail.model,
|
||||
resumeSessionId: sessionId,
|
||||
initialMessages: detail.messages as unknown as NonNullable<SelectedSession>['initialMessages'],
|
||||
});
|
||||
} catch {
|
||||
if (!cancelled) setSelected({ id: sessionId });
|
||||
}
|
||||
})();
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [sessionId, isNew]);
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user