Skip to content

Commit 37e5724

Browse files
committed
refactor: extract main app layout surfaces
1 parent 04d0859 commit 37e5724

10 files changed

Lines changed: 1507 additions & 1760 deletions

src/features/app/components/MainApp.tsx

Lines changed: 326 additions & 691 deletions
Large diffs are not rendered by default.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { useLayoutNodes } from "@/features/layout/hooks/useLayoutNodes";
2+
import type { LayoutNodesOptions } from "@/features/layout/hooks/layoutNodes/types";
3+
4+
export function useMainAppLayoutNodes(options: LayoutNodesOptions) {
5+
return useLayoutNodes(options);
6+
}

src/features/app/hooks/useMainAppLayoutSurfaces.ts

Lines changed: 905 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { SidebarCollapseButton } from "@/features/layout/components/SidebarToggleControls";
2+
import type { ComponentProps } from "react";
3+
import { MainAppShell } from "@app/components/MainAppShell";
4+
5+
type UseMainAppShellPropsArgs = {
6+
shell: Pick<
7+
ComponentProps<typeof MainAppShell>,
8+
| "appClassName"
9+
| "isResizing"
10+
| "appStyle"
11+
| "appRef"
12+
| "sidebarToggleProps"
13+
| "shouldLoadGitHubPanelData"
14+
| "appModalsProps"
15+
| "showMobileSetupWizard"
16+
| "mobileSetupWizardProps"
17+
>;
18+
gitHubPanelDataProps: ComponentProps<typeof MainAppShell>["gitHubPanelDataProps"];
19+
appLayout: Omit<ComponentProps<typeof MainAppShell>["appLayoutProps"], "desktopTopbarLeftNode" | "topbarActionsNode">;
20+
topbar: {
21+
isCompact: boolean;
22+
desktopTopbarLeftNode: ComponentProps<typeof MainAppShell>["appLayoutProps"]["desktopTopbarLeftNode"];
23+
hasActiveWorkspace: boolean;
24+
backendMode: "local" | "remote";
25+
remoteThreadConnectionState: "live" | "polling" | "disconnected";
26+
};
27+
};
28+
29+
export function useMainAppShellProps({
30+
shell,
31+
gitHubPanelDataProps,
32+
appLayout,
33+
topbar,
34+
}: UseMainAppShellPropsArgs) {
35+
const showThreadConnectionIndicator =
36+
topbar.hasActiveWorkspace && topbar.backendMode === "remote";
37+
const topbarActionsNode = showThreadConnectionIndicator ? (
38+
<span
39+
className={`compact-workspace-live-indicator ${
40+
topbar.remoteThreadConnectionState === "live"
41+
? "is-live"
42+
: topbar.remoteThreadConnectionState === "polling"
43+
? "is-polling"
44+
: "is-disconnected"
45+
}`}
46+
title={
47+
topbar.remoteThreadConnectionState === "live"
48+
? "Receiving live thread events"
49+
: topbar.remoteThreadConnectionState === "polling"
50+
? "Connected, syncing thread state by polling"
51+
: "Disconnected from backend"
52+
}
53+
>
54+
{topbar.remoteThreadConnectionState === "live"
55+
? "Live"
56+
: topbar.remoteThreadConnectionState === "polling"
57+
? "Polling"
58+
: "Disconnected"}
59+
</span>
60+
) : null;
61+
62+
const desktopTopbarLeftNodeWithToggle = !topbar.isCompact ? (
63+
<div className="topbar-leading">
64+
<SidebarCollapseButton {...shell.sidebarToggleProps} />
65+
{topbar.desktopTopbarLeftNode}
66+
</div>
67+
) : (
68+
topbar.desktopTopbarLeftNode
69+
);
70+
71+
return {
72+
...shell,
73+
gitHubPanelDataProps,
74+
appLayoutProps: {
75+
...appLayout,
76+
desktopTopbarLeftNode: desktopTopbarLeftNodeWithToggle,
77+
topbarActionsNode,
78+
},
79+
};
80+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { useAppMenuEvents } from "@app/hooks/useAppMenuEvents";
2+
import { useMenuAcceleratorController } from "@app/hooks/useMenuAcceleratorController";
3+
import { useSidebarLayoutActions } from "@app/hooks/useSidebarLayoutActions";
4+
import { useWorkspaceCycling } from "@app/hooks/useWorkspaceCycling";
5+
6+
type UseMainAppSidebarMenuOrchestrationArgs = {
7+
sidebarActions: Parameters<typeof useSidebarLayoutActions>[0];
8+
workspaceCycling: Parameters<typeof useWorkspaceCycling>[0];
9+
appMenu: Omit<
10+
Parameters<typeof useAppMenuEvents>[0],
11+
| "onOpenSettings"
12+
| "onCycleAgent"
13+
| "onCycleWorkspace"
14+
| "onAddWorkspace"
15+
| "onAddWorkspaceFromUrl"
16+
| "onAddAgent"
17+
| "onAddWorktreeAgent"
18+
| "onAddCloneAgent"
19+
> & {
20+
onAddWorkspace: () => void;
21+
onAddWorkspaceFromUrl: () => void;
22+
onAddAgent: NonNullable<Parameters<typeof useAppMenuEvents>[0]["onAddAgent"]>;
23+
onAddWorktreeAgent: NonNullable<
24+
Parameters<typeof useAppMenuEvents>[0]["onAddWorktreeAgent"]
25+
>;
26+
onAddCloneAgent: NonNullable<
27+
Parameters<typeof useAppMenuEvents>[0]["onAddCloneAgent"]
28+
>;
29+
};
30+
appSettings: Parameters<typeof useMenuAcceleratorController>[0]["appSettings"];
31+
onDebug: Parameters<typeof useMenuAcceleratorController>[0]["onDebug"];
32+
};
33+
34+
export function useMainAppSidebarMenuOrchestration({
35+
sidebarActions,
36+
workspaceCycling,
37+
appMenu,
38+
appSettings,
39+
onDebug,
40+
}: UseMainAppSidebarMenuOrchestrationArgs) {
41+
const sidebarHandlers = useSidebarLayoutActions(sidebarActions);
42+
const { handleCycleAgent, handleCycleWorkspace } = useWorkspaceCycling(workspaceCycling);
43+
44+
useAppMenuEvents({
45+
...appMenu,
46+
onAddWorkspace: () => {
47+
appMenu.onAddWorkspace();
48+
},
49+
onAddWorkspaceFromUrl: () => {
50+
appMenu.onAddWorkspaceFromUrl();
51+
},
52+
onAddAgent: (workspace) => {
53+
void appMenu.onAddAgent(workspace);
54+
},
55+
onAddWorktreeAgent: (workspace) => {
56+
void appMenu.onAddWorktreeAgent(workspace);
57+
},
58+
onAddCloneAgent: (workspace) => {
59+
void appMenu.onAddCloneAgent(workspace);
60+
},
61+
onOpenSettings: sidebarHandlers.onOpenSettings,
62+
onCycleAgent: handleCycleAgent,
63+
onCycleWorkspace: handleCycleWorkspace,
64+
});
65+
66+
useMenuAcceleratorController({ appSettings, onDebug });
67+
68+
return sidebarHandlers;
69+
}

0 commit comments

Comments
 (0)