Add Tauri integration and server management features. Introduced auto-start functionality for the bundled server in Tauri environment, added configuration management for data directories, and refactored backend components to utilize the new config module. Updated dependencies and improved project structure for better organization.

This commit is contained in:
Jamie Pine
2026-01-25 04:25:45 -08:00
parent 6164877f7f
commit d14aca2267
19 changed files with 432 additions and 60 deletions
+51 -2
View File
@@ -1,4 +1,4 @@
import { useState } from 'react';
import { useState, useEffect } from 'react';
import { GenerationForm } from '@/components/Generation/GenerationForm';
import { HistoryTable } from '@/components/History/HistoryTable';
import { ConnectionForm } from '@/components/ServerSettings/ConnectionForm';
@@ -7,14 +7,63 @@ import { ModelManagement } from '@/components/ServerSettings/ModelManagement';
import { Toaster } from '@/components/ui/toaster';
import { ProfileList } from '@/components/VoiceProfiles/ProfileList';
import { Sidebar } from '@/components/Sidebar';
import { isTauri, startServer, stopServer } from '@/lib/tauri';
// Track if server is starting to prevent duplicate starts
let serverStarting = false;
function App() {
const [activeTab, setActiveTab] = useState('profiles');
const [serverReady, setServerReady] = useState(false);
// Auto-start server when running in Tauri
useEffect(() => {
if (!isTauri() || serverStarting) {
return;
}
serverStarting = true;
console.log('Running in Tauri, starting bundled server...');
startServer(false)
.then(() => {
console.log('Server is ready');
setServerReady(true);
})
.catch((error) => {
console.error('Failed to auto-start server:', error);
serverStarting = false;
});
// Cleanup: stop server on actual unmount (not StrictMode remount)
return () => {
// In production builds, we want to stop the server on unmount
// In dev mode, React StrictMode causes remounts, so we skip cleanup
if (import.meta.env?.PROD) {
stopServer().catch((error) => {
console.error('Failed to stop server on cleanup:', error);
});
serverStarting = false;
}
};
}, []);
// Show loading screen while server is starting in Tauri
if (isTauri() && !serverReady) {
return (
<div className="min-h-screen bg-background flex items-center justify-center">
<div className="text-center space-y-4">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-primary mx-auto"></div>
<p className="text-muted-foreground">Starting server...</p>
</div>
</div>
);
}
return (
<div className="min-h-screen bg-background flex">
<Sidebar activeTab={activeTab} onTabChange={setActiveTab} />
<main className="flex-1 ml-20">
<div className="container mx-auto px-8 py-8 max-w-7xl">
{activeTab === 'profiles' && (
@@ -14,13 +14,11 @@ import { useToast } from '@/components/ui/use-toast';
import { apiClient } from '@/lib/api/client';
import { useDeleteGeneration, useHistory } from '@/lib/hooks/useHistory';
import { formatDate, formatDuration } from '@/lib/utils/format';
import { useServerStore } from '@/stores/serverStore';
export function HistoryTable() {
const [page, setPage] = useState(0);
const limit = 20;
const { toast } = useToast();
const _serverUrl = useServerStore((state) => state.serverUrl);
const { data: historyData, isLoading } = useHistory({
limit,
@@ -1,14 +1,13 @@
import { Mic, Plus } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Card, CardContent } from '@/components/ui/card';
import { useDeleteProfile, useProfiles } from '@/lib/hooks/useProfiles';
import { useProfiles } from '@/lib/hooks/useProfiles';
import { useUIStore } from '@/stores/uiStore';
import { ProfileCard } from './ProfileCard';
import { ProfileForm } from './ProfileForm';
export function ProfileList() {
const { data: profiles, isLoading, error } = useProfiles();
const _deleteProfile = useDeleteProfile();
const setDialogOpen = useUIStore((state) => state.setProfileDialogOpen);
if (isLoading) {
+47
View File
@@ -0,0 +1,47 @@
/**
* Tauri integration utilities
*/
import { invoke } from '@tauri-apps/api/core';
/**
* Check if running in Tauri environment
*/
export function isTauri(): boolean {
return '__TAURI_INTERNALS__' in window;
}
/**
* Start the bundled Python server (Tauri only)
*/
export async function startServer(remote = false): Promise<string> {
if (!isTauri()) {
throw new Error('Not running in Tauri environment');
}
try {
const result = await invoke<string>('start_server', { remote });
console.log('Server started:', result);
return result;
} catch (error) {
console.error('Failed to start server:', error);
throw error;
}
}
/**
* Stop the bundled Python server (Tauri only)
*/
export async function stopServer(): Promise<void> {
if (!isTauri()) {
throw new Error('Not running in Tauri environment');
}
try {
await invoke('stop_server');
console.log('Server stopped');
} catch (error) {
console.error('Failed to stop server:', error);
throw error;
}
}