diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index edd533d..6eda494 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -81,6 +81,9 @@ pub fn run() { &MenuItem::with_id(app, "statistics", "Statistics", true, Some("CmdOrCtrl+Shift+I"))?, &MenuItem::with_id(app, "scene-cards", "Scene Cards", true, Some("CmdOrCtrl+Shift+K"))?, &MenuItem::with_id(app, "story-mode", "Story Mode", true, Some("CmdOrCtrl+Shift+L"))?, + &PredefinedMenuItem::separator(app)?, + &MenuItem::with_id(app, "toggle-sidebar", "Toggle Sidebar", true, Some("CmdOrCtrl+B"))?, + &MenuItem::with_id(app, "edit-meta", "Edit Meta Data", true, None::<&str>)?, ], )?; @@ -120,6 +123,8 @@ pub fn run() { "statistics" => { let _ = app.emit("menu-statistics", ()); } "scene-cards" => { let _ = app.emit("menu-scene-cards", ()); } "story-mode" => { let _ = app.emit("menu-story-mode", ()); } + "toggle-sidebar" => { let _ = app.emit("menu-toggle-sidebar", ()); } + "edit-meta" => { let _ = app.emit("menu-edit-meta", ()); } "find" => { let _ = app.emit("menu-find", ()); } "find-replace" => { let _ = app.emit("menu-find-replace", ()); } "quit" => { let _ = app.emit("menu-quit", ()); } diff --git a/src/lib/components/Editor.svelte b/src/lib/components/Editor.svelte index e76d6c7..37720df 100644 --- a/src/lib/components/Editor.svelte +++ b/src/lib/components/Editor.svelte @@ -13,6 +13,7 @@ import { findReplacePlugin } from '$lib/editor/findReplace'; import FindReplaceBar from '$lib/components/FindReplaceBar.svelte'; import { InputModeManager } from '$lib/editor/input/InputModeManager'; + import SettingsModal from '$lib/components/SettingsModal.svelte'; import { documentStore } from '$lib/stores/documentStore.svelte'; import { editorStore } from '$lib/stores/editorStore.svelte'; @@ -25,22 +26,14 @@ let view: EditorView | null = null; const inputManager = InputModeManager.getInstance(); - // Svelte 5 runes for reactive state - let currentMode = $state<'ENGLISH' | 'MALAYALAM'>('ENGLISH'); - let currentElement = $state('SCENE HEADING'); - let modeFlash = $state(false); - let currentScheme = $state<'inscript1' | 'inscript2' | 'mozhi'>('mozhi'); - // Map the font setting slug to a CSS font-family name let fontFamily = $derived( documentStore.currentFont === 'manjari' ? 'Manjari' : 'Noto Sans Malayalam' ); - /** Switch the active Malayalam input scheme and update local state */ - function selectScheme(scheme: 'inscript1' | 'inscript2' | 'mozhi') { - currentScheme = scheme; - inputManager.setScheme(scheme); - } + // Svelte 5 runes for reactive state + let currentElement = $state('SCENE HEADING'); + let showSettings = $state(false); // Create initial document with one empty scene_heading function createInitialDoc() { @@ -172,14 +165,7 @@ if (event.ctrlKey && event.code === 'Space') { event.preventDefault(); event.stopPropagation(); - const isNowMalayalam = inputManager.toggle(); - currentMode = isNowMalayalam ? 'MALAYALAM' : 'ENGLISH'; - // When toggling to Malayalam mode, ensure currentScheme reflects the manager's state - currentScheme = inputManager.scheme; - - // Brief flash on the mode indicator for visual feedback - modeFlash = true; - setTimeout(() => { modeFlash = false; }, 500); + inputManager.toggle(); return; } @@ -259,34 +245,22 @@
- - {currentMode} - - {#if currentMode === 'MALAYALAM'} - | - - - - - - {/if} +
{currentElement}
+ + diff --git a/src/lib/components/TitleBar.svelte b/src/lib/components/TitleBar.svelte index 2493e7f..ca6c557 100644 --- a/src/lib/components/TitleBar.svelte +++ b/src/lib/components/TitleBar.svelte @@ -1,11 +1,10 @@
- - - +
@@ -63,34 +46,19 @@
- - - - -
- - -
- - -
- diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 4ea1ba6..132e369 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -11,6 +11,7 @@ import AboutModal from '$lib/components/AboutModal.svelte'; import HelpModal from '$lib/components/HelpModal.svelte'; import StatisticsModal from '$lib/components/StatisticsModal.svelte'; + import MetadataModal from '$lib/components/MetadataModal.svelte'; import { documentStore } from '$lib/stores/documentStore.svelte'; import { themeStore } from '$lib/stores/themeStore.svelte'; @@ -22,6 +23,7 @@ let findReplaceOpen = $state(false); let findReplaceMode = $state<'find' | 'replace'>('find'); let showStatistics = $state(false); + let showMetadata = $state(false); // Module-level guard — prevents newDocument() from firing again on HMR re-mount let appInitialized = false; @@ -113,98 +115,98 @@ window.addEventListener('keydown', handleGlobalKeydown); + let unlistens: (() => void)[] = []; + // Listen for native menu events emitted from the Rust backend. // Each custom menu item (New, Open, Save, Save As) emits an event // that we handle here to call the appropriate store method. - const unlistenNew = await listen('menu-new', async () => { - if (!(await documentStore.confirmIfDirty())) return; - await documentStore.newDocument(); - }); - - const unlistenOpen = await listen('menu-open', async () => { - if (!(await documentStore.confirmIfDirty())) return; - const path = await open({ - multiple: false, - filters: [{ name: 'Screenplay', extensions: ['screenplay'] }] - }); - if (typeof path === 'string') { - await documentStore.openDocument(path); - } - }); - - const unlistenSave = await listen('menu-save', () => { - documentStore.saveWithDialog(); - }); - - const unlistenSaveAs = await listen('menu-save-as', () => { - documentStore.saveAsDialog(); - }); - - const unlistenAbout = await listen('menu-about', () => { - showAbout = true; - }); - - const unlistenHelpGuide = await listen('menu-help-guide', () => { - showHelp = true; - }); - - const unlistenStatistics = await listen('menu-statistics', () => { - showStatistics = true; - }); - - const unlistenSceneCards = await listen('menu-scene-cards', () => { - showSceneCards = !showSceneCards; - }); - - const unlistenStoryMode = await listen('menu-story-mode', () => { - showStoryMode = !showStoryMode; - }); - - const unlistenFind = await listen('menu-find', () => { - findReplaceOpen = true; - findReplaceMode = 'find'; - }); - - const unlistenFindReplace = await listen('menu-find-replace', () => { - findReplaceOpen = true; - findReplaceMode = 'replace'; - }); - - const unlistenQuit = await listen('menu-quit', async () => { - if (!(await documentStore.confirmIfDirty())) return; - quitConfirmed = true; - await getCurrentWindow().close(); - }); - - // Intercept window close to prompt for unsaved changes - const unlistenClose = await getCurrentWindow().onCloseRequested(async (event) => { - if (quitConfirmed) return; // Already confirmed via menu-quit - if (!(await documentStore.confirmIfDirty())) { - event.preventDefault(); - } - }); + (async () => { + unlistens.push(await listen('menu-new', async () => { + if (!(await documentStore.confirmIfDirty())) return; + await documentStore.newDocument(); + })); + + unlistens.push(await listen('menu-open', async () => { + if (!(await documentStore.confirmIfDirty())) return; + const path = await open({ + multiple: false, + filters: [{ name: 'Screenplay', extensions: ['screenplay'] }] + }); + if (typeof path === 'string') { + await documentStore.openDocument(path); + } + })); + + unlistens.push(await listen('menu-save', () => { + documentStore.saveWithDialog(); + })); + + unlistens.push(await listen('menu-save-as', () => { + documentStore.saveAsDialog(); + })); + + unlistens.push(await listen('menu-about', () => { + showAbout = true; + })); + + unlistens.push(await listen('menu-help-guide', () => { + showHelp = true; + })); + + unlistens.push(await listen('menu-statistics', () => { + showStatistics = true; + })); + + unlistens.push(await listen('menu-scene-cards', () => { + showSceneCards = !showSceneCards; + })); + + unlistens.push(await listen('menu-story-mode', () => { + showStoryMode = !showStoryMode; + })); + + unlistens.push(await listen('menu-find', () => { + findReplaceOpen = true; + findReplaceMode = 'find'; + })); + + unlistens.push(await listen('menu-find-replace', () => { + findReplaceOpen = true; + findReplaceMode = 'replace'; + })); + + unlistens.push(await listen('menu-toggle-sidebar', () => { + panelOpen = !panelOpen; + })); + + unlistens.push(await listen('menu-edit-meta', () => { + showMetadata = true; + })); + + unlistens.push(await listen('menu-quit', async () => { + if (!(await documentStore.confirmIfDirty())) return; + quitConfirmed = true; + await getCurrentWindow().close(); + })); + + // Intercept window close to prompt for unsaved changes + unlistens.push(await getCurrentWindow().onCloseRequested(async (event) => { + if (quitConfirmed) return; // Already confirmed via menu-quit + if (!(await documentStore.confirmIfDirty())) { + event.preventDefault(); + } + })); + })(); return () => { window.removeEventListener('keydown', handleGlobalKeydown); - unlistenNew(); - unlistenOpen(); - unlistenSave(); - unlistenSaveAs(); - unlistenAbout(); - unlistenHelpGuide(); - unlistenStatistics(); - unlistenSceneCards(); - unlistenStoryMode(); - unlistenFind(); - unlistenFindReplace(); - unlistenQuit(); - unlistenClose(); + unlistens.forEach((fn) => fn()); }; });
- + { panelOpen = !panelOpen; }} />
{#if showSceneCards} { showSceneCards = false; }} /> @@ -222,6 +224,7 @@ +