返回 DeepSeek-Reasonix
transcript-layout.tsx
根目录 / desktop / frontend / bench / transcript-layout.tsx
1 import { useLayoutEffect, useMemo, useState, type CSSProperties } from "react";
2 import { createRoot } from "react-dom/client";
3 import { ChatPaneRegion, type ChatPaneTranscriptInput } from "../src/app-shell/ChatPaneRegion";
4 import { DockLauncher } from "../src/components/DockLauncher";
5 import { initialState, type Item } from "../src/lib/useController";
6 import { applyConversationWidth } from "../src/lib/conversationWidth";
7 import { LocaleProvider, useT } from "../src/lib/i18n";
8 import { installDesktopHostStub } from "../src/__tests__/desktopHostStub";
9 import "../src/styles.css";
10
11 type Options = {
12 layout: "workbench";
13 width: "standard" | "full";
14 sidebar: boolean;
15 dock: boolean;
16 launcher: boolean;
17 long: boolean;
18 turns: number;
19 text: string | null;
20 streaming: boolean;
21 shell: boolean;
22 };
23 declare global {
24 interface Window {
25 transcriptLayoutFixture: {
26 configure: (next: Partial<Options>) => void;
27 revision: number;
28 copied: string[];
29 command: string;
30 };
31 }
32 }
33
34 // Only the backend boundary is stubbed: layout, launcher, projection, windowing
35 // and message/code rendering below are the production components and stylesheet.
36 installDesktopHostStub({
37 ReportFrontendDiagnostic: async () => {},
38 GitBranches: async () => [],
39 WorkspaceChanges: async () => [],
40 ToolResultForTab: async () => null,
41 });
42 const noAction = () => {};
43 const copied: string[] = [];
44 const command = "printf '%s\\n' \"C:\\中文\\file.txt\"\r\n echo " + "long-command-".repeat(120) + "END_OF_COMMAND";
45 Object.defineProperty(navigator, "clipboard", { configurable: true, value: {
46 writeText: async (text: string) => { copied.push(text); },
47 } });
48 const commands = {
49 onPrompt: noAction, onFork: undefined, onDeliveryContinue: undefined, onAcceptDelivery: undefined,
50 onOpenChanges: undefined, onOpenVerification: undefined, onEditPrompt: undefined,
51 onRewind: undefined, onLoadOlderHistory: undefined, onLoadNewerHistory: undefined,
52 onSurfacePaintReady: undefined,
53 };
54 function Fixture() {
55 const t = useT();
56 const [options, setOptions] = useState<Options>({
57 layout: "workbench", width: "full", sidebar: true, dock: false, launcher: false, long: true, turns: 2, text: null, streaming: false, shell: false,
58 });
59 const [revision, setRevision] = useState(0);
60 const items = useMemo(() => Array.from({ length: options.turns }, (_, index): Item[] => [
61 { kind: "user", id: "user-" + index, text: "USER MESSAGE MUST REMAIN VISIBLE " + index },
62 options.shell
63 ? { kind: "tool", id: "tool-" + index, name: "bash", status: "done", readOnly: false,
64 args: JSON.stringify({ command }), output: "OUTPUT_STAYS_VISIBLE\n" + "abcdefghij".repeat(60) }
65 : { kind: "assistant", id: "answer-" + index, text: options.text ?? ("\`\`\`text\n" + (options.long && (options.turns < 100 || index === 10) ? "abcdefghij".repeat(60) : "short") + "\n\`\`\`"), reasoning: "", streaming: options.streaming },
66 ]).flat(), [options.long, options.turns, options.text, options.streaming, options.shell]);
67 useLayoutEffect(() => {
68 document.documentElement.dataset.themeStyle = "graphite";
69 document.documentElement.dataset.theme = "light";
70 document.documentElement.dataset.platform = "windows";
71 applyConversationWidth(options.width);
72 window.transcriptLayoutFixture = {
73 configure: next => { setOptions(current => ({ ...current, ...next })); setRevision(value => value + 1); },
74 revision,
75 copied,
76 command,
77 };
78 }, [options.width, revision]);
79 const transcript: ChatPaneTranscriptInput = {
80 state: { ...initialState, items, running: options.streaming }, items, tabId: "layout-fixture", geometrySessionKey: "layout-fixture",
81 footerHeight: 100, invocationMetadata: undefined, surfaceCommitToken: undefined,
82 liveStore: undefined, transcriptHydrating: false, navigationDataReady: true, readOnly: false,
83 controllerReady: true, hydratePlaceholderActive: false, clearContextPending: false,
84 availability: { kind: "ready", source: "history" },
85 rewind: { stateActive: false, committing: false },
86 };
87 return <div className={"app app--windows app--windows-frameless app--" + options.layout} data-fixture-revision={revision}>
88 <div className={`layout${options.sidebar ? "" : " layout--sidebar-collapsed"}${options.dock ? " layout--workspace-open" : ""}`}
89 style={{ "--sidebar-expanded-width": "300px", "--workspace-width": "300px" } as CSSProperties}>
90 <header className="topicbar">Transcript layout fixture</header>
91 <aside className="sidebar">Sidebar</aside>
92 <div className="chat-pane">
93 <ChatPaneRegion transitioning={false} t={t} imDetail={null} remote={undefined} commands={commands}
94 transcript={transcript} onRetryHistory={async () => {}}
95 launcher={options.launcher ? <DockLauncher tabId="layout-fixture" scopeKey="layout-fixture"
96 workspaceRoot="" visible onSelect={noAction} overlay={options.dock} /> : undefined} />
97 <footer className="footer"><div className="composer-wrap"><textarea aria-label="Draft" defaultValue="Draft remains inside the chat pane" /></div></footer>
98 </div>
99 {options.dock && <aside className="workbench-dock" style={{ gridColumn: 3, gridRow: 2 }}>Workspace</aside>}
100 </div>
101 </div>;
102 }
103 createRoot(document.getElementById("root")!).render(<LocaleProvider><Fixture /></LocaleProvider>);
104
104 lines Plain Text