1import { useMemo } from "react";
2import { ScreenHeader } from "../../components/ScreenHeader";
3import { ScreenHeaderButton } from "../../components/ScreenHeaderButton";
4import type { ScreenHeaderAction } from "../../components/ScreenHeader.types";
5import { useAdaptiveWorkspaceLayout } from "../layout/AdaptiveWorkspaceLayout";
6import type { ThreadInspectorMode } from "./thread-inspector-content-stack";
7import { useThreadHeaderOptions } from "./useThreadHeaderOptions";
8import { useWorkspaceListNavigation } from "../workspace/useAndroidWorkspaceNavigation";
9
10export function ThreadHeader(
11 props: Parameters<typeof useThreadHeaderOptions>[0] & {
12 readonly hasThreadCwd: boolean;
13 readonly hasWorkspaceRoot: boolean;
14 readonly fileInspectorSupported: boolean;
15 readonly inspectorMode: ThreadInspectorMode | null;
16 readonly onToggleInspector: () => void;
17 readonly onOpenGitInspector: () => void;
18 readonly onOpenFilesInspector: () => void;
19 },
20) {
21 const returnToList = useWorkspaceListNavigation("threads");
22 const { layout, panes, toggleAuxiliaryPane } = useAdaptiveWorkspaceLayout();
23 const { onOpenTerminal, onMergeBack } = props.gitControls;
24 const native = useThreadHeaderOptions(props);
25 const androidHeaderActions = useMemo<ReadonlyArray<ScreenHeaderAction>>(() => {
26 const actions: ScreenHeaderAction[] = [];
27 if (props.onReturnToThread) {
28 actions.push({
29 accessibilityLabel: "Return to chat",
30 icon: "chevron.left",
31 onPress: props.onReturnToThread,
32 });
33 }
34 if (props.hasThreadCwd) {
35 const filesVisible = props.inspectorMode === "files" && panes.auxiliaryPaneVisible;
36 actions.push({
37 accessibilityLabel: filesVisible ? "Close files" : "Open files",
38 selected: filesVisible,
39 icon: "folder",
40 onPress: filesVisible ? toggleAuxiliaryPane : props.onOpenFilesInspector,
41 });
42 }
43 if (props.hasWorkspaceRoot && props.gitControls.canOpenTerminal) {
44 actions.push({
45 accessibilityLabel: "Open terminal",
46 icon: "terminal",
47 onPress: () => onOpenTerminal(null),
48 });
49 }
50 actions.push({
51 accessibilityLabel: "Open git controls",
52 icon: "point.topleft.down.curvedto.point.bottomright.up",
53 onPress: props.onOpenGitInspector,
54 });
55 if (onMergeBack) {
56 actions.push({
57 accessibilityLabel: "Merge back to source",
58 icon: "arrow.triangle.merge",
59 onPress: onMergeBack,
60 });
61 }
62 return actions;
63 }, [
64 props.inspectorMode,
65 panes.auxiliaryPaneVisible,
66 props.onOpenFilesInspector,
67 onOpenTerminal,
68 onMergeBack,
69 props.onOpenGitInspector,
70 toggleAuxiliaryPane,
71 props.onReturnToThread,
72 props.hasThreadCwd,
73 props.hasWorkspaceRoot,
74 props.gitControls.canOpenTerminal,
75 ]);
76
77 return (
78 <>
79 <ScreenHeader
80 title={props.title}
81 subtitle={props.subtitle}
82 sidebar={native.sidebar}
83 options={native.options}
84 optionsVersion={native.optionsVersion}
85 trailing={
86 props.fileInspectorSupported && props.hasThreadCwd ? (
87 <ScreenHeaderButton
88 accessibilityLabel={
89 props.inspectorMode !== null && panes.auxiliaryPaneVisible
90 ? "Hide inspector"
91 : "Show inspector"
92 }
93 icon="sidebar.right"
94 selected={props.inspectorMode !== null && panes.auxiliaryPaneVisible}
95 onPress={props.onToggleInspector}
96 />
97 ) : null
98 }
99 onBack={layout.usesSplitView ? undefined : returnToList}
100 actions={androidHeaderActions}
101 hideBottomBorder
102 />
103 {native.fallback}
104 </>
105 );
106}