💄 native menu items
This commit is contained in:
@@ -11,7 +11,7 @@ import './styles/app.css'
|
||||
export default function App(): JSX.Element {
|
||||
const {
|
||||
setFileTree, activeFilePath, isDirty, markSaved, activeFileContent, theme, toggleTheme,
|
||||
loadSession, revisionPanelOpen, toggleRevisionPanel
|
||||
loadSession, revisionPanelOpen, toggleRevisionPanel, fontSize, setFontSize
|
||||
} = useEditorStore()
|
||||
const [sidebarOpen, setSidebarOpen] = useState(
|
||||
() => localStorage.getItem('sidebarOpen') !== 'false'
|
||||
@@ -27,6 +27,33 @@ export default function App(): JSX.Element {
|
||||
loadSession()
|
||||
}, [])
|
||||
|
||||
// Handle menu actions sent from the main process
|
||||
useEffect(() => {
|
||||
return window.api.onMenuAction(async (action) => {
|
||||
if (action === 'save') {
|
||||
if (activeFilePath && isDirty) {
|
||||
await window.api.writeFile(activeFilePath, activeFileContent)
|
||||
await window.api.saveRevision(activeFilePath, activeFileContent)
|
||||
markSaved()
|
||||
}
|
||||
} else if (action === 'toggleSidebar') {
|
||||
setSidebarOpen((v) => { const n = !v; localStorage.setItem('sidebarOpen', String(n)); return n })
|
||||
} else if (action === 'toggleChat') {
|
||||
setChatOpen((v) => { const n = !v; localStorage.setItem('chatOpen', String(n)); return n })
|
||||
} else if (action === 'toggleRevisions') {
|
||||
toggleRevisionPanel()
|
||||
} else if (action === 'toggleTheme') {
|
||||
toggleTheme()
|
||||
} else if (action === 'fontIncrease') {
|
||||
setFontSize(fontSize + 1)
|
||||
} else if (action === 'fontDecrease') {
|
||||
setFontSize(fontSize - 1)
|
||||
} else if (action === 'fontReset') {
|
||||
setFontSize(15)
|
||||
}
|
||||
})
|
||||
}, [activeFilePath, isDirty, activeFileContent, fontSize])
|
||||
|
||||
// Handle Cmd+S / Ctrl+S
|
||||
useEffect(() => {
|
||||
const handler = async (e: KeyboardEvent): Promise<void> => {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { EditorState, StateField, StateEffect, Annotation, RangeSetBuilder, Comp
|
||||
import { markdown } from '@codemirror/lang-markdown'
|
||||
import { syntaxHighlighting, defaultHighlightStyle } from '@codemirror/language'
|
||||
import { history, defaultKeymap, historyKeymap, invertedEffects, selectAll, indentLess } from '@codemirror/commands'
|
||||
import { search, searchKeymap } from '@codemirror/search'
|
||||
import { search, searchKeymap, openSearchPanel } from '@codemirror/search'
|
||||
import { marked } from 'marked'
|
||||
import DOMPurify from 'dompurify'
|
||||
import { useEditorStore } from '../../store/editorStore'
|
||||
@@ -632,6 +632,14 @@ export function MarkdownEditor(): JSX.Element {
|
||||
view.dispatch({ effects: themeCompartment.reconfigure(buildTheme(fontSize, theme === 'dark')) })
|
||||
}, [fontSize, theme])
|
||||
|
||||
useEffect(() => {
|
||||
return window.api.onMenuAction((action) => {
|
||||
if (action === 'find' && viewRef.current) {
|
||||
openSearchPanel(viewRef.current)
|
||||
}
|
||||
})
|
||||
}, [])
|
||||
|
||||
function handleContextMenu(e: React.MouseEvent): void {
|
||||
if (!activeFilePath) return
|
||||
e.preventDefault()
|
||||
|
||||
1
src/renderer/types/global.d.ts
vendored
1
src/renderer/types/global.d.ts
vendored
@@ -25,6 +25,7 @@ declare global {
|
||||
moveFile: (sourcePath: string, targetDirPath: string) => Promise<string>
|
||||
openStoryBible: () => Promise<{ path: string; content: string }>
|
||||
writeStoryBible: (content: string) => Promise<string>
|
||||
onMenuAction: (handler: (action: string) => void) => () => void
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user