mirror of
https://github.com/jamiepine/voicebox.git
synced 2026-09-19 06:40:38 -07:00
overhaul settings: split into routed sub-tabs, add server logs, changelog, reusable setting components
- Rename Server tab to Settings with horizontal sub-tab navigation (General, Generation, GPU, Logs, Changelog) - All sub-tabs are proper routes under /settings/* with /server redirect for backwards compat - General: connection settings, link cards (docs + discord), API reference card, app updates - Generation: auto-chunking, crossfade, normalize, autoplay as SettingRow components - GPU: info card with platform-aware icons (Apple logo for MPS), CUDA management, explainer text - Logs: real-time server log viewer piped from Tauri sidecar via event system (Tauri-only) - Changelog: parsed from CHANGELOG.md at build time via Vite virtual module plugin - New reusable SettingRow/SettingSection components for consistent settings layout - New Toggle (switch) UI component replacing checkboxes in settings - Toast viewport now offsets when audio player is open - Sidebar stays active on settings sub-routes (fuzzy matching)
This commit is contained in:
@@ -413,6 +413,10 @@ async fn start_server(
|
||||
tauri_plugin_shell::process::CommandEvent::Stdout(line) => {
|
||||
let line_str = String::from_utf8_lossy(&line);
|
||||
println!("Server output: {}", line_str);
|
||||
let _ = app.emit("server-log", serde_json::json!({
|
||||
"stream": "stdout",
|
||||
"line": line_str.trim_end(),
|
||||
}));
|
||||
|
||||
if line_str.contains("Uvicorn running") || line_str.contains("Application startup complete") {
|
||||
println!("Server is ready!");
|
||||
@@ -422,6 +426,10 @@ async fn start_server(
|
||||
tauri_plugin_shell::process::CommandEvent::Stderr(line) => {
|
||||
let line_str = String::from_utf8_lossy(&line).to_string();
|
||||
eprintln!("Server: {}", line_str);
|
||||
let _ = app.emit("server-log", serde_json::json!({
|
||||
"stream": "stderr",
|
||||
"line": line_str.trim_end(),
|
||||
}));
|
||||
|
||||
// Collect error lines for debugging
|
||||
if line_str.contains("ERROR") || line_str.contains("Error") || line_str.contains("Failed") {
|
||||
@@ -482,15 +490,26 @@ async fn start_server(
|
||||
}
|
||||
}
|
||||
|
||||
// Spawn task to continue reading output
|
||||
// Spawn task to continue reading output and emit to frontend
|
||||
let app_handle = app.clone();
|
||||
tokio::spawn(async move {
|
||||
while let Some(event) = rx.recv().await {
|
||||
match event {
|
||||
tauri_plugin_shell::process::CommandEvent::Stdout(line) => {
|
||||
println!("Server: {}", String::from_utf8_lossy(&line));
|
||||
let line_str = String::from_utf8_lossy(&line);
|
||||
println!("Server: {}", line_str);
|
||||
let _ = app_handle.emit("server-log", serde_json::json!({
|
||||
"stream": "stdout",
|
||||
"line": line_str.trim_end(),
|
||||
}));
|
||||
}
|
||||
tauri_plugin_shell::process::CommandEvent::Stderr(line) => {
|
||||
eprintln!("Server error: {}", String::from_utf8_lossy(&line));
|
||||
let line_str = String::from_utf8_lossy(&line);
|
||||
eprintln!("Server error: {}", line_str);
|
||||
let _ = app_handle.emit("server-log", serde_json::json!({
|
||||
"stream": "stderr",
|
||||
"line": line_str.trim_end(),
|
||||
}));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { emit, listen } from '@tauri-apps/api/event';
|
||||
import type { PlatformLifecycle } from '@/platform/types';
|
||||
import type { PlatformLifecycle, ServerLogEntry } from '@/platform/types';
|
||||
|
||||
class TauriLifecycle implements PlatformLifecycle {
|
||||
onServerReady?: () => void;
|
||||
@@ -86,6 +86,20 @@ class TauriLifecycle implements PlatformLifecycle {
|
||||
console.error('Failed to setup window close handler:', error);
|
||||
}
|
||||
}
|
||||
|
||||
subscribeToServerLogs(callback: (entry: ServerLogEntry) => void): () => void {
|
||||
let unlisten: (() => void) | null = null;
|
||||
|
||||
listen<ServerLogEntry>('server-log', (event) => {
|
||||
callback(event.payload);
|
||||
}).then((fn) => {
|
||||
unlisten = fn;
|
||||
});
|
||||
|
||||
return () => {
|
||||
unlisten?.();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const tauriLifecycle = new TauriLifecycle();
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import path from 'node:path';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import tailwindcss from '@tailwindcss/vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import { defineConfig } from 'vite';
|
||||
import { changelogPlugin } from '../app/plugins/changelog';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react(), tailwindcss()],
|
||||
plugins: [react(), tailwindcss(), changelogPlugin(path.resolve(__dirname, '..'))],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.resolve(__dirname, '../app/src'),
|
||||
|
||||
Reference in New Issue
Block a user