openpencil/src/app/shell/menu/use.ts
2026-05-17 14:44:37 +03:00

93 lines
2.9 KiB
TypeScript

import { tryOnScopeDispose } from '@vueuse/core'
import { useEditorCommands, useI18n } from '@open-pencil/vue'
import type { EditorCommandId } from '@open-pencil/vue'
import { useEditorStore } from '@/app/editor/active-store'
import { createSharedEditorMenuActions } from '@/app/shell/menu/editor-actions'
import { importFileDialog, openFileDialog } from '@/app/shell/menu/files'
import { useAppTheme } from '@/app/shell/theme'
import { checkForAppUpdate } from '@/app/shell/updater'
import { createTab, closeTab, activeTab } from '@/app/tabs'
import { isTauri } from '@/app/tauri/env'
const store = useEditorStore()
const COMMAND_MENU_IDS = new Set<string>([
'edit.undo',
'edit.redo',
'selection.selectAll',
'selection.duplicate',
'selection.delete',
'selection.group',
'selection.ungroup',
'selection.createComponent',
'selection.createComponentSet',
'selection.detachInstance',
'selection.wrapInAutoLayout',
'selection.bringToFront',
'selection.sendToBack',
'view.zoom100',
'view.zoomFit',
'view.zoomSelection'
])
export { importFileDialog, openFileDialog }
export { openFileFromPath } from '@/app/shell/menu/files'
function execBrowserCommand(command: 'copy' | 'cut' | 'paste'): void {
document.execCommand(command)
}
export function useMenu() {
if (!isTauri()) return
let unlisten: (() => void) | undefined
const { setTheme } = useAppTheme()
const { dialogs } = useI18n()
const { runCommand } = useEditorCommands()
const actions: Partial<Record<string, () => void>> = {
new: () => createTab(),
open: () => void openFileDialog(),
close: () => {
if (activeTab.value) closeTab(activeTab.value.id)
},
save: () => void store.saveFigFile(),
'save-as': () => void store.saveFigFileAs(),
'export-selection': () => {
if (store.state.selectedIds.size > 0) void store.exportSelection(1, 'png')
},
'export-png': () => {
if (store.state.selectedIds.size > 0) void store.exportSelection(1, 'png')
},
'export-svg': () => {
if (store.state.selectedIds.size > 0) void store.exportSelection(1, 'svg')
},
'export-fig': () => {
if (store.state.selectedIds.size > 0) void store.exportSelection(1, 'fig')
},
autosave: () => {
store.state.autosaveEnabled = !store.state.autosaveEnabled
},
copy: () => execBrowserCommand('copy'),
cut: () => execBrowserCommand('cut'),
paste: () => execBrowserCommand('paste'),
'check-updates': () => void checkForAppUpdate({ messages: dialogs }),
...createSharedEditorMenuActions(setTheme)
}
void import('@tauri-apps/api/event').then(({ listen }) => {
void listen<string>('menu-event', (event) => {
if (COMMAND_MENU_IDS.has(event.payload)) {
runCommand(event.payload as EditorCommandId)
return
}
actions[event.payload]?.()
}).then((fn) => {
unlisten = fn
})
})
tryOnScopeDispose(() => unlisten?.())
}