1/**
2 * Root routes listed as presented over the workspace, including ones that are plain cards on
3 * Android but still sit above the workspace there.
4 */
5const LISTED_OVERLAY_ROUTES: ReadonlySet<string> = new Set([
6 "PullRequestReview",
7 "PullRequestInlineComment",
8 "ConnectOnboarding",
9 "Connections",
10 "ConnectionsNew",
11 "GitBranches",
12 "GitCommit",
13 "GitConfirm",
14 "GitOverview",
15 "NewTaskProject",
16 "NewTaskFiles",
17 "NewTaskFile",
18 "NewTaskAttachment",
19 "NewTaskThreadSettings",
20 "AddProject",
21 "AddProjectRepository",
22 "AddProjectDestination",
23 "AddProjectLocal",
24 "AddProjectNew",
25 "NewTaskEnvironment",
26 "NewTaskBranch",
27 "SettingsLegal",
28 "SettingsAuth",
29 "SettingsWaitlist",
30 "ThreadAgents",
31 "ThreadBackgroundWork",
32 "ThreadPullRequests",
33 "ThreadQueue",
34 "ThreadReviewComment",
35 "ThreadDevicePreview",
36 "ThreadBrowserPreview",
37 "ThreadSettingsSheet",
38]);
39
40// Every route whose `presentation` is a sheet or modal, read from the root stack's config once.
41let presentedRoutes: ReadonlySet<string> = new Set();
42
43export function registerPresentedRoutes(names: Iterable<string>) {
44 presentedRoutes = new Set(names);
45}
46
47/** Whether a root route is presented over the workspace (a sheet or modal). */
48export function isWorkspaceOverlayRoute(name: string) {
49 return LISTED_OVERLAY_ROUTES.has(name) || presentedRoutes.has(name);
50}
51
52/** The routes that make up the workspace, up to the first sheet or modal above it. */
53export function workspaceRoutesOf<Route extends { readonly name: string }>(
54 routes: readonly Route[],
55) {
56 const firstOverlay = routes.findIndex((route) => isWorkspaceOverlayRoute(route.name));
57 return {
58 workspace: firstOverlay < 0 ? routes : routes.slice(0, firstOverlay),
59 overlays: firstOverlay < 0 ? [] : routes.slice(firstOverlay),
60 };
61}