feat(ui): persist selectedProfileId across sessions

Wrap useUIStore in zustand/middleware's persist under the key
voicebox-ui. partialize only selectedProfileId so volatile UI state
(dialog open flags, form drafts, engine/voice pickers, sidebar) stays
in-memory as before — but reopening the app no longer loses whichever
profile the user was last working with.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
This commit is contained in:
James Pine
2026-04-23 19:20:42 -07:00
co-authored by Claude Opus 4.7
parent 67a9e308a9
commit 687ab2aa16
+32 -23
View File
@@ -1,4 +1,5 @@
import { create } from 'zustand'; import { create } from 'zustand';
import { persist } from 'zustand/middleware';
// Draft state for the create voice profile form // Draft state for the create voice profile form
export interface ProfileFormDraft { export interface ProfileFormDraft {
@@ -49,33 +50,41 @@ interface UIStore {
setTheme: (theme: 'light' | 'dark') => void; setTheme: (theme: 'light' | 'dark') => void;
} }
export const useUIStore = create<UIStore>((set) => ({ export const useUIStore = create<UIStore>()(
sidebarOpen: true, persist(
setSidebarOpen: (open) => set({ sidebarOpen: open }), (set) => ({
sidebarOpen: true,
setSidebarOpen: (open) => set({ sidebarOpen: open }),
profileDialogOpen: false, profileDialogOpen: false,
setProfileDialogOpen: (open) => set({ profileDialogOpen: open }), setProfileDialogOpen: (open) => set({ profileDialogOpen: open }),
editingProfileId: null, editingProfileId: null,
setEditingProfileId: (id) => set({ editingProfileId: id }), setEditingProfileId: (id) => set({ editingProfileId: id }),
generationDialogOpen: false, generationDialogOpen: false,
setGenerationDialogOpen: (open) => set({ generationDialogOpen: open }), setGenerationDialogOpen: (open) => set({ generationDialogOpen: open }),
selectedProfileId: null, selectedProfileId: null,
setSelectedProfileId: (id) => set({ selectedProfileId: id }), setSelectedProfileId: (id) => set({ selectedProfileId: id }),
selectedEngine: 'qwen', selectedEngine: 'qwen',
setSelectedEngine: (engine) => set({ selectedEngine: engine }), setSelectedEngine: (engine) => set({ selectedEngine: engine }),
selectedVoiceId: null, selectedVoiceId: null,
setSelectedVoiceId: (id) => set({ selectedVoiceId: id }), setSelectedVoiceId: (id) => set({ selectedVoiceId: id }),
profileFormDraft: null, profileFormDraft: null,
setProfileFormDraft: (draft) => set({ profileFormDraft: draft }), setProfileFormDraft: (draft) => set({ profileFormDraft: draft }),
theme: 'light', theme: 'light',
setTheme: (theme) => { setTheme: (theme) => {
set({ theme }); set({ theme });
document.documentElement.classList.toggle('dark', theme === 'dark'); document.documentElement.classList.toggle('dark', theme === 'dark');
}, },
})); }),
{
name: 'voicebox-ui',
partialize: (state) => ({ selectedProfileId: state.selectedProfileId }),
},
),
);