1import type { DesktopSnapShotState } from "@t3tools/contracts";
2
3export type CaptureSetupStep = "access" | "shortcut";
4
5export function captureSetupDesktopName(state: DesktopSnapShotState): string | undefined {
6 if (state.mode !== "portal") return undefined;
7 const desktop = state.linuxDesktop ?? captureSetupBackend(state);
8 switch (desktop) {
9 case "gnome":
10 return "GNOME";
11 case "kde":
12 return "KDE Plasma";
13 case "niri":
14 return "Niri";
15 case "hyprland":
16 return "Hyprland";
17 default:
18 return undefined;
19 }
20}
21
22export function captureSetupBackend(state: DesktopSnapShotState) {
23 if (state.mode !== "portal") return "direct";
24 if (state.linuxBackend === "niri") return "niri";
25 if (state.linuxBackend === "kde") return "kde";
26 if (state.linuxBackend === "hyprland") return "hyprland";
27 if (state.linuxBackend === "screenshot-portal") return "portal";
28 if (state.linuxBackend === "picker" && state.gnomeExtension?.status === "unsupported")
29 return "picker";
30 if (state.linuxBackend === "gnome-extension" || state.gnomeExtension) return "gnome";
31 return "picker";
32}
33
34export function captureSetupAccessReady(state: DesktopSnapShotState): boolean {
35 if (state.mode === "unavailable" || state.message) return false;
36 if (captureSetupBackend(state) === "gnome")
37 return state.gnomeExtension?.status === "enabled" && state.linuxBackend === "gnome-extension";
38 if (captureSetupBackend(state) === "kde") return state.kdeHelper?.status === "ready";
39 if (captureSetupBackend(state) === "hyprland") return state.hyprlandHelper?.status === "ready";
40 return true;
41}
42
43export function captureSetupMacPermissionsReady(
44 state: DesktopSnapShotState,
45 includeAccessibility: boolean,
46): boolean {
47 const permissions = state.macPermissions;
48 if (!permissions) return true;
49 return permissions.screenRecording && (!includeAccessibility || permissions.accessibility);
50}
51
52export function captureSetupCheckMessage(state: DesktopSnapShotState): string {
53 const backend = captureSetupBackend(state);
54 const gnome = backend === "gnome";
55 if (
56 state.message ||
57 (gnome && state.gnomeExtension?.status === "error") ||
58 (backend === "kde" && state.kdeHelper?.status === "error") ||
59 (backend === "hyprland" && state.hyprlandHelper?.status === "error")
60 )
61 return "Still unable to check access. See Advanced for help.";
62 if (captureSetupBackend(state) === "picker") return "Ready. You'll choose a window each time.";
63 if (gnome && state.gnomeExtension?.status === "restart-required")
64 return "Still waiting for you to sign out and back in.";
65 return captureSetupAccessReady(state)
66 ? "Ready. Continue to choose your shortcut."
67 : "Not ready yet. Finish the step above.";
68}
69
70export function captureSetupShortcutReady(state: DesktopSnapShotState, unsaved: boolean): boolean {
71 if (unsaved || !captureSetupAccessReady(state)) return false;
72 if (state.linuxBackend === "hyprland") return Boolean(state.shortcutActionRegistered);
73 return state.linuxBackend === "niri"
74 ? Boolean(state.shortcutBinding)
75 : state.shortcutRegistered || Boolean(state.shortcutPending);
76}
77
78export function captureSetupInitialStep(
79 state: DesktopSnapShotState,
80 requested: CaptureSetupStep | "resume" = "resume",
81): CaptureSetupStep {
82 if (!captureSetupAccessReady(state)) return "access";
83 if (requested === "resume") {
84 // A disabled native backend hasn't checked system permissions yet. A picker
85 // still needs its explanation; neither is proof of active-window access.
86 if (
87 (state.mode === "direct" && !state.shortcutRegistered) ||
88 captureSetupBackend(state) === "picker"
89 )
90 return "access";
91 return "shortcut";
92 }
93 return requested;
94}
95
96export function captureSetupShouldDisableOnClose(wasEnabled: boolean, completed: boolean): boolean {
97 return !wasEnabled && !completed;
98}