feat: ship v1.2.0 Wave 1 foundation with book settings, chapter management, and focus mode
Deliver schema v9, book/chapter IPC extensions, BookSettingsTab, chapter meta/tags, AI session menu, focus mode and TTS, template context enrich, and Wave 1 E2E coverage. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+33
-2
@@ -18,10 +18,14 @@ import { useEditStore } from '@renderer/stores/useEditStore'
|
||||
import { SearchModal } from '@renderer/components/search/SearchModal'
|
||||
import { InspirationModal } from '@renderer/components/inspiration/InspirationModal'
|
||||
import { ImportBookModal } from '@renderer/components/import/ImportBookModal'
|
||||
import { FocusModeOverlay } from '@renderer/components/focus/FocusModeOverlay'
|
||||
import { NamingCheckModal } from '@renderer/components/ai/NamingCheckModal'
|
||||
import { useSearchStore } from '@renderer/stores/useSearchStore'
|
||||
import { useReferenceStore } from '@renderer/stores/useReferenceStore'
|
||||
import { flushEditorSave } from '@renderer/components/editor/TipTapEditor'
|
||||
import { getEditorTextForTts } from '@renderer/lib/editor-commands'
|
||||
import { insertLandmarkInEditor } from '@renderer/lib/editor-commands'
|
||||
import { isSpeaking, speakText, stopSpeaking } from '@renderer/lib/tts-controller'
|
||||
import { useAiStore } from '@renderer/stores/useAiStore'
|
||||
import { useExportStore } from '@renderer/stores/useExportStore'
|
||||
import { ipcCall } from '@renderer/lib/ipc-client'
|
||||
@@ -30,6 +34,10 @@ function AppInner(): React.JSX.Element {
|
||||
const { t } = useTranslation()
|
||||
const view = useAppStore((s) => s.view)
|
||||
const toast = useAppStore((s) => s.toast)
|
||||
const focusMode = useAppStore((s) => s.focusMode)
|
||||
const namingCheckOpen = useAppStore((s) => s.namingCheckOpen)
|
||||
const setFocusMode = useAppStore((s) => s.setFocusMode)
|
||||
const setNamingCheckOpen = useAppStore((s) => s.setNamingCheckOpen)
|
||||
const showToast = useAppStore((s) => s.showToast)
|
||||
const setView = useAppStore((s) => s.setView)
|
||||
const { loaded, onboardingCompleted, load: loadSettings } = useSettingsStore()
|
||||
@@ -158,27 +166,50 @@ function AppInner(): React.JSX.Element {
|
||||
useExportStore.getState().openModal()
|
||||
return
|
||||
}
|
||||
if (action === 'focusMode') {
|
||||
if (view !== 'editor') return
|
||||
setFocusMode(!useAppStore.getState().focusMode)
|
||||
return
|
||||
}
|
||||
if (action === 'toggleTTS') {
|
||||
if (view !== 'editor') return
|
||||
if (isSpeaking()) {
|
||||
stopSpeaking()
|
||||
showToast(t('tts.stopped'))
|
||||
return
|
||||
}
|
||||
const text = getEditorTextForTts()
|
||||
if (!text.trim()) {
|
||||
showToast(t('tts.noText'))
|
||||
return
|
||||
}
|
||||
speakText(text)
|
||||
showToast(t('tts.started'))
|
||||
return
|
||||
}
|
||||
showToast(t('feature.comingSoon'))
|
||||
})
|
||||
return unsub
|
||||
}, [view, activeTabId, openTabs, openBook, setView, showToast, t])
|
||||
}, [view, activeTabId, openTabs, openBook, setView, setFocusMode, showToast, t])
|
||||
|
||||
const handleOnboardingComplete = (): void => {
|
||||
setShowOnboarding(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<div id="app">
|
||||
<div id="app" className={focusMode ? 'focus-mode' : undefined} data-testid="app-root">
|
||||
<TopBar />
|
||||
<div id="main-area">
|
||||
{view === 'home' && <HomePage />}
|
||||
{view === 'editor' && <EditorLayout />}
|
||||
{view === 'settings' && <SettingsPage />}
|
||||
</div>
|
||||
<FocusModeOverlay />
|
||||
{showOnboarding && <OnboardingWizard onComplete={handleOnboardingComplete} />}
|
||||
<SearchModal />
|
||||
<InspirationModal />
|
||||
<ImportBookModal />
|
||||
<NamingCheckModal open={namingCheckOpen} onClose={() => setNamingCheckOpen(false)} />
|
||||
{toast && <div className="toast">{toast}</div>}
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user