Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
7b1e229
Implement server management enhancements with window close handling
jamiepine Jan 25, 2026
edbdf0c
Update development scripts and add macOS icon assets
jamiepine Jan 25, 2026
e20795d
Update macOS icon configuration and add new assets
jamiepine Jan 25, 2026
e5bfa4c
fix icons
jamiepine Jan 25, 2026
c876fab
Enhance SampleUpload component with transcription functionality
jamiepine Jan 25, 2026
6fa2966
Add audio recording feature to SampleUpload component
jamiepine Jan 25, 2026
f80f870
Implement audio player component and integrate with history and sampl…
jamiepine Jan 25, 2026
d3ca3a9
Add landing page for voicebox.sh
jamiepine Jan 25, 2026
05036df
Enhance UI components and styles for improved user experience
jamiepine Jan 25, 2026
98cfe2d
Refactor App layout and enhance UI components for better usability
jamiepine Jan 25, 2026
0e38d47
Enhance UI components and styles for improved user experience
jamiepine Jan 25, 2026
7d1ee4c
Implement autoupdater functionality and enhance icon management
jamiepine Jan 25, 2026
041ca15
Refactor HistoryTable component for improved styling and structure
jamiepine Jan 25, 2026
45c4c2f
Update icon assets and improve icon management script
jamiepine Jan 26, 2026
e7e3a0a
Update dependencies and enhance UI components for better functionality
jamiepine Jan 26, 2026
586b19f
Update UI components and styles for improved functionality and aesthe…
jamiepine Jan 26, 2026
a1b0f26
Refactor HistoryTable and ProfileList components for improved UI and …
jamiepine Jan 26, 2026
a0302c0
Add framer-motion dependency and update HistoryTable and ProfileCard …
jamiepine Jan 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ jobs:
- uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
with:
projectPath: tauri
tagName: v__VERSION__
Expand All @@ -111,6 +113,9 @@ jobs:
- **macOS**: Download the `.dmg` file
- **Windows**: Download the `.msi` installer
- **Linux**: Download the `.AppImage` or `.deb` package

The app includes automatic updates - future updates will be installed automatically.
releaseDraft: true
prerelease: false
args: ${{ matrix.args }}
includeUpdaterJson: true
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ __pycache__/
venv/
env/
ENV/

*.prompt
# Build outputs
dist/
build/
Expand Down
2 changes: 1 addition & 1 deletion CURRENT_STATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ projects

## 💡 Development Workflow

1. **Start backend**: `bun run dev:backend` (or via Tauri)
1. **Start backend**: `bun run dev:server` (or via Tauri)
2. **Start frontend**: `bun run dev` (Tauri) or `bun run dev:web` (web)
3. **Generate API client**: `bun run generate:api` (after backend changes)
4. **Build server binary**: `bun run build:server` (for Tauri bundling)
Expand Down
42 changes: 23 additions & 19 deletions app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,38 @@
"check": "biome check --write src"
},
"dependencies": {
"@tauri-apps/api": "^2.0.0",
"react": "^18.3.0",
"react-dom": "^18.3.0",
"@tanstack/react-query": "^5.0.0",
"@tanstack/react-query-devtools": "^5.0.0",
"zustand": "^4.5.0",
"react-hook-form": "^7.53.0",
"@hookform/resolvers": "^3.9.0",
"zod": "^3.23.8",
"wavesurfer.js": "^7.0.0",
"lucide-react": "^0.454.0",
"date-fns": "^3.6.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"tailwind-merge": "^2.5.4",
"@radix-ui/react-alert-dialog": "^1.1.1",
"@radix-ui/react-avatar": "^1.1.0",
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-popover": "^1.1.1",
"@radix-ui/react-progress": "^1.1.0",
"@radix-ui/react-scroll-area": "^1.1.0",
"@radix-ui/react-select": "^2.1.1",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slider": "^1.3.6",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tabs": "^1.1.0",
"@radix-ui/react-toast": "^1.2.1",
"@radix-ui/react-popover": "^1.1.1",
"@radix-ui/react-progress": "^1.1.0",
"@radix-ui/react-scroll-area": "^1.1.0",
"@radix-ui/react-avatar": "^1.1.0",
"@radix-ui/react-alert-dialog": "^1.1.1"
"@tanstack/react-query": "^5.0.0",
"@tanstack/react-query-devtools": "^5.0.0",
"@tauri-apps/api": "^2.0.0",
"@tauri-apps/plugin-process": "^2.3.1",
"@tauri-apps/plugin-updater": "^2.9.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"date-fns": "^3.6.0",
"framer-motion": "^12.29.0",
"lucide-react": "^0.454.0",
"react": "^18.3.0",
"react-dom": "^18.3.0",
"react-hook-form": "^7.53.0",
"tailwind-merge": "^2.5.4",
"wavesurfer.js": "^7.0.0",
"zod": "^3.23.8",
"zustand": "^4.5.0"
},
"devDependencies": {
"@tailwindcss/vite": "^4.1.18",
Expand Down
128 changes: 82 additions & 46 deletions app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,73 @@ import { GenerationForm } from '@/components/Generation/GenerationForm';
import { HistoryTable } from '@/components/History/HistoryTable';
import { ConnectionForm } from '@/components/ServerSettings/ConnectionForm';
import { ServerStatus } from '@/components/ServerSettings/ServerStatus';
import { UpdateStatus } from '@/components/ServerSettings/UpdateStatus';
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';
import { AudioPlayer } from '@/components/AudioPlayer/AudioPlayer';
import { UpdateNotification } from '@/components/UpdateNotification';
import { isTauri, startServer, setupWindowCloseHandler } from '@/lib/tauri';

// Track if server is starting to prevent duplicate starts
let serverStarting = false;

function App() {
const [activeTab, setActiveTab] = useState('profiles');
const [activeTab, setActiveTab] = useState('main');
const [serverReady, setServerReady] = useState(false);

// Auto-start server when running in Tauri
// Setup window close handler and auto-start server when running in Tauri (production only)
useEffect(() => {
if (!isTauri() || serverStarting) {
if (!isTauri()) {
return;
}

// Setup window close handler to check setting and stop server if needed
// This works in both dev and prod, but will only stop server if it was started by the app
setupWindowCloseHandler().catch((error) => {
console.error('Failed to setup window close handler:', error);
});

// Only auto-start server in production mode
// In dev mode, user runs server separately
if (!import.meta.env?.PROD) {
console.log('Dev mode: Skipping auto-start of server (run it separately)');
setServerReady(true); // Mark as ready so UI doesn't show loading screen
// Mark that server was not started by app (so we don't try to stop it on close)
// @ts-expect-error - adding property to window
window.__voiceboxServerStartedByApp = false;
return;
}

// Auto-start server in production
if (serverStarting) {
return;
}

serverStarting = true;
console.log('Running in Tauri, starting bundled server...');
console.log('Production mode: Starting bundled server...');

startServer(false)
.then(() => {
console.log('Server is ready');
setServerReady(true);
// Mark that we started the server (so we know to stop it on close)
// @ts-expect-error - adding property to window
window.__voiceboxServerStartedByApp = true;
})
.catch((error) => {
console.error('Failed to auto-start server:', error);
serverStarting = false;
// @ts-expect-error - adding property to window
window.__voiceboxServerStartedByApp = false;
});

// Cleanup: stop server on actual unmount (not StrictMode remount)
// Note: Window close is handled separately in Tauri Rust code
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;
}
// Window close event handles server shutdown based on setting
serverStarting = false;
};
}, []);

Expand All @@ -61,40 +86,51 @@ function App() {
}

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' && (
<div className="space-y-4">
<ProfileList />
</div>
)}

{activeTab === 'generate' && (
<div className="space-y-4">
<GenerationForm />
</div>
)}

{activeTab === 'history' && (
<div className="space-y-4">
<HistoryTable />
</div>
)}

{activeTab === 'settings' && (
<div className="space-y-4">
<div className="grid gap-4 md:grid-cols-2">
<ConnectionForm />
<ServerStatus />
<div className="h-screen bg-background flex flex-col overflow-hidden">
<div className="flex flex-1 min-h-0 overflow-hidden">
<Sidebar activeTab={activeTab} onTabChange={setActiveTab} />

<main className="flex-1 ml-20 overflow-hidden flex flex-col">
<div className="container mx-auto px-8 py-8 max-w-[1800px] h-full overflow-hidden flex flex-col">
<UpdateNotification />

{activeTab === 'settings' ? (
<div className="space-y-4 overflow-y-auto">
<div className="grid gap-4 md:grid-cols-2">
<ConnectionForm />
<ServerStatus />
</div>
{isTauri() && <UpdateStatus />}
<ModelManagement />
</div>
<ModelManagement />
</div>
)}
</div>
</main>
) : (
// Main view: Profiles top left, Generator bottom left, History right
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 h-full min-h-0 overflow-hidden">
{/* Left Column */}
<div className="flex flex-col gap-6 min-h-0 overflow-y-auto pb-32">
{/* Profiles - Top Left */}
<div className="shrink-0 flex flex-col">
<ProfileList />
</div>

{/* Generator - Bottom Left */}
<div className="shrink-0">
<GenerationForm />
</div>
</div>

{/* Right Column - History */}
<div className="flex flex-col min-h-0 overflow-hidden">
<HistoryTable />
</div>
</div>
)}
</div>
</main>
</div>

{/* Audio Player - always visible except on settings */}
{activeTab !== 'settings' && <AudioPlayer />}

<Toaster />
</div>
Expand Down
Binary file added app/src/assets/voicebox-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading