| 1 | import type { DesktopSnapShotState } from "@t3tools/contracts"; |
| 2 | |
| 3 | export type CaptureSetupStep = "access" | "shortcut"; |
| 4 | |
| 5 | export 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 | |
| 22 | export 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 | |
| 34 | export 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 | |
| 43 | export 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 | |
| 52 | export 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 | |
| 70 | export 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 | |
| 78 | export 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 | |
| 96 | export function captureSetupShouldDisableOnClose(wasEnabled: boolean, completed: boolean): boolean { |
| 97 | return !wasEnabled && !completed; |
| 98 | } |