fix terminal state key leaking phantom dashboards; fix infinite loop in chat panel resume
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { useCallback, useEffect, useRef } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { useWorkspace } from '../../components/Workspace';
|
import { useWorkspace } from '../../components/Workspace';
|
||||||
import { usePanelChannel } from 'hooks/usePanelChannel';
|
import { usePanelChannel } from 'hooks/usePanelChannel';
|
||||||
import { useSavedSessions } from 'state/useSavedSessions';
|
import { useSavedSessions } from 'state/useSavedSessions';
|
||||||
@@ -97,6 +97,12 @@ export const ChatPanelWrapper = () => {
|
|||||||
: {};
|
: {};
|
||||||
|
|
||||||
const [selection] = usePanelChannel<ChatSessionSelection | null>('chat:panel-session', null);
|
const [selection] = usePanelChannel<ChatSessionSelection | null>('chat:panel-session', null);
|
||||||
|
const [resumeKey, setResumeKey] = useState(0);
|
||||||
|
const prevSelectionRef = useRef(selection);
|
||||||
|
if (selection !== prevSelectionRef.current) {
|
||||||
|
prevSelectionRef.current = selection;
|
||||||
|
if (selection?.resumeSummary) setResumeKey((k) => k + 1);
|
||||||
|
}
|
||||||
const [, setActiveSession] = usePanelChannel<string | null>('chat:active-session', null);
|
const [, setActiveSession] = usePanelChannel<string | null>('chat:active-session', null);
|
||||||
const [, setPreviewRefresh] = usePanelChannel<number>('preview:refresh', 0);
|
const [, setPreviewRefresh] = usePanelChannel<number>('preview:refresh', 0);
|
||||||
const [, setFilesRefresh] = usePanelChannel<number>('files:refresh-signal', 0);
|
const [, setFilesRefresh] = usePanelChannel<number>('files:refresh-signal', 0);
|
||||||
@@ -121,7 +127,7 @@ export const ChatPanelWrapper = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ChatPanelInner
|
<ChatPanelInner
|
||||||
key={resumeSummary ? `resume-${Date.now()}` : (sessionId ?? 'new')}
|
key={resumeSummary ? `resume-${resumeKey}` : (sessionId ?? 'new')}
|
||||||
sessionId={sessionId}
|
sessionId={sessionId}
|
||||||
model={model}
|
model={model}
|
||||||
resumeSummary={resumeSummary}
|
resumeSummary={resumeSummary}
|
||||||
|
|||||||
@@ -13,8 +13,18 @@ export const TerminalWrapper = ({ panelId }: { panelId: string }) => {
|
|||||||
const { mode } = useTerminalMode(panelId);
|
const { mode } = useTerminalMode(panelId);
|
||||||
const hostRoot = root === '~' || root === 'officer.dev';
|
const hostRoot = root === '~' || root === 'officer.dev';
|
||||||
const sandboxed = !hostRoot && (cwd !== '~' || mode === 'sandboxed');
|
const sandboxed = !hostRoot && (cwd !== '~' || mode === 'sandboxed');
|
||||||
const stateKey = dashboardId ? `ws-terminals-${mode}-${dashboardId}` : `ws-terminals-${mode}-default`;
|
const stateKey = (() => {
|
||||||
const { value: terminals, setValue: setTerminals } = useDashboardState<Record<string, string>>(stateKey, EMPTY_TERMINALS);
|
const hostSuffix = mode === 'host' ? 'host-' : '';
|
||||||
|
const wsMatch = dashboardId?.match(/^ws-layout-(.+)$/);
|
||||||
|
if (wsMatch) return `ws-${hostSuffix}terminals-${wsMatch[1]}`;
|
||||||
|
const projMatch = dashboardId?.match(/^proj-layout-(.+)$/);
|
||||||
|
if (projMatch) return `proj-${hostSuffix}terminals-${projMatch[1]}`;
|
||||||
|
return `ws-${hostSuffix}terminals-default`;
|
||||||
|
})();
|
||||||
|
const { value: terminals, setValue: setTerminals } = useDashboardState<Record<string, string>>(
|
||||||
|
stateKey,
|
||||||
|
EMPTY_TERMINALS,
|
||||||
|
);
|
||||||
const setTerminalsRef = useRef(setTerminals);
|
const setTerminalsRef = useRef(setTerminals);
|
||||||
setTerminalsRef.current = setTerminals;
|
setTerminalsRef.current = setTerminals;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user