MCPcopy
hub / github.com/jamiepine/voicebox / MainApp

Function MainApp

app/src/App.tsx:91–306  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

89}
90
91function MainApp() {
92 const platform = usePlatform();
93 const [serverReady, setServerReady] = useState(false);
94 const [startupError, setStartupError] = useState<string | null>(null);
95 const [loadingMessageIndex, setLoadingMessageIndex] = useState(0);
96 const serverStartingRef = useRef(false);
97
98 // Automatically check for app updates on startup and show toast notifications
99 useAutoUpdater({ checkOnMount: true, showToast: true });
100
101 // Replay the saved chord into the Rust hotkey listener every time
102 // capture_settings resolves or the user edits the chord.
103 useChordSync();
104
105 // Sync stored setting to Rust on startup
106 useEffect(() => {
107 if (platform.metadata.isTauri) {
108 const keepRunning = useServerStore.getState().keepServerRunningOnClose;
109 platform.lifecycle.setKeepServerRunning(keepRunning).catch((error) => {
110 console.error('Failed to sync initial setting to Rust:', error);
111 });
112 }
113 // Empty dependency array - platform is stable from context, only run once
114 // eslint-disable-next-line react-hooks/exhaustive-deps
115 }, [platform.metadata.isTauri, platform.lifecycle]);
116
117 // Setup lifecycle callbacks
118 useEffect(() => {
119 platform.lifecycle.onServerReady = () => {
120 setServerReady(true);
121 };
122 // Empty dependency array - platform is stable from context, only run once
123 // eslint-disable-next-line react-hooks/exhaustive-deps
124 }, [platform.lifecycle]);
125
126 // Subscribe to server logs
127 useEffect(() => {
128 const unsubscribe = platform.lifecycle.subscribeToServerLogs((entry) => {
129 useLogStore.getState().addEntry(entry);
130 });
131 return unsubscribe;
132 }, [platform.lifecycle]);
133
134 // Setup window close handler and auto-start server when running in Tauri (production only)
135 useEffect(() => {
136 if (!platform.metadata.isTauri) {
137 const serverUrl = getDefaultServerUrl();
138 const currentServerUrl = useServerStore.getState().serverUrl;
139 if (currentServerUrl !== serverUrl && isLoopbackVoiceboxServerUrl(currentServerUrl)) {
140 useServerStore.getState().setServerUrl(serverUrl);
141 }
142 setServerReady(true); // Web assumes server is running
143 return;
144 }
145
146 // Setup window close handler to check setting and stop server if needed
147 // This works in both dev and prod, but will only stop server if it was started by the app
148 platform.lifecycle.setupWindowCloseHandler().catch((error) => {

Callers

nothing calls this directly

Calls 15

usePlatformFunction · 0.90
useAutoUpdaterFunction · 0.90
useChordSyncFunction · 0.90
getDefaultServerUrlFunction · 0.90
cnFunction · 0.90
isPortInUseErrorFunction · 0.85
isVoiceboxHealthResponseFunction · 0.85
catchMethod · 0.80
thenMethod · 0.80
getHealthMethod · 0.80
setKeepServerRunningMethod · 0.65

Tested by

no test coverage detected