|
1 | | -import { useEffect, useState } from "react"; |
| 1 | +import { useEffect, useState, useRef } from "react"; |
2 | 2 | import { Toaster } from "sonner"; |
3 | 3 | import "./App.css"; |
4 | 4 | import AccessibilityPermissions from "./components/AccessibilityPermissions"; |
5 | 5 | import Footer from "./components/footer"; |
6 | | -import Onboarding from "./components/onboarding"; |
| 6 | +import Onboarding, { AccessibilityOnboarding } from "./components/onboarding"; |
7 | 7 | import { Sidebar, SidebarSection, SECTIONS_CONFIG } from "./components/Sidebar"; |
8 | 8 | import { useSettings } from "./hooks/useSettings"; |
| 9 | +import { useSettingsStore } from "./stores/settingsStore"; |
9 | 10 | import { commands } from "@/bindings"; |
10 | 11 |
|
| 12 | +type OnboardingStep = "accessibility" | "model" | "done"; |
| 13 | + |
11 | 14 | const renderSettingsContent = (section: SidebarSection) => { |
12 | 15 | const ActiveComponent = |
13 | 16 | SECTIONS_CONFIG[section]?.component || SECTIONS_CONFIG.general.component; |
14 | 17 | return <ActiveComponent />; |
15 | 18 | }; |
16 | 19 |
|
17 | 20 | function App() { |
18 | | - const [showOnboarding, setShowOnboarding] = useState<boolean | null>(null); |
| 21 | + const [onboardingStep, setOnboardingStep] = useState<OnboardingStep | null>( |
| 22 | + null |
| 23 | + ); |
19 | 24 | const [currentSection, setCurrentSection] = |
20 | 25 | useState<SidebarSection>("general"); |
21 | 26 | const { settings, updateSetting } = useSettings(); |
| 27 | + const refreshAudioDevices = useSettingsStore( |
| 28 | + (state) => state.refreshAudioDevices |
| 29 | + ); |
| 30 | + const refreshOutputDevices = useSettingsStore( |
| 31 | + (state) => state.refreshOutputDevices |
| 32 | + ); |
| 33 | + const hasCompletedPostOnboardingInit = useRef(false); |
22 | 34 |
|
23 | 35 | useEffect(() => { |
24 | 36 | checkOnboardingStatus(); |
25 | 37 | }, []); |
26 | 38 |
|
| 39 | + // Initialize Enigo and refresh audio devices when main app loads |
| 40 | + useEffect(() => { |
| 41 | + if (onboardingStep === "done" && !hasCompletedPostOnboardingInit.current) { |
| 42 | + hasCompletedPostOnboardingInit.current = true; |
| 43 | + commands.initializeEnigo().catch((e) => { |
| 44 | + console.warn("Failed to initialize Enigo:", e); |
| 45 | + }); |
| 46 | + refreshAudioDevices(); |
| 47 | + refreshOutputDevices(); |
| 48 | + } |
| 49 | + }, [onboardingStep, refreshAudioDevices, refreshOutputDevices]); |
| 50 | + |
27 | 51 | // Handle keyboard shortcuts for debug mode toggle |
28 | 52 | useEffect(() => { |
29 | 53 | const handleKeyDown = (event: KeyboardEvent) => { |
@@ -51,25 +75,39 @@ function App() { |
51 | 75 |
|
52 | 76 | const checkOnboardingStatus = async () => { |
53 | 77 | try { |
54 | | - // Always check if they have any models available |
| 78 | + // Check if they have any models available |
55 | 79 | const result = await commands.hasAnyModelsAvailable(); |
56 | 80 | if (result.status === "ok") { |
57 | | - setShowOnboarding(!result.data); |
| 81 | + // If they have models/downloads, they're done. Otherwise start permissions step. |
| 82 | + setOnboardingStep(result.data ? "done" : "accessibility"); |
58 | 83 | } else { |
59 | | - setShowOnboarding(true); |
| 84 | + setOnboardingStep("accessibility"); |
60 | 85 | } |
61 | 86 | } catch (error) { |
62 | 87 | console.error("Failed to check onboarding status:", error); |
63 | | - setShowOnboarding(true); |
| 88 | + setOnboardingStep("accessibility"); |
64 | 89 | } |
65 | 90 | }; |
66 | 91 |
|
| 92 | + const handleAccessibilityComplete = () => { |
| 93 | + setOnboardingStep("model"); |
| 94 | + }; |
| 95 | + |
67 | 96 | const handleModelSelected = () => { |
68 | 97 | // Transition to main app - user has started a download |
69 | | - setShowOnboarding(false); |
| 98 | + setOnboardingStep("done"); |
70 | 99 | }; |
71 | 100 |
|
72 | | - if (showOnboarding) { |
| 101 | + // Still checking onboarding status |
| 102 | + if (onboardingStep === null) { |
| 103 | + return null; |
| 104 | + } |
| 105 | + |
| 106 | + if (onboardingStep === "accessibility") { |
| 107 | + return <AccessibilityOnboarding onComplete={handleAccessibilityComplete} />; |
| 108 | + } |
| 109 | + |
| 110 | + if (onboardingStep === "model") { |
73 | 111 | return <Onboarding onModelSelected={handleModelSelected} />; |
74 | 112 | } |
75 | 113 |
|
|
0 commit comments