UNPKG

p3x-onenote

Version:
553 lines (517 loc) 21.5 kB
import { app, dialog, Menu, shell, nativeTheme } from 'electron' import menus from '../menus.mjs' import action from '../action.mjs' import mainTray from './tray.mjs' import naturalCompareDocument from '../../lib/natural-compare-document.mjs' import relaunch from '../actions/relaunch.mjs' import registry from '../../registry.mjs' import notify from '../notify.mjs' function mainMenu() { const copyLocation = { label: registry.lang.label.copyLocation, click: () => { registry.window.onenote.webContents.send('p3x-onenote-action', { action: 'get-location' }) } } const minimizationBehaviorLabel = !registry.disableHide ? registry.lang.label.disableHide.no : registry.lang.label.disableHide.yes const languageCheckbox = []; languageCheckbox.push({ label: registry.lang.menu.language.auto || 'Auto (system)', type: 'radio', checked: registry.conf.get('lang') === 'auto', click: () => { registry.conf.set('lang', 'auto') const detected = registry.detectOsLocale() registry.translationKey = detected registry.lang = registry.translations[detected] mainMenu() mainTray() registry.window.onenote.webContents.send('p3x-onenote-language', { translation: detected, }) } }); for (let trans of Object.keys(registry.lang.menu.language.translations)) { const transLabel = registry.lang.menu.language.translations[trans] const transMenu = ((trans) => { return { label: transLabel, type: 'radio', checked: registry.conf.get('lang') === trans, click: () => { registry.conf.set('lang', trans) registry.translationKey = trans registry.lang = registry.translations[trans] mainMenu() mainTray() registry.window.onenote.webContents.send('p3x-onenote-language', { translation: trans, }) } } })(trans) languageCheckbox.push(transMenu) } const bookmarksMenu = [ { label: registry.lang.bookmarks.add, click: () => { registry.window.onenote.webContents.send('p3x-onenote-action-bookmark-add', { edit: false, }) } }, { label: registry.lang.bookmarks.importBookmarks || 'Import bookmarks', click: async () => { try { const result = await registry.window.onenote.webContents.executeJavaScript( `window.electronShim.ipcRenderer.invoke('p3x-onenote-bookmarks-import')` ) if (result && result.success) { const msg = registry.lang.bookmarks.imported ? registry.lang.bookmarks.imported(result.added) : `Imported ${result.added} bookmark(s).` notify(msg) } } catch (e) { console.error(e) } } }, ] const bookmarks = registry.conf.get('bookmarks') || [] if (bookmarks.length > 0) { bookmarksMenu.push({ label: registry.lang.bookmarks.exportBookmarks || 'Export bookmarks', click: async () => { try { const result = await registry.window.onenote.webContents.executeJavaScript( `window.electronShim.ipcRenderer.invoke('p3x-onenote-bookmarks-export')` ) if (result && result.success) { notify(registry.lang.bookmarks.exported || 'Bookmarks exported.') } } catch (e) { console.error(e) } } }) bookmarksMenu.push({ label: registry.lang.bookmarks?.manager || 'Manage bookmarks', click: () => { registry.window.onenote.webContents.send('p3x-onenote-action', { action: 'bookmark-manager', }) } }) bookmarksMenu.push({ type: 'separator' }) } let bookmarksSort = bookmarks.sort(naturalCompareDocument({ byProperty: 'title' })) // Build bookmark tree from folder paths (using / as separator) const tree = { items: [], children: {} }; for (let bookmarkIndex in bookmarksSort) { const bookmark = bookmarksSort[bookmarkIndex] const thisBookmarkIndex = bookmarkIndex const menuItem = { label: bookmark.title, click: () => { registry.window.onenote.webContents.send('p3x-onenote-action-bookmark-open', bookmark) } } if (bookmark.category) { const parts = bookmark.category.split('/').map(p => p.trim()).filter(p => p); let node = tree; for (const part of parts) { if (!node.children[part]) { node.children[part] = { items: [], children: {} }; } node = node.children[part]; } node.items.push(menuItem); } else { tree.items.push(menuItem); } } // Recursively build menu from tree function buildTreeMenu(node) { const result = []; // Add items at this level for (const item of node.items) { result.push(item); } // Add child folders sorted alphabetically const childKeys = Object.keys(node.children).sort((a, b) => a.localeCompare(b)); for (const key of childKeys) { result.push({ label: '📁 ' + key, submenu: buildTreeMenu(node.children[key]), }); } return result; } const treeMenu = buildTreeMenu(tree); for (const item of treeMenu) { bookmarksMenu.push(item); } const template = [ { label: registry.title, submenu: menus.default(), }, { label: registry.lang.bookmarks.title, submenu: bookmarksMenu }, { label: registry.lang.menu.action, submenu: [ copyLocation, { label: registry.lang.label.openUrl, click: () => { registry.window.onenote.webContents.send('p3x-onenote-action-open-url') } }, {type: 'separator'}, { label: registry.lang.tabs?.restoreClosedTab || 'Restore last closed tab', click: () => { registry.window.onenote.webContents.send('p3x-onenote-action', { action: 'restore-closed-tab', }) } } ] }, { label: registry.lang.label.settings, submenu: [ { label: registry.lang.label.hideMenu, type: 'checkbox', checked: registry.optionToHideMenu, click: () => { try { registry.optionToHideMenu = !registry.optionToHideMenu registry.conf.set('option-to-hide-menu', registry.optionToHideMenu,); if (!registry.optionToHideMenu) { registry.window.onenote.setAutoHideMenuBar(false) registry.window.onenote.setMenuBarVisibility(true) } else { const message = ` ${registry.lang.label.optionToHideMenuState.yes} ${registry.lang.restart} ${registry.lang.slow} ` dialog.showMessageBox( registry.window.onenote, { type: 'info', // title: registry.lang.dialog.minimizationBehavior.title, message: message, buttons: [registry.lang.button.ok] }).then(() => { relaunch() }).catch(e => console.error(e)) } } catch(e) { console.error(e) } } }, { label: registry.lang.label.disableHide.checkbox, type: 'checkbox', checked: !registry.disableHide, click: () => { try { registry.disableHide = !registry.disableHide; registry.conf.set('disable-hide', registry.disableHide); let message = registry.disableHide ? registry.lang.label.disableHide.message.yes : registry.lang.label.disableHide.message.no if (registry.disableHide === true && registry.tray !== undefined) { message += `\n\n${registry.lang.restart}\n\n${registry.lang.slow}` } dialog.showMessageBox(registry.window.onenote, { type: 'info', title: registry.lang.dialog.minimizationBehavior.title, message: message, buttons: [registry.lang.button.ok] }).then(() => { mainMenu() mainTray({ allowQuit: true }) }) } catch(e) { console.error(e) } } }, { label: registry.lang.label.optionToDisableInternalExternalPopup, type: 'checkbox', checked: registry.optionToDisableInternalExternalPopup, click: () => { registry.optionToDisableInternalExternalPopup = !registry.optionToDisableInternalExternalPopup; registry.conf.set('option-to-disable-internal-external-popup', registry.optionToDisableInternalExternalPopup); mainMenu() mainTray() } }, { label: registry.lang.label.desktopNotifications || 'Enable desktop notifications', type: 'checkbox', checked: registry.conf.get('desktopNotifications', false), click: () => { const current = registry.conf.get('desktopNotifications', false) registry.conf.set('desktopNotifications', !current) mainMenu() mainTray() } }, // Auto-launch on login — not available on Snap/Flatpak ...(!process.env.SNAP && !process.env.SNAP_NAME && !process.env.FLATPAK_ID ? [{ label: registry.lang.label.startOnLogin || 'Start on login', type: 'checkbox', checked: registry.conf.get('startOnLogin', false), click: () => { const newValue = !registry.conf.get('startOnLogin', false) registry.conf.set('startOnLogin', newValue) app.setLoginItemSettings({ openAtLogin: newValue, openAsHidden: true, }) mainMenu() mainTray() } }] : []), { label: registry.lang.label.setProxy, click: action.setProxy, }, { label: registry.lang.label.darkThemeInvert?.title || 'Dark mode (using invert)', submenu: [ { label: registry.lang.label.darkThemeInvert?.off || 'Off', type: 'radio', checked: registry.darkThemeMode === 'off', click: () => { registry.darkThemeMode = 'off' registry.conf.set('darkThemeMode', 'off') registry.darkThemeInvert = false registry.conf.set('darkThemeInvert', false) registry.window.onenote.webContents.send('p3x-onenote-action', { action: 'dark-theme-invert', darkThemeInvert: false, }) }, }, { label: registry.lang.label.darkThemeInvert?.on || 'On', type: 'radio', checked: registry.darkThemeMode === 'on', click: () => { registry.darkThemeMode = 'on' registry.conf.set('darkThemeMode', 'on') registry.darkThemeInvert = true registry.conf.set('darkThemeInvert', true) registry.window.onenote.webContents.send('p3x-onenote-action', { action: 'dark-theme-invert', darkThemeInvert: true, }) }, }, { label: registry.lang.label.darkThemeInvert?.system || 'Follow system', type: 'radio', checked: registry.darkThemeMode === 'system', click: () => { registry.darkThemeMode = 'system' registry.conf.set('darkThemeMode', 'system') const shouldDark = nativeTheme.shouldUseDarkColors registry.darkThemeInvert = shouldDark registry.conf.set('darkThemeInvert', shouldDark) registry.window.onenote.webContents.send('p3x-onenote-action', { action: 'dark-theme-invert', darkThemeInvert: shouldDark, }) }, }, ], }, { type: 'separator' }, { label: registry.lang.label?.exportSettings || 'Export settings', click: async () => { try { const result = await registry.window.onenote.webContents.executeJavaScript( `window.electronShim.ipcRenderer.invoke('p3x-onenote-settings-export')` ) if (result && result.success) { notify(registry.lang.label?.settingsExported || 'Settings exported.') } } catch (e) { console.error(e) } } }, { label: registry.lang.label?.importSettings || 'Import settings', click: async () => { try { const result = await registry.window.onenote.webContents.executeJavaScript( `window.electronShim.ipcRenderer.invoke('p3x-onenote-settings-import')` ) if (result && result.success) { notify(registry.lang.label?.settingsImported || 'Settings imported. Restarting...') setTimeout(() => { relaunch() }, 1500) } } catch (e) { console.error(e) } } }, ], }, { label: registry.lang.menu.language.label, submenu: languageCheckbox, }, { label: registry.lang.label.edit, submenu: [ copyLocation, {type: 'separator'}, { label: registry.lang.menu.role.edit.undo, role: 'undo' }, { label: registry.lang.menu.role.edit.redo, role: 'redo' }, {type: 'separator'}, { label: registry.lang.menu.role.edit.cut, role: 'cut' }, { label: registry.lang.menu.role.edit.copy, role: 'copy' }, { label: registry.lang.menu.role.edit.paste, role: 'paste' }, { label: registry.lang.menu.role.edit.pasteandmatchstyle, role: 'pasteandmatchstyle' }, { label: registry.lang.menu.role.edit.delete, role: 'delete' }, { label: registry.lang.menu.role.edit.selectall, role: 'selectall' } ] }, { label: registry.lang.label.view, submenu: [ { label: registry.lang.menu.role.view.reload, role: 'reload' }, { label: registry.lang.menu.role.view.forcereload, role: 'forcereload' }, { label: registry.lang.menu.role.view.toggledevtools, role: 'toggledevtools' }, {type: 'separator'}, { label: registry.lang.menu.role.view.resetzoom, role: 'resetzoom' }, { label: registry.lang.menu.role.view.zoomin, role: 'zoomin' }, { label: registry.lang.menu.role.view.zoomout, role: 'zoomout' }, {type: 'separator'}, { label: registry.lang.menu.role.view.togglefullscreen, role: 'togglefullscreen' } ] }, { label: registry.lang.menu.help.title, role: 'help', submenu: [ { label: registry.lang.label.download, click: action.download }, { label: 'GitHub', click: action.github }, { label: registry.lang.label.reportIssue || 'Report issue / Request feature', click: action.reportIssue }, { label: registry.lang.label.developer, click: action.patrik }, { label: 'P3X', click: action.p3x }, { label: 'Corifeus', click: action.corifeus }, { label: 'NPM', click: action.npm }, ] }, { label: registry.lang.label.donate, click: () => { shell.openExternal('https://paypal.me/patrikx3') } }, ] //if (process.env.APPIMAGE !== undefined) { template[7].submenu.push({type: 'separator'}) template[7].submenu.push({ label: registry.lang.menu.help.checkUpdates, click: async () => { const electronUpdater = await import("electron-updater"); const { autoUpdater } = electronUpdater.default ?? electronUpdater; autoUpdater.checkForUpdatesAndNotify(); } }, ) //} const menu = Menu.buildFromTemplate(template) Menu.setApplicationMenu(menu) } export default mainMenu;