"use client"; import { useEffect, useState } from "react"; import { useRouter } from "next/navigation"; import { Logo } from "@/components/Logo"; import { Button } from "@/components/ui/button"; import { Spinner } from "@/components/ui/spinner"; type PermissionStatus = "authorized" | "denied" | "not determined" | "restricted" | "limited"; interface PermissionsStatus { accessibility: PermissionStatus; inputMonitoring: PermissionStatus; } const STEPS = [ { id: "input-monitoring", title: "Input Monitoring", description: "Helps you write faster by enriching your text with suggestions from your knowledge base.", action: "requestInputMonitoring", field: "inputMonitoring" as const, }, { id: "accessibility", title: "Accessibility", description: "Lets you accept suggestions seamlessly, right where you're typing.", action: "requestAccessibility", field: "accessibility" as const, }, ]; function StatusBadge({ status }: { status: PermissionStatus }) { if (status === "authorized") { return ( Granted ); } if (status === "denied") { return ( Denied ); } return ( Pending ); } export default function DesktopPermissionsPage() { const router = useRouter(); const [permissions, setPermissions] = useState(null); const [isElectron, setIsElectron] = useState(false); useEffect(() => { if (!window.electronAPI) return; setIsElectron(true); let interval: ReturnType | null = null; const isResolved = (s: string) => s === "authorized" || s === "restricted"; const poll = async () => { const status = await window.electronAPI!.getPermissionsStatus(); setPermissions(status); if (isResolved(status.accessibility) && isResolved(status.inputMonitoring)) { if (interval) clearInterval(interval); } }; poll(); interval = setInterval(poll, 2000); return () => { if (interval) clearInterval(interval); }; }, []); if (!isElectron) { return (

This page is only available in the desktop app.

); } if (!permissions) { return (
); } const allGranted = permissions.accessibility === "authorized" && permissions.inputMonitoring === "authorized"; const handleRequest = async (action: string) => { if (action === "requestInputMonitoring") { await window.electronAPI!.requestInputMonitoring(); } else if (action === "requestAccessibility") { await window.electronAPI!.requestAccessibility(); } }; const handleContinue = () => { if (allGranted) { window.electronAPI!.restartApp(); } }; const handleSkip = () => { router.push("/dashboard"); }; return (
{/* Header */}

System Permissions

SurfSense needs two macOS permissions to provide system-wide autocomplete.

{/* Steps */}
{STEPS.map((step, index) => { const status = permissions[step.field]; const isGranted = status === "authorized"; return (
{isGranted ? "✓" : index + 1}

{step.title}

{step.description}

{!isGranted && (
{status === "denied" && (

Toggle SurfSense on in System Settings to continue.

)}
)}
); })}
{/* Footer */}
{allGranted ? ( <>

A restart is needed for permissions to take effect.

) : ( <> )}
); }