105 lines
4.3 KiB
JavaScript
105 lines
4.3 KiB
JavaScript
import { create } from 'zustand';
|
|
import { persistSet } from '../lib/persistence';
|
|
|
|
export const useAppStore = create((set, get) => ({
|
|
// --- Chapter State ---
|
|
chapters: [],
|
|
activeChapterId: null,
|
|
activeWorkId: typeof window !== 'undefined' ? localStorage.getItem('author-active-work') || null : null,
|
|
setChapters: (chapters) => set({ chapters: Array.isArray(chapters) ? chapters.filter(ch => ch && typeof ch === 'object' && ch.id) : [] }),
|
|
setActiveChapterId: (id) => set({ activeChapterId: id }),
|
|
setActiveWorkId: (id) => set({ activeWorkId: id }),
|
|
addChapter: (chapter) => set((state) => ({ chapters: [...state.chapters, chapter] })),
|
|
deleteChapter: (id) => set((state) => ({ chapters: state.chapters.filter((ch) => ch.id !== id) })),
|
|
updateChapter: (id, updates) => set((state) => ({
|
|
chapters: state.chapters.map((ch) => (ch.id === id ? { ...ch, ...updates } : ch))
|
|
})),
|
|
|
|
// --- UI State ---
|
|
sidebarOpen: true,
|
|
setSidebarOpen: (open) => set({ sidebarOpen: open }),
|
|
toggleSidebar: () => set((state) => ({ sidebarOpen: !state.sidebarOpen })),
|
|
|
|
aiSidebarOpen: false,
|
|
setAiSidebarOpen: (open) => set({ aiSidebarOpen: open }),
|
|
toggleAiSidebar: () => set((state) => ({ aiSidebarOpen: !state.aiSidebarOpen })),
|
|
|
|
showSettings: false,
|
|
setShowSettings: (show) => set({ showSettings: show }),
|
|
|
|
jumpToNodeId: null,
|
|
setJumpToNodeId: (id) => set({ jumpToNodeId: id }),
|
|
|
|
showSnapshots: false,
|
|
setShowSnapshots: (show) => set({ showSnapshots: show }),
|
|
|
|
theme: 'light',
|
|
setTheme: (theme) => set({ theme }),
|
|
|
|
writingMode: 'webnovel',
|
|
setWritingMode: (mode) => set({ writingMode: mode }),
|
|
|
|
// --- Localization & Theming ---
|
|
language: typeof window !== 'undefined' ? localStorage.getItem('author-lang') || null : null,
|
|
setLanguage: (lang) => set(() => {
|
|
if (typeof window !== 'undefined') {
|
|
localStorage.setItem('author-lang', lang);
|
|
persistSet('author-lang', lang).catch(() => { });
|
|
}
|
|
return { language: lang };
|
|
}),
|
|
|
|
visualTheme: typeof window !== 'undefined' ? localStorage.getItem('author-visual') || null : null,
|
|
setVisualTheme: (vTheme) => set(() => {
|
|
if (typeof window !== 'undefined') {
|
|
localStorage.setItem('author-visual', vTheme);
|
|
persistSet('author-visual', vTheme).catch(() => { });
|
|
}
|
|
return { visualTheme: vTheme };
|
|
}),
|
|
|
|
startTour: false,
|
|
setStartTour: (val) => set({ startTour: val }),
|
|
|
|
// --- Toast ---
|
|
toast: null,
|
|
setToast: (toast) => {
|
|
set({ toast });
|
|
if (toast) {
|
|
setTimeout(() => set({ toast: null }), 3000);
|
|
}
|
|
},
|
|
showToast: (message, type = 'info') => get().setToast({ message, type }),
|
|
|
|
// --- Context & Settings (RAG Preparation) ---
|
|
contextSelection: typeof window !== 'undefined' && localStorage.getItem('author-context-selection')
|
|
? new Set(JSON.parse(localStorage.getItem('author-context-selection')))
|
|
: new Set(),
|
|
setContextSelection: (selection) => set((state) => {
|
|
const newSelection = typeof selection === 'function' ? selection(state.contextSelection) : selection;
|
|
if (typeof window !== 'undefined') {
|
|
const arr = Array.from(newSelection);
|
|
localStorage.setItem('author-context-selection', JSON.stringify(arr));
|
|
persistSet('author-context-selection', arr).catch(() => { });
|
|
}
|
|
return { contextSelection: newSelection };
|
|
}),
|
|
|
|
contextItems: [],
|
|
setContextItems: (items) => set({ contextItems: items }),
|
|
|
|
settingsVersion: 0,
|
|
incrementSettingsVersion: () => set((state) => ({ settingsVersion: state.settingsVersion + 1 })),
|
|
|
|
// --- AI Chat & Generation State ---
|
|
sessionStore: { activeSessionId: null, sessions: [] },
|
|
setSessionStore: (action) => set((state) => ({ sessionStore: typeof action === 'function' ? action(state.sessionStore) : action })),
|
|
|
|
chatStreaming: false,
|
|
setChatStreaming: (streaming) => set({ chatStreaming: streaming }),
|
|
|
|
generationArchive: [],
|
|
setGenerationArchive: (archive) => set({ generationArchive: typeof archive === 'function' ? archive(get().generationArchive) : archive }),
|
|
addGenerationArchive: (record) => set((state) => ({ generationArchive: [...state.generationArchive, record] })),
|
|
}));
|