fixed /chat

This commit is contained in:
2026-02-23 08:00:53 +00:00
parent 3e2c8090d5
commit d9b69c8209
10 changed files with 194 additions and 26 deletions
@@ -1,4 +1,4 @@
import { useEffect } from 'react';
import { useEffect, useMemo } from 'react';
import { useParams } from 'react-router';
import type { LayoutNode, SelectedSession } from 'officerdev';
import { WorkspaceView } from 'officerdev';
@@ -9,6 +9,25 @@ import { defaultLayout } from './defaultLayout';
export { ChatHistory as ChatHistoryApp } from './Widget';
// Allowed panel app types for the /chat screen
const ALLOWED_APP_TYPES = new Set<string | null>(['chat-session-list', 'chat-detail', null]);
/** Recursively fix any panel that uses a wrong app type (e.g. officerdev/chat) */
function normalizeLayout(node: LayoutNode): LayoutNode {
if (node.type === 'panel') {
if (!ALLOWED_APP_TYPES.has(node.appType)) {
return { ...node, appType: 'chat-detail' };
}
return node;
}
const children = node.children.map((c) => {
const fixed = normalizeLayout(c.node);
return fixed === c.node ? c : { ...c, node: fixed };
});
const changed = children.some((c, i) => c !== node.children[i]);
return changed ? { ...node, children } : node;
}
type SessionListPageProps = {
isNew?: boolean;
};
@@ -17,7 +36,21 @@ export const SessionListPage = ({ isNew }: SessionListPageProps) => {
const { sessionId } = useParams<{ sessionId: string }>();
const { sessions } = useChatSessions();
const [, setSelected] = usePanelChannel<SelectedSession>('chat:selected-session', null);
const workspace = useWorkspacesState<LayoutNode>('screens/chat', defaultLayout);
const rawWorkspace = useWorkspacesState<LayoutNode>('screens/chat', defaultLayout);
// Normalize synchronously so the wrong panel never renders
const workspace = useMemo(() => {
const fixed = normalizeLayout(rawWorkspace.value);
if (fixed === rawWorkspace.value) return rawWorkspace;
return { ...rawWorkspace, value: fixed };
}, [rawWorkspace]);
// Persist the fix to the backend
useEffect(() => {
if (rawWorkspace.isLoaded && workspace.value !== rawWorkspace.value) {
rawWorkspace.setValue(workspace.value);
}
}, [rawWorkspace.isLoaded, workspace.value, rawWorkspace.value]);
useEffect(() => {
if (isNew) {