diff --git a/src/renderer/components/SetupWizard.tsx b/src/renderer/components/SetupWizard.tsx
index fe82bfb..29f1244 100644
--- a/src/renderer/components/SetupWizard.tsx
+++ b/src/renderer/components/SetupWizard.tsx
@@ -13,7 +13,15 @@ interface SetupWizardProps {
initialStep?: "imap";
}
-type Step = "loading" | "credentials" | "apikey" | "oauth" | "extensions" | "analytics" | "imap";
+type Step =
+ | "loading"
+ | "credentials"
+ | "apikey"
+ | "oauth"
+ | "extensions"
+ | "permissions"
+ | "analytics"
+ | "imap";
interface ExtensionAuthInfo {
extensionId: string;
@@ -44,6 +52,13 @@ export function SetupWizard({ onComplete, initialStep }: SetupWizardProps) {
// Analytics opt-in (default ON — session replay is bundled under analytics)
const [analyticsEnabled, setAnalyticsEnabled] = useState(true);
+ // Notification permission state. "unknown" before the user has clicked
+ // Grant; "granted" / "denied" after macOS has decided. Used by the
+ // permissions wizard step to render the right copy + CTA.
+ const [notificationPermission, setNotificationPermission] = useState<
+ "unknown" | "granted" | "denied" | "requesting"
+ >("unknown");
+
// Check what's already configured and skip to the right step.
// If `initialStep` was passed (e.g. "imap" from the empty-state CTA),
// we still compute the visible-step indicator but don't override the
@@ -73,6 +88,7 @@ export function SetupWizard({ onComplete, initialStep }: SetupWizardProps) {
if (!hasAnthropicKey) flow.push("apikey");
if (!hasTokens) flow.push("oauth");
flow.push("extensions");
+ flow.push("permissions");
flow.push("analytics");
setVisibleSteps(flow);
@@ -86,7 +102,14 @@ export function SetupWizard({ onComplete, initialStep }: SetupWizardProps) {
enterExtensionsStep();
}
} else {
- setVisibleSteps(["credentials", "apikey", "oauth", "extensions", "analytics"]);
+ setVisibleSteps([
+ "credentials",
+ "apikey",
+ "oauth",
+ "extensions",
+ "permissions",
+ "analytics",
+ ]);
setStep("credentials");
}
})
@@ -221,19 +244,20 @@ export function SetupWizard({ onComplete, initialStep }: SetupWizardProps) {
setStep("extensions");
setIsLoading(false);
} else {
- // No extensions need auth (or IPC failed) — skip extensions step entirely
+ // No extensions need auth (or IPC failed) — skip extensions step
+ // entirely and move to the permissions step (next in the flow).
if (!result.success) {
console.error("[SetupWizard] getPendingAuths failed:", result.error);
}
setVisibleSteps((prev) => prev.filter((s) => s !== "extensions"));
setIsLoading(false);
- setStep("analytics");
+ setStep("permissions");
}
} catch (err) {
console.error("[SetupWizard] getPendingAuths failed:", err);
setVisibleSteps((prev) => prev.filter((s) => s !== "extensions"));
setIsLoading(false);
- setStep("analytics");
+ setStep("permissions");
}
}, []);
@@ -569,7 +593,7 @@ export function SetupWizard({ onComplete, initialStep }: SetupWizardProps) {
{error &&
{error}
}