Skip to content
Source
Sign inSign up

adaptive-workspace-context.ts

108 lines4.4 KB

1import type { WorkspaceTab } from "./workspace/workspace-tabs-state";
2import { createContext, use } from "react";
3import type { InspectorContent } from "./inspector-panes";
4import type { WorkspaceDetail, WorkspaceDetailSheet } from "./workspace/workspace-detail-selection";
5import {
6 deriveFileInspectorPaneLayout,
7 deriveLayout,
8 deriveWorkspacePaneLayout,
9 type FileInspectorPaneLayout,
10 type Layout,
11 type WorkspacePaneLayout,
12} from "../../lib/layout";
13​
14/** The workspace's actions; their identities never change. */
15export interface AdaptiveWorkspaceActions {
16 readonly startNewTask: () => void;
17 /** Use `useSelectWorkspaceDetail`, which also works outside the layout. */
18 readonly selectDetail?: (detail: WorkspaceDetail, sheet?: WorkspaceDetailSheet) => void;
19 readonly registerWorkspaceInspector: (
20 content: InspectorContent,
21 routeKey: string | undefined,
22 revealKey?: string,
23 ) => () => void;
24 readonly setPrimarySidebarSearchQuery: (query: string) => void;
25 /** Opens the inspector: its column where the window has one, otherwise a sheet. */
26 readonly showInspector: () => void;
27 readonly toggleAuxiliaryPane: () => void;
28 readonly togglePrimarySidebar: () => void;
29 /** Shows the sidebar, setting aside the keyboard or an inspector that took its room. */
30 readonly revealPrimarySidebar: () => void;
31 readonly setPrimarySidebarVisible: (visible: boolean) => void;
32 /** Opens a workspace tab with its list and, with columns, the page it last showed. */
33 readonly openWorkspaceTab: (
34 tab: WorkspaceTab | "settings",
35 options?: { readonly columns?: boolean },
36 ) => void;
37 readonly setAuxiliaryPaneWidth: (width: number) => void;
38 readonly setNativeInspectorWidth: (width: number) => void;
40​
41/** Changes only with the window (size, fold, hinge), never with a pane toggle or the keyboard. */
42interface AdaptiveWorkspaceLayoutValue extends AdaptiveWorkspaceActions {
43 readonly layout: Layout;
44 readonly nativeInspectorWidth: number;
45 /** Android split: the width a workspace page (Usage) opens at; null without columns. */
46 readonly workspacePageWidth?: number | null;
48​
49/** Changes as panes toggle and the keyboard comes and goes; read it only where that shows. */
50interface WorkspacePaneStateValue {
51 readonly panes: WorkspacePaneLayout;
52 readonly fileInspector: FileInspectorPaneLayout;
53 readonly primarySidebarSearchQuery: string;
54 /**
55 * Whether the content pane offers a sidebar button: false without columns, on a list that keeps
56 * its sidebar, and on a workspace page (Android Settings, Usage) that covers it.
57 */
58 readonly sidebarToggleable: boolean;
59 /**
60 * Whether the sidebar shows in each orientation, where it floats over the content in portrait
61 * (the unfolded Duo). The native split switches between them as a rotation starts.
62 */
63 readonly sidebarByOrientation: { readonly landscape: boolean; readonly portrait: boolean } | null;
65​
66const compactLayout = deriveLayout({ width: 0, height: 0 });
67const compactPanes = deriveWorkspacePaneLayout({
68 layout: compactLayout,
69 viewportWidth: 0,
70 primarySidebarPreferredVisible: true,
71 auxiliaryPanePreferredVisible: true,
72});
73const compactFileInspector = deriveFileInspectorPaneLayout({
74 layout: compactLayout,
75 viewportWidth: 0,
76});
77export const AdaptiveWorkspaceContext = createContext<AdaptiveWorkspaceLayoutValue>({
78 layout: compactLayout,
79 startNewTask: () => undefined,
80 registerWorkspaceInspector: () => () => undefined,
81 setPrimarySidebarSearchQuery: () => undefined,
82 showInspector: () => undefined,
83 toggleAuxiliaryPane: () => undefined,
84 togglePrimarySidebar: () => undefined,
85 revealPrimarySidebar: () => undefined,
86 setPrimarySidebarVisible: () => undefined,
87 openWorkspaceTab: () => undefined,
88 setAuxiliaryPaneWidth: () => undefined,
89 nativeInspectorWidth: 0,
90 setNativeInspectorWidth: () => undefined,
91});
92export const WorkspacePaneStateContext = createContext<WorkspacePaneStateValue>({
93 panes: compactPanes,
94 fileInspector: compactFileInspector,
95 primarySidebarSearchQuery: "",
96 sidebarToggleable: false,
97 sidebarByOrientation: null,
98});
99​
100/** The window's layout and the workspace's actions. Toggling a pane doesn't re-render readers. */
101export function useAdaptiveWorkspaceLayout(): AdaptiveWorkspaceLayoutValue {
102 return use(AdaptiveWorkspaceContext);
104​
105/** Which panes show, and the keyboard's hold on them. Re-renders on every pane toggle. */
106export function useWorkspacePaneState(): WorkspacePaneStateValue {
107 return use(WorkspacePaneStateContext);