mirror of
https://github.com/marktext/marktext.git
synced 2025-05-02 07:31:18 +08:00
Refactor menu actions and shortcut handling (#3032)
* Refactor menu actions and shortcut handling * Remove duplicated command id * Update docs
This commit is contained in:
parent
f01e30c59a
commit
cb57af4b2a
@ -8,7 +8,7 @@ MarkText key bindings for Linux. Please see [general key bindings](KEYBINDINGS.m
|
||||
|
||||
| Id | Default | Description |
|
||||
|:------------------- | --------------------------------------------- | ------------------------------------- |
|
||||
| `file.new-file` | <kbd>Ctrl</kbd>+<kbd>N</kbd> | New file |
|
||||
| `file.new-window` | <kbd>Ctrl</kbd>+<kbd>N</kbd> | New window |
|
||||
| `file.new-tab` | <kbd>Ctrl</kbd>+<kbd>T</kbd> | New tab |
|
||||
| `file.open-file` | <kbd>Ctrl</kbd>+<kbd>O</kbd> | Open markdown file |
|
||||
| `file.open-folder` | <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>O</kbd> | Open folder |
|
||||
|
@ -17,7 +17,7 @@ MarkText key bindings for macOS. Please see [general key bindings](KEYBINDINGS.m
|
||||
|
||||
| Id | Default | Description |
|
||||
|:------------------- | ------------------------------------------------ | ------------------------------------- |
|
||||
| `file.new-file` | <kbd>Command</kbd>+<kbd>N</kbd> | New file |
|
||||
| `file.new-window` | <kbd>Command</kbd>+<kbd>N</kbd> | New window |
|
||||
| `file.new-tab` | <kbd>Command</kbd>+<kbd>T</kbd> | New tab |
|
||||
| `file.open-file` | <kbd>Command</kbd>+<kbd>O</kbd> | Open markdown file |
|
||||
| `file.open-folder` | <kbd>Command</kbd>+<kbd>Shift</kbd>+<kbd>O</kbd> | Open folder |
|
||||
|
@ -8,7 +8,7 @@ MarkText key bindings for Windows. Please see [general key bindings](KEYBINDINGS
|
||||
|
||||
| Id | Default | Description |
|
||||
|:------------------- | --------------------------------------------- | ------------------------------------- |
|
||||
| `file.new-file` | <kbd>Ctrl</kbd>+<kbd>N</kbd> | New file |
|
||||
| `file.new-window` | <kbd>Ctrl</kbd>+<kbd>N</kbd> | New window |
|
||||
| `file.new-tab` | <kbd>Ctrl</kbd>+<kbd>T</kbd> | New tab |
|
||||
| `file.open-file` | <kbd>Ctrl</kbd>+<kbd>O</kbd> | Open markdown file |
|
||||
| `file.open-folder` | <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>O</kbd> | Open folder |
|
||||
|
110
src/common/commands/constants.js
Normal file
110
src/common/commands/constants.js
Normal file
@ -0,0 +1,110 @@
|
||||
const COMMANDS = Object.freeze({
|
||||
EDIT_COPY: 'edit.copy',
|
||||
EDIT_COPY_AS_HTML: 'edit.copy-as-html',
|
||||
EDIT_COPY_AS_MARKDOWN: 'edit.copy-as-markdown',
|
||||
EDIT_CREATE_PARAGRAPH: 'edit.create-paragraph',
|
||||
EDIT_CUT: 'edit.cut',
|
||||
EDIT_DELETE_PARAGRAPH: 'edit.delete-paragraph',
|
||||
EDIT_DUPLICATE: 'edit.duplicate',
|
||||
EDIT_FIND: 'edit.find',
|
||||
EDIT_FIND_IN_FOLDER: 'edit.find-in-folder',
|
||||
EDIT_FIND_NEXT: 'edit.find-next',
|
||||
EDIT_FIND_PREVIOUS: 'edit.find-previous',
|
||||
EDIT_PASTE: 'edit.paste',
|
||||
EDIT_PASTE_AS_PLAINTEXT: 'edit.paste-as-plaintext',
|
||||
EDIT_REDO: 'edit.redo',
|
||||
EDIT_REPLACE: 'edit.replace',
|
||||
EDIT_SCREENSHOT: 'edit.screenshot',
|
||||
EDIT_SELECT_ALL: 'edit.select-all',
|
||||
EDIT_UNDO: 'edit.undo',
|
||||
|
||||
FILE_CHECK_UPDATE: 'file.check-update',
|
||||
FILE_CLOSE_TAB: 'file.close-tab',
|
||||
FILE_CLOSE_WINDOW: 'file.close-window',
|
||||
FILE_EXPORT_FILE: 'file.export-file',
|
||||
FILE_IMPORT_FILE: 'file.import-file',
|
||||
FILE_MOVE_FILE: 'file.move-file',
|
||||
FILE_NEW_FILE: 'file.new-window',
|
||||
FILE_NEW_TAB: 'file.new-tab',
|
||||
FILE_OPEN_FILE: 'file.open-file',
|
||||
FILE_OPEN_FOLDER: 'file.open-folder',
|
||||
FILE_PREFERENCES: 'file.preferences',
|
||||
FILE_PRINT: 'file.print',
|
||||
FILE_QUICK_OPEN: 'file.quick-open',
|
||||
FILE_QUIT: 'file.quit',
|
||||
FILE_RENAME_FILE: 'file.rename-file',
|
||||
FILE_SAVE: 'file.save',
|
||||
FILE_SAVE_AS: 'file.save-as',
|
||||
// FILE_TOGGLE_AUTO_SAVE: 'file.toggle-auto-save',
|
||||
|
||||
FORMAT_CLEAR_FORMAT: 'format.clear-format',
|
||||
FORMAT_EMPHASIS: 'format.emphasis',
|
||||
FORMAT_HIGHLIGHT: 'format.highlight',
|
||||
FORMAT_HYPERLINK: 'format.hyperlink',
|
||||
FORMAT_IMAGE: 'format.image',
|
||||
FORMAT_INLINE_CODE: 'format.inline-code',
|
||||
FORMAT_INLINE_MATH: 'format.inline-math',
|
||||
FORMAT_STRIKE: 'format.strike',
|
||||
FORMAT_STRONG: 'format.strong',
|
||||
FORMAT_SUBSCRIPT: 'format.subscript',
|
||||
FORMAT_SUPERSCRIPT: 'format.superscript',
|
||||
FORMAT_UNDERLINE: 'format.underline',
|
||||
|
||||
MT_HIDE: 'mt.hide',
|
||||
MT_HIDE_OTHERS: 'mt.hide-others',
|
||||
|
||||
PARAGRAPH_BULLET_LIST: 'paragraph.bullet-list',
|
||||
PARAGRAPH_CODE_FENCE: 'paragraph.code-fence',
|
||||
PARAGRAPH_DEGRADE_HEADING: 'paragraph.degrade-heading',
|
||||
PARAGRAPH_FRONT_MATTER: 'paragraph.front-matter',
|
||||
PARAGRAPH_HEADING_1: 'paragraph.heading-1',
|
||||
PARAGRAPH_HEADING_2: 'paragraph.heading-2',
|
||||
PARAGRAPH_HEADING_3: 'paragraph.heading-3',
|
||||
PARAGRAPH_HEADING_4: 'paragraph.heading-4',
|
||||
PARAGRAPH_HEADING_5: 'paragraph.heading-5',
|
||||
PARAGRAPH_HEADING_6: 'paragraph.heading-6',
|
||||
PARAGRAPH_HORIZONTAL_LINE: 'paragraph.horizontal-line',
|
||||
PARAGRAPH_HTML_BLOCK: 'paragraph.html-block',
|
||||
PARAGRAPH_LOOSE_LIST_ITEM: 'paragraph.loose-list-item',
|
||||
PARAGRAPH_MATH_FORMULA: 'paragraph.math-formula',
|
||||
PARAGRAPH_ORDERED_LIST: 'paragraph.order-list',
|
||||
PARAGRAPH_PARAGRAPH: 'paragraph.paragraph',
|
||||
PARAGRAPH_QUOTE_BLOCK: 'paragraph.quote-block',
|
||||
PARAGRAPH_TABLE: 'paragraph.table',
|
||||
PARAGRAPH_TASK_LIST: 'paragraph.task-list',
|
||||
PARAGRAPH_INCREASE_HEADING: 'paragraph.upgrade-heading',
|
||||
|
||||
TABS_CYCLE_BACKWARD: 'tabs.cycle-backward',
|
||||
TABS_CYCLE_FORWARD: 'tabs.cycle-forward',
|
||||
TABS_SWITCH_TO_EIGHTH: 'tabs.switch-to-eighth',
|
||||
TABS_SWITCH_TO_FIFTH: 'tabs.switch-to-fifth',
|
||||
TABS_SWITCH_TO_FIRST: 'tabs.switch-to-first',
|
||||
TABS_SWITCH_TO_FOURTH: 'tabs.switch-to-fourth',
|
||||
TABS_SWITCH_TO_LEFT: 'tabs.switch-to-left',
|
||||
TABS_SWITCH_TO_NINTH: 'tabs.switch-to-ninth',
|
||||
TABS_SWITCH_TO_RIGHT: 'tabs.switch-to-right',
|
||||
TABS_SWITCH_TO_SECOND: 'tabs.switch-to-second',
|
||||
TABS_SWITCH_TO_SEVENTH: 'tabs.switch-to-seventh',
|
||||
TABS_SWITCH_TO_SIXTH: 'tabs.switch-to-sixth',
|
||||
TABS_SWITCH_TO_TENTH: 'tabs.switch-to-tenth',
|
||||
TABS_SWITCH_TO_THIRD: 'tabs.switch-to-third',
|
||||
|
||||
VIEW_COMMAND_PALETTE: 'view.command-palette',
|
||||
VIEW_DEV_RELOAD: 'view.dev-reload',
|
||||
VIEW_FOCUS_MODE: 'view.focus-mode',
|
||||
VIEW_FORCE_RELOAD_IMAGES: 'view.reload-images',
|
||||
VIEW_SOURCE_CODE_MODE: 'view.source-code-mode',
|
||||
VIEW_TOGGLE_DEV_TOOLS: 'view.toggle-dev-tools',
|
||||
VIEW_TOGGLE_SIDEBAR: 'view.toggle-sidebar',
|
||||
VIEW_TOGGLE_TABBAR: 'view.toggle-tabbar',
|
||||
VIEW_TOGGLE_TOC: 'view.toggle-toc',
|
||||
VIEW_TYPEWRITER_MODE: 'view.typewriter-mode',
|
||||
|
||||
WINDOW_MINIMIZE: 'window.minimize',
|
||||
WINDOW_TOGGLE_ALWAYS_ON_TOP: 'window.toggle-always-on-top',
|
||||
WINDOW_TOGGLE_FULL_SCREEN: 'window.toggle-full-screen',
|
||||
WINDOW_ZOOM_IN: 'window.zoom-in',
|
||||
WINDOW_ZOOM_OUT: 'window.zoom-out'
|
||||
})
|
||||
|
||||
export default COMMANDS
|
@ -3,6 +3,8 @@ import Preference from '../preferences'
|
||||
import DataCenter from '../dataCenter'
|
||||
import Keybindings from '../keyboard/shortcutHandler'
|
||||
import AppMenu from '../menu'
|
||||
import { loadMenuCommands } from '../menu/actions'
|
||||
import { CommandManager, loadDefaultCommands } from '../commands'
|
||||
|
||||
class Accessor {
|
||||
/**
|
||||
@ -13,12 +15,27 @@ class Accessor {
|
||||
|
||||
this.env = appEnvironment
|
||||
this.paths = appEnvironment.paths // export paths to make it better accessible
|
||||
|
||||
this.preferences = new Preference(this.paths)
|
||||
this.dataCenter = new DataCenter(this.paths)
|
||||
this.keybindings = new Keybindings(userDataPath)
|
||||
|
||||
this.commandManager = CommandManager
|
||||
this._loadCommands()
|
||||
|
||||
this.keybindings = new Keybindings(this.commandManager, appEnvironment)
|
||||
this.menu = new AppMenu(this.preferences, this.keybindings, userDataPath)
|
||||
this.windowManager = new WindowManager(this.menu, this.preferences)
|
||||
}
|
||||
|
||||
_loadCommands () {
|
||||
const { commandManager } = this
|
||||
loadDefaultCommands(commandManager)
|
||||
loadMenuCommands(commandManager)
|
||||
|
||||
if (this.env.isDevMode) {
|
||||
commandManager.__verifyDefaultCommands()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Accessor
|
||||
|
@ -14,6 +14,7 @@ export class AppEnvironment {
|
||||
this._id = envId++
|
||||
this._appPaths = new AppPaths(options.userDataPath)
|
||||
this._debug = !!options.debug
|
||||
this._isDevMode = !!options.isDevMode
|
||||
this._verbose = !!options.verbose
|
||||
this._safeMode = !!options.safeMode
|
||||
}
|
||||
@ -41,6 +42,13 @@ export class AppEnvironment {
|
||||
return this._debug
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
get isDevMode () {
|
||||
return this._isDevMode
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
@ -65,6 +73,7 @@ export class AppEnvironment {
|
||||
const setupEnvironment = args => {
|
||||
patchEnvPath()
|
||||
|
||||
const isDevMode = process.env.NODE_ENV !== 'production'
|
||||
const debug = args['--debug'] || !!process.env.MARKTEXT_DEBUG || process.env.NODE_ENV !== 'production'
|
||||
const verbose = args['--verbose'] || 0
|
||||
const safeMode = args['--safe']
|
||||
@ -72,6 +81,7 @@ const setupEnvironment = args => {
|
||||
|
||||
const appEnvironment = new AppEnvironment({
|
||||
debug,
|
||||
isDevMode,
|
||||
verbose,
|
||||
safeMode,
|
||||
userDataPath
|
||||
|
11
src/main/commands/file.js
Normal file
11
src/main/commands/file.js
Normal file
@ -0,0 +1,11 @@
|
||||
import { COMMANDS } from './index'
|
||||
|
||||
const openQuickOpenDialog = win => {
|
||||
if (win && win.webContents) {
|
||||
win.webContents.send('mt::execute-command-by-id', 'file.quick-open')
|
||||
}
|
||||
}
|
||||
|
||||
export const loadFileCommands = commandManager => {
|
||||
commandManager.add(COMMANDS.FILE_QUICK_OPEN, openQuickOpenDialog)
|
||||
}
|
53
src/main/commands/index.js
Normal file
53
src/main/commands/index.js
Normal file
@ -0,0 +1,53 @@
|
||||
import COMMAND_CONSTANTS from 'common/commands/constants'
|
||||
import { loadFileCommands } from './file'
|
||||
import { loadTabCommands } from './tab'
|
||||
|
||||
export const COMMANDS = COMMAND_CONSTANTS
|
||||
|
||||
export const loadDefaultCommands = commandManager => {
|
||||
loadFileCommands(commandManager)
|
||||
loadTabCommands(commandManager)
|
||||
}
|
||||
|
||||
class CommandManager {
|
||||
constructor () {
|
||||
this._commands = new Map()
|
||||
}
|
||||
|
||||
add (id, callback) {
|
||||
const { _commands } = this
|
||||
if (_commands.has(id)) {
|
||||
throw new Error(`Command with id="${id}" already exists.`)
|
||||
}
|
||||
_commands.set(id, callback)
|
||||
}
|
||||
|
||||
remove (id) {
|
||||
return this._commands.delete(id)
|
||||
}
|
||||
|
||||
has (id) {
|
||||
return this._commands.has(id)
|
||||
}
|
||||
|
||||
execute (id, ...args) {
|
||||
const command = this._commands.get(id)
|
||||
if (!command) {
|
||||
throw new Error(`No command found with id="${id}".`)
|
||||
}
|
||||
return command(...args)
|
||||
}
|
||||
|
||||
__verifyDefaultCommands () {
|
||||
const { _commands } = this
|
||||
Object.keys(COMMANDS).forEach(propertyName => {
|
||||
const id = COMMANDS[propertyName]
|
||||
if (!_commands.has(id)) {
|
||||
console.error(`[DEBUG] Default command with id="${id}" isn't available!`)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const commandManagerInstance = new CommandManager()
|
||||
export { commandManagerInstance as CommandManager }
|
36
src/main/commands/tab.js
Normal file
36
src/main/commands/tab.js
Normal file
@ -0,0 +1,36 @@
|
||||
import { COMMANDS } from './index'
|
||||
|
||||
const switchToLeftTab = win => {
|
||||
if (win && win.webContents) {
|
||||
win.webContents.send('mt::tabs-cycle-left')
|
||||
}
|
||||
}
|
||||
|
||||
const switchToRightTab = win => {
|
||||
if (win && win.webContents) {
|
||||
win.webContents.send('mt::tabs-cycle-right')
|
||||
}
|
||||
}
|
||||
|
||||
const switchTabByIndex = (win, index) => {
|
||||
if (win && win.webContents) {
|
||||
win.webContents.send('mt::switch-tab-by-index', index)
|
||||
}
|
||||
}
|
||||
|
||||
export const loadTabCommands = commandManager => {
|
||||
commandManager.add(COMMANDS.TABS_CYCLE_BACKWARD, switchToLeftTab)
|
||||
commandManager.add(COMMANDS.TABS_CYCLE_FORWARD, switchToRightTab)
|
||||
commandManager.add(COMMANDS.TABS_SWITCH_TO_LEFT, switchToLeftTab)
|
||||
commandManager.add(COMMANDS.TABS_SWITCH_TO_RIGHT, switchToRightTab)
|
||||
commandManager.add(COMMANDS.TABS_SWITCH_TO_FIRST, win => switchTabByIndex(win, 0))
|
||||
commandManager.add(COMMANDS.TABS_SWITCH_TO_SECOND, win => switchTabByIndex(win, 1))
|
||||
commandManager.add(COMMANDS.TABS_SWITCH_TO_THIRD, win => switchTabByIndex(win, 2))
|
||||
commandManager.add(COMMANDS.TABS_SWITCH_TO_FOURTH, win => switchTabByIndex(win, 3))
|
||||
commandManager.add(COMMANDS.TABS_SWITCH_TO_FIFTH, win => switchTabByIndex(win, 4))
|
||||
commandManager.add(COMMANDS.TABS_SWITCH_TO_SIXTH, win => switchTabByIndex(win, 5))
|
||||
commandManager.add(COMMANDS.TABS_SWITCH_TO_SEVENTH, win => switchTabByIndex(win, 6))
|
||||
commandManager.add(COMMANDS.TABS_SWITCH_TO_EIGHTH, win => switchTabByIndex(win, 7))
|
||||
commandManager.add(COMMANDS.TABS_SWITCH_TO_NINTH, win => switchTabByIndex(win, 8))
|
||||
commandManager.add(COMMANDS.TABS_SWITCH_TO_TENTH, win => switchTabByIndex(win, 9))
|
||||
}
|
@ -10,7 +10,7 @@ export default new Map([
|
||||
['file.preferences', 'Command+,'], // located under MarkText menu in macOS only
|
||||
|
||||
// File menu
|
||||
['file.new-file', 'Command+N'],
|
||||
['file.new-window', 'Command+N'],
|
||||
['file.new-tab', 'Command+T'],
|
||||
['file.open-file', 'Command+O'],
|
||||
['file.open-folder', 'Command+Shift+O'],
|
||||
|
@ -13,7 +13,7 @@ export default new Map([
|
||||
['mt.hide-others', ''],
|
||||
|
||||
// File menu
|
||||
['file.new-file', 'Ctrl+N'],
|
||||
['file.new-window', 'Ctrl+N'],
|
||||
['file.new-tab', 'Ctrl+T'],
|
||||
['file.open-file', 'Ctrl+O'],
|
||||
['file.open-folder', 'Ctrl+Shift+O'],
|
||||
|
@ -10,7 +10,7 @@ export default new Map([
|
||||
['mt.hide-others', ''],
|
||||
|
||||
// File menu
|
||||
['file.new-file', 'Ctrl+N'],
|
||||
['file.new-window', 'Ctrl+N'],
|
||||
['file.new-tab', 'Ctrl+T'],
|
||||
['file.open-file', 'Ctrl+O'],
|
||||
['file.open-folder', 'Ctrl+Shift+O'],
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { shell, Menu } from 'electron'
|
||||
import { shell } from 'electron'
|
||||
import fs from 'fs'
|
||||
import fsPromises from 'fs/promises'
|
||||
import path from 'path'
|
||||
@ -14,15 +14,26 @@ import keybindingsWindows from './keybindingsWindows'
|
||||
|
||||
class Keybindings {
|
||||
/**
|
||||
* @param {string} userDataPath The user data path.
|
||||
* @param {CommandManager} commandManager The command manager instance.
|
||||
* @param {AppEnvironment} appEnvironment The application environment instance.
|
||||
*/
|
||||
constructor (userDataPath) {
|
||||
constructor (commandManager, appEnvironment) {
|
||||
const { userDataPath } = appEnvironment.paths
|
||||
this.configPath = path.join(userDataPath, 'keybindings.json')
|
||||
this.commandManager = commandManager
|
||||
|
||||
this.userKeybindings = new Map()
|
||||
this.keys = this.getDefaultKeybindings()
|
||||
this._prepareKeyMapper()
|
||||
|
||||
if (appEnvironment.isDevMode) {
|
||||
for (const [id, accelerator] of this.keys) {
|
||||
if (!commandManager.has(id)) {
|
||||
console.error(`[DEBUG] Command with id="${id}" isn't available for accelerator="${accelerator}".`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load user-defined keybindings
|
||||
this._loadLocalKeybindings()
|
||||
}
|
||||
@ -35,21 +46,32 @@ class Keybindings {
|
||||
return name
|
||||
}
|
||||
|
||||
registerKeyHandlers (win, acceleratorMap) {
|
||||
for (const item of acceleratorMap) {
|
||||
let { accelerator } = item
|
||||
if (accelerator == null || accelerator === '') {
|
||||
continue
|
||||
}
|
||||
registerAccelerator (win, accelerator, callback) {
|
||||
if (!win || !accelerator || !callback) {
|
||||
throw new Error(`addKeyHandler: invalid arguments (accelerator="${accelerator}").`)
|
||||
}
|
||||
|
||||
// Regisiter shortcuts on the BrowserWindow instead of using Chromium's native menu.
|
||||
// This makes it possible to receive key down events before Chromium/Electron and we
|
||||
// can handle reserved Chromium shortcuts. Afterwards prevent the default action of
|
||||
// the event so the native menu is not triggered.
|
||||
electronLocalshortcut.register(win, accelerator, () => {
|
||||
callMenuCallback(item, win)
|
||||
return true // prevent default action
|
||||
})
|
||||
// Register shortcuts on the BrowserWindow instead of using Chromium's native menu.
|
||||
// This makes it possible to receive key down events before Chromium/Electron and we
|
||||
// can handle reserved Chromium shortcuts. Afterwards prevent the default action of
|
||||
// the event so the native menu is not triggered.
|
||||
electronLocalshortcut.register(win, accelerator, () => {
|
||||
callback(win)
|
||||
return true // prevent default action
|
||||
})
|
||||
}
|
||||
|
||||
unregisterAccelerator (win, accelerator) {
|
||||
electronLocalshortcut.unregister(win, accelerator)
|
||||
}
|
||||
|
||||
registerEditorKeyHandlers (win) {
|
||||
for (const [id, accelerator] of this.keys) {
|
||||
if (accelerator && accelerator.length > 1) {
|
||||
this.registerAccelerator(win, accelerator, () => {
|
||||
this.commandManager.execute(id, win)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,43 +235,4 @@ class Keybindings {
|
||||
}
|
||||
}
|
||||
|
||||
export const parseMenu = menuTemplate => {
|
||||
const { submenu, accelerator, click, id, visible } = menuTemplate
|
||||
const items = []
|
||||
if (Array.isArray(menuTemplate)) {
|
||||
for (const item of menuTemplate) {
|
||||
const subitems = parseMenu(item)
|
||||
if (subitems) items.push(...subitems)
|
||||
}
|
||||
} else if (submenu) {
|
||||
const subitems = parseMenu(submenu)
|
||||
if (subitems) items.push(...subitems)
|
||||
} else if ((visible === undefined || visible) && accelerator && click) {
|
||||
items.push({
|
||||
accelerator,
|
||||
click,
|
||||
id // may be null
|
||||
})
|
||||
}
|
||||
return items.length === 0 ? null : items
|
||||
}
|
||||
|
||||
const callMenuCallback = (menuInfo, win) => {
|
||||
const { click, id } = menuInfo
|
||||
if (click) {
|
||||
let menuItem = null
|
||||
if (id) {
|
||||
const menus = Menu.getApplicationMenu()
|
||||
menuItem = menus.getMenuItemById(id)
|
||||
}
|
||||
|
||||
// Allow all shortcuts/menus without id and only enabled menus with id (GH#980).
|
||||
if (!menuItem || menuItem.enabled !== false) {
|
||||
click(menuItem, win)
|
||||
}
|
||||
} else {
|
||||
console.error('ERROR: callback function is not defined.')
|
||||
}
|
||||
}
|
||||
|
||||
export default Keybindings
|
||||
|
@ -1,8 +1,10 @@
|
||||
import path from 'path'
|
||||
import { ipcMain, BrowserWindow } from 'electron'
|
||||
import log from 'electron-log'
|
||||
import { COMMANDS } from '../../commands'
|
||||
import { searchFilesAndDir } from '../../utils/imagePathAutoComplement'
|
||||
|
||||
// TODO(Refactor): Move to filesystem and provide generic API to search files in directories.
|
||||
ipcMain.on('mt::ask-for-image-auto-path', (e, { pathname, src, id }) => {
|
||||
const win = BrowserWindow.fromWebContents(e.sender)
|
||||
if (!src || typeof src !== 'string') {
|
||||
@ -26,6 +28,64 @@ ipcMain.on('mt::ask-for-image-auto-path', (e, { pathname, src, id }) => {
|
||||
})
|
||||
})
|
||||
|
||||
// --- Menu actions -------------------------------------------------------------
|
||||
|
||||
export const editorUndo = win => {
|
||||
edit(win, 'undo')
|
||||
}
|
||||
|
||||
export const editorRedo = win => {
|
||||
edit(win, 'redo')
|
||||
}
|
||||
|
||||
export const editorCopyAsMarkdown = win => {
|
||||
edit(win, 'copyAsMarkdown')
|
||||
}
|
||||
|
||||
export const editorCopyAsHtml = win => {
|
||||
edit(win, 'copyAsHtml')
|
||||
}
|
||||
|
||||
export const editorPasteAsPlainText = win => {
|
||||
edit(win, 'pasteAsPlainText')
|
||||
}
|
||||
|
||||
export const editorSelectAll = win => {
|
||||
edit(win, 'selectAll')
|
||||
}
|
||||
|
||||
export const editorDuplicate = win => {
|
||||
edit(win, 'duplicate')
|
||||
}
|
||||
|
||||
export const editorCreateParagraph = win => {
|
||||
edit(win, 'createParagraph')
|
||||
}
|
||||
|
||||
export const editorDeleteParagraph = win => {
|
||||
edit(win, 'deleteParagraph')
|
||||
}
|
||||
|
||||
export const editorFind = win => {
|
||||
edit(win, 'find')
|
||||
}
|
||||
|
||||
export const editorFindNext = win => {
|
||||
edit(win, 'findNext')
|
||||
}
|
||||
|
||||
export const editorFindPrevious = win => {
|
||||
edit(win, 'findPrev')
|
||||
}
|
||||
|
||||
export const editorReplace = win => {
|
||||
edit(win, 'undo')
|
||||
}
|
||||
|
||||
export const findInFolder = win => {
|
||||
edit(win, 'findInFolder')
|
||||
}
|
||||
|
||||
export const edit = (win, type) => {
|
||||
if (win && win.webContents) {
|
||||
win.webContents.send('mt::editor-edit-action', type)
|
||||
@ -60,6 +120,29 @@ export const lineEnding = (win, lineEnding) => {
|
||||
}
|
||||
}
|
||||
|
||||
// --- Commands -------------------------------------------------------------
|
||||
|
||||
export const loadEditCommands = commandManager => {
|
||||
commandManager.add(COMMANDS.EDIT_COPY, nativeCopy)
|
||||
commandManager.add(COMMANDS.EDIT_COPY_AS_HTML, editorCopyAsHtml)
|
||||
commandManager.add(COMMANDS.EDIT_COPY_AS_MARKDOWN, editorCopyAsMarkdown)
|
||||
commandManager.add(COMMANDS.EDIT_CREATE_PARAGRAPH, editorCreateParagraph)
|
||||
commandManager.add(COMMANDS.EDIT_CUT, nativeCut)
|
||||
commandManager.add(COMMANDS.EDIT_DELETE_PARAGRAPH, editorDeleteParagraph)
|
||||
commandManager.add(COMMANDS.EDIT_DUPLICATE, editorDuplicate)
|
||||
commandManager.add(COMMANDS.EDIT_FIND, editorFind)
|
||||
commandManager.add(COMMANDS.EDIT_FIND_IN_FOLDER, findInFolder)
|
||||
commandManager.add(COMMANDS.EDIT_FIND_NEXT, editorFindNext)
|
||||
commandManager.add(COMMANDS.EDIT_FIND_PREVIOUS, editorFindPrevious)
|
||||
commandManager.add(COMMANDS.EDIT_PASTE, nativePaste)
|
||||
commandManager.add(COMMANDS.EDIT_PASTE_AS_PLAINTEXT, editorPasteAsPlainText)
|
||||
commandManager.add(COMMANDS.EDIT_REDO, editorRedo)
|
||||
commandManager.add(COMMANDS.EDIT_REPLACE, editorReplace)
|
||||
commandManager.add(COMMANDS.EDIT_SCREENSHOT, screenshot)
|
||||
commandManager.add(COMMANDS.EDIT_SELECT_ALL, editorSelectAll)
|
||||
commandManager.add(COMMANDS.EDIT_UNDO, editorUndo)
|
||||
}
|
||||
|
||||
// --- IPC events -------------------------------------------------------------
|
||||
|
||||
// NOTE: Don't use static `getMenuItemById` here, instead request the menu by
|
||||
|
@ -1,9 +1,12 @@
|
||||
import fs from 'fs-extra'
|
||||
import path from 'path'
|
||||
import { BrowserWindow, dialog, ipcMain, shell } from 'electron'
|
||||
import { BrowserWindow, app, dialog, ipcMain, shell } from 'electron'
|
||||
import log from 'electron-log'
|
||||
import { isDirectory, isFile, exists } from 'common/filesystem'
|
||||
import { MARKDOWN_EXTENSIONS, isMarkdownFile } from 'common/filesystem/paths'
|
||||
import { checkUpdates, userSetting } from './marktext'
|
||||
import { showTabBar } from './view'
|
||||
import { COMMANDS } from '../../commands'
|
||||
import { EXTENSION_HASN, PANDOC_EXTENSIONS, URL_REG } from '../../config'
|
||||
import { normalizeAndResolvePath, writeFile } from '../../filesystem'
|
||||
import { writeMarkdownFile } from '../../filesystem/markdown'
|
||||
@ -501,7 +504,7 @@ export const importFile = async win => {
|
||||
}
|
||||
}
|
||||
|
||||
export const print = win => {
|
||||
export const printDocument = win => {
|
||||
if (win) {
|
||||
win.webContents.send('mt::show-export-dialog', 'print')
|
||||
}
|
||||
@ -545,6 +548,7 @@ export const openFileOrFolder = (win, pathname) => {
|
||||
export const newBlankTab = win => {
|
||||
if (win && win.webContents) {
|
||||
win.webContents.send('mt::new-untitled-tab')
|
||||
showTabBar(win)
|
||||
}
|
||||
}
|
||||
|
||||
@ -596,3 +600,24 @@ export const rename = win => {
|
||||
export const clearRecentlyUsed = () => {
|
||||
ipcMain.emit('menu-clear-recently-used')
|
||||
}
|
||||
|
||||
// --- Commands -------------------------------------------------------------
|
||||
|
||||
export const loadFileCommands = commandManager => {
|
||||
commandManager.add(COMMANDS.FILE_CHECK_UPDATE, checkUpdates)
|
||||
commandManager.add(COMMANDS.FILE_CLOSE_TAB, closeTab)
|
||||
commandManager.add(COMMANDS.FILE_CLOSE_WINDOW, closeWindow)
|
||||
commandManager.add(COMMANDS.FILE_EXPORT_FILE, exportFile)
|
||||
commandManager.add(COMMANDS.FILE_IMPORT_FILE, importFile)
|
||||
commandManager.add(COMMANDS.FILE_MOVE_FILE, moveTo)
|
||||
commandManager.add(COMMANDS.FILE_NEW_FILE, newEditorWindow)
|
||||
commandManager.add(COMMANDS.FILE_NEW_TAB, newBlankTab)
|
||||
commandManager.add(COMMANDS.FILE_OPEN_FILE, openFile)
|
||||
commandManager.add(COMMANDS.FILE_OPEN_FOLDER, openFolder)
|
||||
commandManager.add(COMMANDS.FILE_PREFERENCES, userSetting)
|
||||
commandManager.add(COMMANDS.FILE_PRINT, printDocument)
|
||||
commandManager.add(COMMANDS.FILE_QUIT, app.quit)
|
||||
commandManager.add(COMMANDS.FILE_RENAME_FILE, rename)
|
||||
commandManager.add(COMMANDS.FILE_SAVE, save)
|
||||
commandManager.add(COMMANDS.FILE_SAVE_AS, saveAs)
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
const MENU_ID_FORMAT_MAP = {
|
||||
import { COMMANDS } from '../../commands'
|
||||
|
||||
const MENU_ID_FORMAT_MAP = Object.freeze({
|
||||
strongMenuItem: 'strong',
|
||||
emphasisMenuItem: 'em',
|
||||
inlineCodeMenuItem: 'inline_code',
|
||||
@ -6,14 +8,79 @@ const MENU_ID_FORMAT_MAP = {
|
||||
hyperlinkMenuItem: 'link',
|
||||
imageMenuItem: 'image',
|
||||
inlineMathMenuItem: 'inline_math'
|
||||
}
|
||||
})
|
||||
|
||||
export const format = (win, type) => {
|
||||
const format = (win, type) => {
|
||||
if (win && win.webContents) {
|
||||
win.webContents.send('mt::editor-format-action', { type })
|
||||
}
|
||||
}
|
||||
|
||||
export const clearFormat = win => {
|
||||
format(win, 'clear')
|
||||
}
|
||||
|
||||
export const emphasis = win => {
|
||||
format(win, 'em')
|
||||
}
|
||||
|
||||
export const highlight = win => {
|
||||
format(win, 'mark')
|
||||
}
|
||||
|
||||
export const hyperlink = win => {
|
||||
format(win, 'link')
|
||||
}
|
||||
|
||||
export const image = win => {
|
||||
format(win, 'image')
|
||||
}
|
||||
|
||||
export const inlineCode = win => {
|
||||
format(win, 'inline_code')
|
||||
}
|
||||
|
||||
export const inlineMath = win => {
|
||||
format(win, 'inline_math')
|
||||
}
|
||||
|
||||
export const strikethrough = win => {
|
||||
format(win, 'del')
|
||||
}
|
||||
|
||||
export const strong = win => {
|
||||
format(win, 'strong')
|
||||
}
|
||||
|
||||
export const subscript = win => {
|
||||
format(win, 'sub')
|
||||
}
|
||||
|
||||
export const superscript = win => {
|
||||
format(win, 'sup')
|
||||
}
|
||||
|
||||
export const underline = win => {
|
||||
format(win, 'u')
|
||||
}
|
||||
|
||||
// --- Commands -------------------------------------------------------------
|
||||
|
||||
export const loadFormatCommands = commandManager => {
|
||||
commandManager.add(COMMANDS.FORMAT_CLEAR_FORMAT, clearFormat)
|
||||
commandManager.add(COMMANDS.FORMAT_EMPHASIS, emphasis)
|
||||
commandManager.add(COMMANDS.FORMAT_HIGHLIGHT, highlight)
|
||||
commandManager.add(COMMANDS.FORMAT_HYPERLINK, hyperlink)
|
||||
commandManager.add(COMMANDS.FORMAT_IMAGE, image)
|
||||
commandManager.add(COMMANDS.FORMAT_INLINE_CODE, inlineCode)
|
||||
commandManager.add(COMMANDS.FORMAT_INLINE_MATH, inlineMath)
|
||||
commandManager.add(COMMANDS.FORMAT_STRIKE, strikethrough)
|
||||
commandManager.add(COMMANDS.FORMAT_STRONG, strong)
|
||||
commandManager.add(COMMANDS.FORMAT_SUBSCRIPT, subscript)
|
||||
commandManager.add(COMMANDS.FORMAT_SUPERSCRIPT, superscript)
|
||||
commandManager.add(COMMANDS.FORMAT_UNDERLINE, underline)
|
||||
}
|
||||
|
||||
// --- IPC events -------------------------------------------------------------
|
||||
|
||||
// NOTE: Don't use static `getMenuItemById` here, instead request the menu by
|
||||
|
17
src/main/menu/actions/index.js
Normal file
17
src/main/menu/actions/index.js
Normal file
@ -0,0 +1,17 @@
|
||||
import { loadEditCommands } from './edit'
|
||||
import { loadFileCommands } from './file'
|
||||
import { loadFormatCommands } from './format'
|
||||
import { loadMarktextCommands } from './marktext'
|
||||
import { loadParagraphCommands } from './paragraph'
|
||||
import { loadViewCommands } from './view'
|
||||
import { loadWindowCommands } from './window'
|
||||
|
||||
export const loadMenuCommands = commandManager => {
|
||||
loadEditCommands(commandManager)
|
||||
loadFileCommands(commandManager)
|
||||
loadFormatCommands(commandManager)
|
||||
loadMarktextCommands(commandManager)
|
||||
loadParagraphCommands(commandManager)
|
||||
loadViewCommands(commandManager)
|
||||
loadWindowCommands(commandManager)
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
import { autoUpdater } from 'electron-updater'
|
||||
import { ipcMain, BrowserWindow } from 'electron'
|
||||
import { ipcMain, BrowserWindow, Menu } from 'electron'
|
||||
import { COMMANDS } from '../../commands'
|
||||
import { isOsx } from '../../config'
|
||||
|
||||
let runningUpdate = false
|
||||
let win = null
|
||||
@ -36,18 +38,6 @@ autoUpdater.on('update-downloaded', () => {
|
||||
setImmediate(() => autoUpdater.quitAndInstall())
|
||||
})
|
||||
|
||||
export const userSetting = () => {
|
||||
ipcMain.emit('app-create-settings-window')
|
||||
}
|
||||
|
||||
export const checkUpdates = browserWindow => {
|
||||
if (!runningUpdate) {
|
||||
runningUpdate = true
|
||||
win = browserWindow
|
||||
autoUpdater.checkForUpdates()
|
||||
}
|
||||
}
|
||||
|
||||
ipcMain.on('mt::NEED_UPDATE', (e, { needUpdate }) => {
|
||||
if (needUpdate) {
|
||||
autoUpdater.downloadUpdate()
|
||||
@ -60,3 +50,42 @@ ipcMain.on('mt::check-for-update', e => {
|
||||
const win = BrowserWindow.fromWebContents(e.sender)
|
||||
checkUpdates(win)
|
||||
})
|
||||
|
||||
// --------------------------------------------------------
|
||||
|
||||
export const userSetting = () => {
|
||||
ipcMain.emit('app-create-settings-window')
|
||||
}
|
||||
|
||||
export const checkUpdates = browserWindow => {
|
||||
if (!runningUpdate) {
|
||||
runningUpdate = true
|
||||
win = browserWindow
|
||||
autoUpdater.checkForUpdates()
|
||||
}
|
||||
}
|
||||
|
||||
export const osxHide = () => {
|
||||
if (isOsx) {
|
||||
Menu.sendActionToFirstResponder('hide:')
|
||||
}
|
||||
}
|
||||
|
||||
export const osxHideAll = () => {
|
||||
if (isOsx) {
|
||||
Menu.sendActionToFirstResponder('hideOtherApplications:')
|
||||
}
|
||||
}
|
||||
|
||||
export const osxShowAll = () => {
|
||||
if (isOsx) {
|
||||
Menu.sendActionToFirstResponder('unhideAllApplications:')
|
||||
}
|
||||
}
|
||||
|
||||
// --- Commands -------------------------------------------------------------
|
||||
|
||||
export const loadMarktextCommands = commandManager => {
|
||||
commandManager.add(COMMANDS.MT_HIDE, osxHide)
|
||||
commandManager.add(COMMANDS.MT_HIDE_OTHERS, osxHideAll)
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { COMMANDS } from '../../commands'
|
||||
|
||||
const DISABLE_LABELS = [
|
||||
// paragraph menu items
|
||||
'heading1MenuItem', 'heading2MenuItem', 'heading3MenuItem', 'heading4MenuItem',
|
||||
@ -8,7 +10,7 @@ const DISABLE_LABELS = [
|
||||
'hyperlinkMenuItem', 'imageMenuItem'
|
||||
]
|
||||
|
||||
const MENU_ID_MAP = {
|
||||
const MENU_ID_MAP = Object.freeze({
|
||||
heading1MenuItem: 'h1',
|
||||
heading2MenuItem: 'h2',
|
||||
heading3MenuItem: 'h3',
|
||||
@ -26,14 +28,119 @@ const MENU_ID_MAP = {
|
||||
paragraphMenuItem: 'p',
|
||||
horizontalLineMenuItem: 'hr',
|
||||
frontMatterMenuItem: 'frontmatter' // 'pre'
|
||||
}
|
||||
})
|
||||
|
||||
export const paragraph = (win, type) => {
|
||||
const transformEditorElement = (win, type) => {
|
||||
if (win && win.webContents) {
|
||||
win.webContents.send('mt::editor-paragraph-action', { type })
|
||||
}
|
||||
}
|
||||
|
||||
export const bulletList = win => {
|
||||
transformEditorElement(win, 'ul-bullet')
|
||||
}
|
||||
|
||||
export const codeFence = win => {
|
||||
transformEditorElement(win, 'pre')
|
||||
}
|
||||
|
||||
export const degradeHeading = win => {
|
||||
transformEditorElement(win, 'degrade heading')
|
||||
}
|
||||
|
||||
export const frontMatter = win => {
|
||||
transformEditorElement(win, 'front-matter')
|
||||
}
|
||||
|
||||
export const heading1 = win => {
|
||||
transformEditorElement(win, 'heading 1')
|
||||
}
|
||||
|
||||
export const heading2 = win => {
|
||||
transformEditorElement(win, 'heading 2')
|
||||
}
|
||||
|
||||
export const heading3 = win => {
|
||||
transformEditorElement(win, 'heading 3')
|
||||
}
|
||||
|
||||
export const heading4 = win => {
|
||||
transformEditorElement(win, 'heading 4')
|
||||
}
|
||||
|
||||
export const heading5 = win => {
|
||||
transformEditorElement(win, 'heading 5')
|
||||
}
|
||||
|
||||
export const heading6 = win => {
|
||||
transformEditorElement(win, 'heading 6')
|
||||
}
|
||||
|
||||
export const horizontalLine = win => {
|
||||
transformEditorElement(win, 'hr')
|
||||
}
|
||||
|
||||
export const htmlBlock = win => {
|
||||
transformEditorElement(win, 'html')
|
||||
}
|
||||
|
||||
export const looseListItem = win => {
|
||||
transformEditorElement(win, 'loose-list-item')
|
||||
}
|
||||
|
||||
export const mathFormula = win => {
|
||||
transformEditorElement(win, 'mathblock')
|
||||
}
|
||||
|
||||
export const orderedList = win => {
|
||||
transformEditorElement(win, 'ol-order')
|
||||
}
|
||||
|
||||
export const paragraph = win => {
|
||||
transformEditorElement(win, 'paragraph')
|
||||
}
|
||||
|
||||
export const quoteBlock = win => {
|
||||
transformEditorElement(win, 'blockquote')
|
||||
}
|
||||
|
||||
export const table = win => {
|
||||
transformEditorElement(win, 'table')
|
||||
}
|
||||
|
||||
export const taskList = win => {
|
||||
transformEditorElement(win, 'ul-task')
|
||||
}
|
||||
|
||||
export const increaseHeading = win => {
|
||||
transformEditorElement(win, 'upgrade heading')
|
||||
}
|
||||
|
||||
// --- Commands -------------------------------------------------------------
|
||||
|
||||
export const loadParagraphCommands = commandManager => {
|
||||
commandManager.add(COMMANDS.PARAGRAPH_BULLET_LIST, bulletList)
|
||||
commandManager.add(COMMANDS.PARAGRAPH_CODE_FENCE, codeFence)
|
||||
commandManager.add(COMMANDS.PARAGRAPH_DEGRADE_HEADING, degradeHeading)
|
||||
commandManager.add(COMMANDS.PARAGRAPH_FRONT_MATTER, frontMatter)
|
||||
commandManager.add(COMMANDS.PARAGRAPH_HEADING_1, heading1)
|
||||
commandManager.add(COMMANDS.PARAGRAPH_HEADING_2, heading2)
|
||||
commandManager.add(COMMANDS.PARAGRAPH_HEADING_3, heading3)
|
||||
commandManager.add(COMMANDS.PARAGRAPH_HEADING_4, heading4)
|
||||
commandManager.add(COMMANDS.PARAGRAPH_HEADING_5, heading5)
|
||||
commandManager.add(COMMANDS.PARAGRAPH_HEADING_6, heading6)
|
||||
commandManager.add(COMMANDS.PARAGRAPH_HORIZONTAL_LINE, horizontalLine)
|
||||
commandManager.add(COMMANDS.PARAGRAPH_HTML_BLOCK, htmlBlock)
|
||||
commandManager.add(COMMANDS.PARAGRAPH_LOOSE_LIST_ITEM, looseListItem)
|
||||
commandManager.add(COMMANDS.PARAGRAPH_MATH_FORMULA, mathFormula)
|
||||
commandManager.add(COMMANDS.PARAGRAPH_ORDERED_LIST, orderedList)
|
||||
commandManager.add(COMMANDS.PARAGRAPH_PARAGRAPH, paragraph)
|
||||
commandManager.add(COMMANDS.PARAGRAPH_QUOTE_BLOCK, quoteBlock)
|
||||
commandManager.add(COMMANDS.PARAGRAPH_TABLE, table)
|
||||
commandManager.add(COMMANDS.PARAGRAPH_TASK_LIST, taskList)
|
||||
commandManager.add(COMMANDS.PARAGRAPH_INCREASE_HEADING, increaseHeading)
|
||||
}
|
||||
|
||||
// --- IPC events -------------------------------------------------------------
|
||||
|
||||
// NOTE: Don't use static `getMenuItemById` here, instead request the menu by
|
||||
|
@ -1,40 +1,95 @@
|
||||
import { getMenuItemById } from '../../menu'
|
||||
import { ipcMain } from 'electron'
|
||||
import { COMMANDS } from '../../commands'
|
||||
|
||||
const typewriterModeMenuItemId = 'typewriterModeMenuItem'
|
||||
const focusModeMenuItemId = 'focusModeMenuItem'
|
||||
|
||||
export const showCommandPalette = win => {
|
||||
win.webContents.send('mt::show-command-palette')
|
||||
}
|
||||
|
||||
export const typeMode = (win, type, item) => {
|
||||
if (!win) {
|
||||
return
|
||||
}
|
||||
const { checked } = item
|
||||
win.webContents.send('mt::editor-change-view', { type, checked })
|
||||
|
||||
if (type === 'sourceCode') {
|
||||
const typewriterModeMenuItem = getMenuItemById(typewriterModeMenuItemId)
|
||||
const focusModeMenuItem = getMenuItemById(focusModeMenuItemId)
|
||||
typewriterModeMenuItem.enabled = !checked
|
||||
focusModeMenuItem.enabled = !checked
|
||||
}
|
||||
}
|
||||
|
||||
export const layout = (item, win, type, value) => {
|
||||
const toggleTypeMode = (win, type) => {
|
||||
if (win && win.webContents) {
|
||||
win.webContents.send('mt::set-view-layout', { [type]: value || item.checked })
|
||||
win.webContents.send('mt::toggle-view-mode-entry', type)
|
||||
}
|
||||
}
|
||||
|
||||
const setLayout = (win, type, value) => {
|
||||
if (win && win.webContents) {
|
||||
win.webContents.send('mt::set-view-layout', { [type]: value })
|
||||
}
|
||||
}
|
||||
|
||||
const toggleLayout = (win, type) => {
|
||||
if (win && win.webContents) {
|
||||
win.webContents.send('mt::toggle-view-layout-entry', type)
|
||||
}
|
||||
}
|
||||
|
||||
export const debugToggleDevTools = win => {
|
||||
if (win && global.MARKTEXT_DEBUG) {
|
||||
win.webContents.toggleDevTools()
|
||||
}
|
||||
}
|
||||
|
||||
export const debugReloadWindow = win => {
|
||||
if (win && global.MARKTEXT_DEBUG) {
|
||||
ipcMain.emit('window-reload-by-id', win.id)
|
||||
}
|
||||
}
|
||||
|
||||
export const showCommandPalette = win => {
|
||||
if (win && win.webContents) {
|
||||
win.webContents.send('mt::show-command-palette')
|
||||
}
|
||||
}
|
||||
|
||||
export const toggleFocusMode = win => {
|
||||
toggleTypeMode(win, 'focus')
|
||||
}
|
||||
|
||||
export const toggleSourceCodeMode = win => {
|
||||
toggleTypeMode(win, 'sourceCode')
|
||||
}
|
||||
|
||||
export const toggleSidebar = win => {
|
||||
toggleLayout(win, 'showSideBar')
|
||||
}
|
||||
|
||||
export const toggleTabBar = win => {
|
||||
toggleLayout(win, 'showTabBar')
|
||||
}
|
||||
|
||||
export const showTabBar = win => {
|
||||
const tabBarMenuItem = getMenuItemById('tabBarMenuItem')
|
||||
if (tabBarMenuItem && !tabBarMenuItem.checked && tabBarMenuItem.click) {
|
||||
tabBarMenuItem.click(tabBarMenuItem, win)
|
||||
setLayout(win, 'showTabBar', true)
|
||||
}
|
||||
|
||||
export const showTableOfContents = win => {
|
||||
setLayout(win, 'rightColumn', 'toc')
|
||||
}
|
||||
|
||||
export const toggleTypewriterMode = win => {
|
||||
toggleTypeMode(win, 'typewriter')
|
||||
}
|
||||
|
||||
export const reloadImageCache = win => {
|
||||
if (win && win.webContents) {
|
||||
win.webContents.send('mt::invalidate-image-cache')
|
||||
}
|
||||
}
|
||||
|
||||
// --- Commands -------------------------------------------------------------
|
||||
|
||||
export const loadViewCommands = commandManager => {
|
||||
commandManager.add(COMMANDS.VIEW_COMMAND_PALETTE, showCommandPalette)
|
||||
commandManager.add(COMMANDS.VIEW_FOCUS_MODE, toggleFocusMode)
|
||||
commandManager.add(COMMANDS.VIEW_FORCE_RELOAD_IMAGES, reloadImageCache)
|
||||
commandManager.add(COMMANDS.VIEW_SOURCE_CODE_MODE, toggleSourceCodeMode)
|
||||
commandManager.add(COMMANDS.VIEW_TOGGLE_SIDEBAR, toggleSidebar)
|
||||
commandManager.add(COMMANDS.VIEW_TOGGLE_TABBAR, toggleTabBar)
|
||||
commandManager.add(COMMANDS.VIEW_TOGGLE_TOC, showTableOfContents)
|
||||
commandManager.add(COMMANDS.VIEW_TYPEWRITER_MODE, toggleTypewriterMode)
|
||||
|
||||
commandManager.add(COMMANDS.VIEW_DEV_RELOAD, debugReloadWindow)
|
||||
commandManager.add(COMMANDS.VIEW_TOGGLE_DEV_TOOLS, debugToggleDevTools)
|
||||
}
|
||||
|
||||
// --- IPC events -------------------------------------------------------------
|
||||
|
||||
// NOTE: Don't use static `getMenuItemById` here, instead request the menu by
|
||||
@ -46,6 +101,10 @@ export const showTabBar = win => {
|
||||
* @param {*} changes Array of changed view settings (e.g. [ {showSideBar: true} ]).
|
||||
*/
|
||||
export const viewLayoutChanged = (applicationMenu, changes) => {
|
||||
const disableMenuByName = (id, value) => {
|
||||
const menuItem = applicationMenu.getMenuItemById(id)
|
||||
menuItem.enabled = value
|
||||
}
|
||||
const changeMenuByName = (id, value) => {
|
||||
const menuItem = applicationMenu.getMenuItemById(id)
|
||||
menuItem.checked = value
|
||||
@ -62,6 +121,8 @@ export const viewLayoutChanged = (applicationMenu, changes) => {
|
||||
break
|
||||
case 'sourceCode':
|
||||
changeMenuByName('sourceCodeModeMenuItem', value)
|
||||
disableMenuByName(focusModeMenuItemId, !value)
|
||||
disableMenuByName(typewriterModeMenuItemId, !value)
|
||||
break
|
||||
case 'typewriter':
|
||||
changeMenuByName(typewriterModeMenuItemId, value)
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { ipcMain, Menu } from 'electron'
|
||||
import { isOsx } from '../../config'
|
||||
import { COMMANDS } from '../../commands'
|
||||
import { zoomIn, zoomOut } from '../../windows/utils'
|
||||
|
||||
export const minimizeWindow = win => {
|
||||
if (win) {
|
||||
@ -16,3 +18,19 @@ export const toggleAlwaysOnTop = win => {
|
||||
ipcMain.emit('window-toggle-always-on-top', win)
|
||||
}
|
||||
}
|
||||
|
||||
export const toggleFullScreen = win => {
|
||||
if (win) {
|
||||
win.setFullScreen(!win.isFullScreen())
|
||||
}
|
||||
}
|
||||
|
||||
// --- Commands -------------------------------------------------------------
|
||||
|
||||
export const loadWindowCommands = commandManager => {
|
||||
commandManager.add(COMMANDS.WINDOW_MINIMIZE, minimizeWindow)
|
||||
commandManager.add(COMMANDS.WINDOW_TOGGLE_ALWAYS_ON_TOP, toggleAlwaysOnTop)
|
||||
commandManager.add(COMMANDS.WINDOW_TOGGLE_FULL_SCREEN, toggleFullScreen)
|
||||
commandManager.add(COMMANDS.WINDOW_ZOOM_IN, zoomIn)
|
||||
commandManager.add(COMMANDS.WINDOW_ZOOM_OUT, zoomOut)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import { app, ipcMain, Menu } from 'electron'
|
||||
import log from 'electron-log'
|
||||
import { ensureDirSync, isDirectory2, isFile2 } from 'common/filesystem'
|
||||
import { isLinux, isOsx, isWindows } from '../config'
|
||||
import { parseMenu } from '../keyboard/shortcutHandler'
|
||||
import { updateSidebarMenu } from '../menu/actions/edit'
|
||||
import { updateFormatMenu } from '../menu/actions/format'
|
||||
import { updateSelectionMenus } from '../menu/actions/paragraph'
|
||||
@ -144,9 +143,9 @@ class AppMenu {
|
||||
addEditorMenu (window, options = {}) {
|
||||
const isSourceMode = !!options.sourceCodeModeEnabled
|
||||
const { windowMenus } = this
|
||||
windowMenus.set(window.id, this._buildEditorMenu(true))
|
||||
windowMenus.set(window.id, this._buildEditorMenu())
|
||||
|
||||
const { menu, shortcutMap } = windowMenus.get(window.id)
|
||||
const { menu } = windowMenus.get(window.id)
|
||||
|
||||
// Set source-code editor if preferred.
|
||||
const sourceCodeModeMenuItem = menu.getMenuItemById('sourceCodeModeMenuItem')
|
||||
@ -158,7 +157,19 @@ class AppMenu {
|
||||
typewriterModeMenuItem.enabled = false
|
||||
focusModeMenuItem.enabled = false
|
||||
}
|
||||
this._keybindings.registerKeyHandlers(window, shortcutMap)
|
||||
|
||||
const { _keybindings } = this
|
||||
_keybindings.registerEditorKeyHandlers(window)
|
||||
|
||||
if (isWindows) {
|
||||
// WORKAROUND: Window close event isn't triggered on Windows if `setIgnoreMenuShortcuts(true)` is used (Electron#32674).
|
||||
// NB: Remove this immediately if upstream is fixed because the event may be emitted twice.
|
||||
_keybindings.registerAccelerator(window, 'Alt+F4', win => {
|
||||
if (win && !win.isDestroyed()) {
|
||||
win.close()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -233,7 +244,7 @@ class AppMenu {
|
||||
const { menu: oldMenu, type } = value
|
||||
if (type !== MenuType.EDITOR) return
|
||||
|
||||
const { menu: newMenu } = this._buildEditorMenu(false, recentUsedDocuments)
|
||||
const { menu: newMenu } = this._buildEditorMenu(recentUsedDocuments)
|
||||
|
||||
// all other menu items are set automatically
|
||||
updateMenuItem(oldMenu, newMenu, 'sourceCodeModeMenuItem')
|
||||
@ -325,152 +336,14 @@ class AppMenu {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Append misc shortcuts the the given shortcut map.
|
||||
*
|
||||
* @param {*} lineEnding The shortcut map.
|
||||
*/
|
||||
_appendMiscShortcuts = shortcutMap => {
|
||||
shortcutMap.push({
|
||||
accelerator: this._keybindings.getAccelerator('tabs.cycle-forward'),
|
||||
click: (menuItem, win) => {
|
||||
win.webContents.send('mt::tabs-cycle-right')
|
||||
},
|
||||
id: null
|
||||
})
|
||||
shortcutMap.push({
|
||||
accelerator: this._keybindings.getAccelerator('tabs.cycle-backward'),
|
||||
click: (menuItem, win) => {
|
||||
win.webContents.send('mt::tabs-cycle-left')
|
||||
},
|
||||
id: null
|
||||
})
|
||||
shortcutMap.push({
|
||||
accelerator: this._keybindings.getAccelerator('tabs.switch-to-left'),
|
||||
click: (menuItem, win) => {
|
||||
win.webContents.send('mt::tabs-cycle-left')
|
||||
},
|
||||
id: null
|
||||
})
|
||||
shortcutMap.push({
|
||||
accelerator: this._keybindings.getAccelerator('tabs.switch-to-right'),
|
||||
click: (menuItem, win) => {
|
||||
win.webContents.send('mt::tabs-cycle-right')
|
||||
},
|
||||
id: null
|
||||
})
|
||||
shortcutMap.push({
|
||||
accelerator: this._keybindings.getAccelerator('tabs.switch-to-first'),
|
||||
click: (menuItem, win) => {
|
||||
win.webContents.send('mt::switch-first-tab')
|
||||
},
|
||||
id: null
|
||||
})
|
||||
shortcutMap.push({
|
||||
accelerator: this._keybindings.getAccelerator('tabs.switch-to-second'),
|
||||
click: (menuItem, win) => {
|
||||
win.webContents.send('mt::switch-second-tab')
|
||||
},
|
||||
id: null
|
||||
})
|
||||
shortcutMap.push({
|
||||
accelerator: this._keybindings.getAccelerator('tabs.switch-to-third'),
|
||||
click: (menuItem, win) => {
|
||||
win.webContents.send('mt::switch-third-tab')
|
||||
},
|
||||
id: null
|
||||
})
|
||||
shortcutMap.push({
|
||||
accelerator: this._keybindings.getAccelerator('tabs.switch-to-fourth'),
|
||||
click: (menuItem, win) => {
|
||||
win.webContents.send('mt::switch-fourth-tab')
|
||||
},
|
||||
id: null
|
||||
})
|
||||
shortcutMap.push({
|
||||
accelerator: this._keybindings.getAccelerator('tabs.switch-to-fifth'),
|
||||
click: (menuItem, win) => {
|
||||
win.webContents.send('mt::switch-fifth-tab')
|
||||
},
|
||||
id: null
|
||||
})
|
||||
shortcutMap.push({
|
||||
accelerator: this._keybindings.getAccelerator('tabs.switch-to-sixth'),
|
||||
click: (menuItem, win) => {
|
||||
win.webContents.send('mt::switch-sixth-tab')
|
||||
},
|
||||
id: null
|
||||
})
|
||||
shortcutMap.push({
|
||||
accelerator: this._keybindings.getAccelerator('tabs.switch-to-seventh'),
|
||||
click: (menuItem, win) => {
|
||||
win.webContents.send('mt::switch-seventh-tab')
|
||||
},
|
||||
id: null
|
||||
})
|
||||
shortcutMap.push({
|
||||
accelerator: this._keybindings.getAccelerator('tabs.switch-to-eighth'),
|
||||
click: (menuItem, win) => {
|
||||
win.webContents.send('mt::switch-eighth-tab')
|
||||
},
|
||||
id: null
|
||||
})
|
||||
shortcutMap.push({
|
||||
accelerator: this._keybindings.getAccelerator('tabs.switch-to-ninth'),
|
||||
click: (menuItem, win) => {
|
||||
win.webContents.send('mt::switch-ninth-tab')
|
||||
},
|
||||
id: null
|
||||
})
|
||||
shortcutMap.push({
|
||||
accelerator: this._keybindings.getAccelerator('tabs.switch-to-tenth'),
|
||||
click: (menuItem, win) => {
|
||||
win.webContents.send('mt::switch-tenth-tab')
|
||||
},
|
||||
id: null
|
||||
})
|
||||
shortcutMap.push({
|
||||
accelerator: this._keybindings.getAccelerator('file.quick-open'),
|
||||
click: (menuItem, win) => {
|
||||
win.webContents.send('mt::execute-command-by-id', 'file.quick-open')
|
||||
},
|
||||
id: null
|
||||
})
|
||||
|
||||
if (isWindows) {
|
||||
// WORKAROUND: Window close event isn't triggered on Windows if `setIgnoreMenuShortcuts(true)` is used (Electron#32674).
|
||||
// NB: Remove this immediately if upstream is fixed because the event may be emitted twice.
|
||||
shortcutMap.push({
|
||||
accelerator: 'Alt+F4',
|
||||
click: (menuItem, win) => {
|
||||
if (win && !win.isDestroyed()) {
|
||||
win.close()
|
||||
}
|
||||
},
|
||||
id: null
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
_buildEditorMenu (createShortcutMap, recentUsedDocuments = null) {
|
||||
_buildEditorMenu (recentUsedDocuments = null) {
|
||||
if (!recentUsedDocuments) {
|
||||
recentUsedDocuments = this.getRecentlyUsedDocuments()
|
||||
}
|
||||
|
||||
const menuTemplate = configureMenu(this._keybindings, this._preferences, recentUsedDocuments)
|
||||
const menu = Menu.buildFromTemplate(menuTemplate)
|
||||
|
||||
let shortcutMap = null
|
||||
if (createShortcutMap) {
|
||||
shortcutMap = parseMenu(menuTemplate)
|
||||
this._appendMiscShortcuts(shortcutMap)
|
||||
}
|
||||
|
||||
return {
|
||||
shortcutMap,
|
||||
menu,
|
||||
type: MenuType.EDITOR
|
||||
}
|
||||
return { menu, type: MenuType.EDITOR }
|
||||
}
|
||||
|
||||
_buildSettingMenu () {
|
||||
|
@ -4,7 +4,11 @@ import * as actions from '../actions/file'
|
||||
const dockMenu = Menu.buildFromTemplate([{
|
||||
label: 'Open...',
|
||||
click (menuItem, browserWindow) {
|
||||
actions.openFile(browserWindow)
|
||||
if (browserWindow) {
|
||||
actions.openFile(browserWindow)
|
||||
} else {
|
||||
actions.newEditorWindow()
|
||||
}
|
||||
}
|
||||
}, {
|
||||
label: 'Clear Recent',
|
||||
|
@ -1,38 +1,39 @@
|
||||
import * as actions from '../actions/edit'
|
||||
import { isOsx } from '../../config'
|
||||
import { COMMANDS } from '../../commands'
|
||||
|
||||
export default function (keybindings) {
|
||||
return {
|
||||
label: '&Edit',
|
||||
submenu: [{
|
||||
label: 'Undo',
|
||||
accelerator: keybindings.getAccelerator('edit.undo'),
|
||||
accelerator: keybindings.getAccelerator(COMMANDS.EDIT_UNDO),
|
||||
click: (menuItem, browserWindow) => {
|
||||
actions.edit(browserWindow, 'undo')
|
||||
actions.editorUndo(browserWindow)
|
||||
}
|
||||
}, {
|
||||
label: 'Redo',
|
||||
accelerator: keybindings.getAccelerator('edit.redo'),
|
||||
accelerator: keybindings.getAccelerator(COMMANDS.EDIT_REDO),
|
||||
click: (menuItem, browserWindow) => {
|
||||
actions.edit(browserWindow, 'redo')
|
||||
actions.editorRedo(browserWindow)
|
||||
}
|
||||
}, {
|
||||
type: 'separator'
|
||||
}, {
|
||||
label: 'Cut',
|
||||
accelerator: keybindings.getAccelerator('edit.cut'),
|
||||
accelerator: keybindings.getAccelerator(COMMANDS.EDIT_CUT),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.nativeCut(browserWindow)
|
||||
}
|
||||
}, {
|
||||
label: 'Copy',
|
||||
accelerator: keybindings.getAccelerator('edit.copy'),
|
||||
accelerator: keybindings.getAccelerator(COMMANDS.EDIT_COPY),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.nativeCopy(browserWindow)
|
||||
}
|
||||
}, {
|
||||
label: 'Paste',
|
||||
accelerator: keybindings.getAccelerator('edit.paste'),
|
||||
accelerator: keybindings.getAccelerator(COMMANDS.EDIT_PASTE),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.nativePaste(browserWindow)
|
||||
}
|
||||
@ -40,83 +41,83 @@ export default function (keybindings) {
|
||||
type: 'separator'
|
||||
}, {
|
||||
label: 'Copy as Markdown',
|
||||
accelerator: keybindings.getAccelerator('edit.copy-as-markdown'),
|
||||
accelerator: keybindings.getAccelerator(COMMANDS.EDIT_COPY_AS_MARKDOWN),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.edit(browserWindow, 'copyAsMarkdown')
|
||||
actions.editorCopyAsMarkdown(browserWindow)
|
||||
}
|
||||
}, {
|
||||
label: 'Copy as HTML',
|
||||
accelerator: keybindings.getAccelerator('edit.copy-as-html'),
|
||||
accelerator: keybindings.getAccelerator(COMMANDS.EDIT_COPY_AS_HTML),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.edit(browserWindow, 'copyAsHtml')
|
||||
actions.editorCopyAsHtml(browserWindow)
|
||||
}
|
||||
}, {
|
||||
label: 'Paste as Plain Text',
|
||||
accelerator: keybindings.getAccelerator('edit.paste-as-plaintext'),
|
||||
accelerator: keybindings.getAccelerator(COMMANDS.EDIT_PASTE_AS_PLAINTEXT),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.edit(browserWindow, 'pasteAsPlainText')
|
||||
actions.editorPasteAsPlainText(browserWindow)
|
||||
}
|
||||
}, {
|
||||
type: 'separator'
|
||||
}, {
|
||||
label: 'Select All',
|
||||
accelerator: keybindings.getAccelerator('edit.select-all'),
|
||||
accelerator: keybindings.getAccelerator(COMMANDS.EDIT_SELECT_ALL),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.edit(browserWindow, 'selectAll')
|
||||
actions.editorSelectAll(browserWindow)
|
||||
}
|
||||
}, {
|
||||
type: 'separator'
|
||||
}, {
|
||||
label: 'Duplicate',
|
||||
accelerator: keybindings.getAccelerator('edit.duplicate'),
|
||||
accelerator: keybindings.getAccelerator(COMMANDS.EDIT_DUPLICATE),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.edit(browserWindow, 'duplicate')
|
||||
actions.editorDuplicate(browserWindow)
|
||||
}
|
||||
}, {
|
||||
label: 'Create Paragraph',
|
||||
accelerator: keybindings.getAccelerator('edit.create-paragraph'),
|
||||
accelerator: keybindings.getAccelerator(COMMANDS.EDIT_CREATE_PARAGRAPH),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.edit(browserWindow, 'createParagraph')
|
||||
actions.editorCreateParagraph(browserWindow)
|
||||
}
|
||||
}, {
|
||||
label: 'Delete Paragraph',
|
||||
accelerator: keybindings.getAccelerator('edit.delete-paragraph'),
|
||||
accelerator: keybindings.getAccelerator(COMMANDS.EDIT_DELETE_PARAGRAPH),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.edit(browserWindow, 'deleteParagraph')
|
||||
actions.editorDeleteParagraph(browserWindow)
|
||||
}
|
||||
}, {
|
||||
type: 'separator'
|
||||
}, {
|
||||
label: 'Find',
|
||||
accelerator: keybindings.getAccelerator('edit.find'),
|
||||
accelerator: keybindings.getAccelerator(COMMANDS.EDIT_FIND),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.edit(browserWindow, 'find')
|
||||
actions.editorFind(browserWindow)
|
||||
}
|
||||
}, {
|
||||
label: 'Find Next',
|
||||
accelerator: keybindings.getAccelerator('edit.find-next'),
|
||||
accelerator: keybindings.getAccelerator(COMMANDS.EDIT_FIND_NEXT),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.edit(browserWindow, 'findNext')
|
||||
actions.editorFindNext(browserWindow)
|
||||
}
|
||||
}, {
|
||||
label: 'Find Previous',
|
||||
accelerator: keybindings.getAccelerator('edit.find-previous'),
|
||||
accelerator: keybindings.getAccelerator(COMMANDS.EDIT_FIND_PREVIOUS),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.edit(browserWindow, 'findPrev')
|
||||
actions.editorFindPrevious(browserWindow)
|
||||
}
|
||||
}, {
|
||||
label: 'Replace',
|
||||
accelerator: keybindings.getAccelerator('edit.replace'),
|
||||
accelerator: keybindings.getAccelerator(COMMANDS.EDIT_REPLACE),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.edit(browserWindow, 'replace')
|
||||
actions.editorReplace(browserWindow)
|
||||
}
|
||||
}, {
|
||||
type: 'separator'
|
||||
}, {
|
||||
label: 'Find in Folder',
|
||||
accelerator: keybindings.getAccelerator('edit.find-in-folder'),
|
||||
accelerator: keybindings.getAccelerator(COMMANDS.EDIT_FIND_IN_FOLDER),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.edit(browserWindow, 'findInFolder')
|
||||
actions.findInFolder(browserWindow)
|
||||
}
|
||||
}, {
|
||||
type: 'separator'
|
||||
@ -124,7 +125,7 @@ export default function (keybindings) {
|
||||
label: 'Screenshot',
|
||||
id: 'screenshot',
|
||||
visible: isOsx,
|
||||
accelerator: keybindings.getAccelerator('edit.screenshot'),
|
||||
accelerator: keybindings.getAccelerator(COMMANDS.EDIT_SCREENSHOT),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.screenshot(browserWindow)
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { app } from 'electron'
|
||||
import * as actions from '../actions/file'
|
||||
import { userSetting } from '../actions/marktext'
|
||||
import { showTabBar } from '../actions/view'
|
||||
import { isOsx } from '../../config'
|
||||
|
||||
export default function (keybindings, userPreference, recentlyUsedFiles) {
|
||||
@ -13,11 +12,10 @@ export default function (keybindings, userPreference, recentlyUsedFiles) {
|
||||
accelerator: keybindings.getAccelerator('file.new-tab'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.newBlankTab(browserWindow)
|
||||
showTabBar(browserWindow)
|
||||
}
|
||||
}, {
|
||||
label: 'New Window',
|
||||
accelerator: keybindings.getAccelerator('file.new-file'),
|
||||
accelerator: keybindings.getAccelerator('file.new-window'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.newEditorWindow()
|
||||
}
|
||||
@ -77,8 +75,6 @@ export default function (keybindings, userPreference, recentlyUsedFiles) {
|
||||
|
||||
fileMenu.submenu.push({
|
||||
type: 'separator'
|
||||
}, {
|
||||
type: 'separator'
|
||||
}, {
|
||||
label: 'Save',
|
||||
accelerator: keybindings.getAccelerator('file.save'),
|
||||
@ -139,7 +135,7 @@ export default function (keybindings, userPreference, recentlyUsedFiles) {
|
||||
label: 'Print',
|
||||
accelerator: keybindings.getAccelerator('file.print'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.print(browserWindow)
|
||||
actions.printDocument(browserWindow)
|
||||
}
|
||||
}, {
|
||||
type: 'separator',
|
||||
|
@ -9,24 +9,24 @@ export default function (keybindings) {
|
||||
label: 'Bold',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('format.strong'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.format(browserWindow, 'strong')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.strong(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'emphasisMenuItem',
|
||||
label: 'Italic',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('format.emphasis'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.format(browserWindow, 'em')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.emphasis(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'underlineMenuItem',
|
||||
label: 'Underline',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('format.underline'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.format(browserWindow, 'u')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.underline(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
type: 'separator'
|
||||
@ -35,24 +35,24 @@ export default function (keybindings) {
|
||||
label: 'Superscript',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('format.superscript'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.format(browserWindow, 'sup')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.superscript(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'subscriptMenuItem',
|
||||
label: 'Subscript',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('format.subscript'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.format(browserWindow, 'sub')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.subscript(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'highlightMenuItem',
|
||||
label: 'Highlight',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('format.highlight'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.format(browserWindow, 'mark')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.highlight(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
type: 'separator'
|
||||
@ -61,16 +61,16 @@ export default function (keybindings) {
|
||||
label: 'Inline Code',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('format.inline-code'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.format(browserWindow, 'inline_code')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.inlineCode(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'inlineMathMenuItem',
|
||||
label: 'Inline Math',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('format.inline-math'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.format(browserWindow, 'inline_math')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.inlineMath(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
type: 'separator'
|
||||
@ -79,32 +79,32 @@ export default function (keybindings) {
|
||||
label: 'Strikethrough',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('format.strike'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.format(browserWindow, 'del')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.strikethrough(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'hyperlinkMenuItem',
|
||||
label: 'Hyperlink',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('format.hyperlink'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.format(browserWindow, 'link')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.hyperlink(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'imageMenuItem',
|
||||
label: 'Image',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('format.image'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.format(browserWindow, 'image')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.image(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
type: 'separator'
|
||||
}, {
|
||||
label: 'Clear Formatting',
|
||||
accelerator: keybindings.getAccelerator('format.clear-format'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.format(browserWindow, 'clear')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.clearFormat(focusedWindow)
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { app, Menu } from 'electron'
|
||||
import { app } from 'electron'
|
||||
import { showAboutDialog } from '../actions/help'
|
||||
import * as actions from '../actions/marktext'
|
||||
|
||||
@ -9,13 +9,13 @@ export default function (keybindings) {
|
||||
label: 'MarkText',
|
||||
submenu: [{
|
||||
label: 'About MarkText',
|
||||
click (menuItem, browserWindow) {
|
||||
showAboutDialog(browserWindow)
|
||||
click (menuItem, focusedWindow) {
|
||||
showAboutDialog(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
label: 'Check for updates...',
|
||||
click (menuItem, browserWindow) {
|
||||
actions.checkUpdates(browserWindow)
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.checkUpdates(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
label: 'Preferences',
|
||||
@ -35,18 +35,18 @@ export default function (keybindings) {
|
||||
label: 'Hide MarkText',
|
||||
accelerator: keybindings.getAccelerator('mt.hide'),
|
||||
click () {
|
||||
Menu.sendActionToFirstResponder('hide:')
|
||||
actions.osxHide()
|
||||
}
|
||||
}, {
|
||||
label: 'Hide Others',
|
||||
accelerator: keybindings.getAccelerator('mt.hide-others'),
|
||||
click () {
|
||||
Menu.sendActionToFirstResponder('hideOtherApplications:')
|
||||
actions.osxHideAll()
|
||||
}
|
||||
}, {
|
||||
label: 'Show All',
|
||||
click () {
|
||||
Menu.sendActionToFirstResponder('unhideAllApplications:')
|
||||
actions.osxShowAll()
|
||||
}
|
||||
}, {
|
||||
type: 'separator'
|
||||
|
@ -9,48 +9,48 @@ export default function (keybindings) {
|
||||
label: 'Heading 1',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('paragraph.heading-1'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.paragraph(browserWindow, 'heading 1')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.heading1(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'heading2MenuItem',
|
||||
label: 'Heading 2',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('paragraph.heading-2'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.paragraph(browserWindow, 'heading 2')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.heading2(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'heading3MenuItem',
|
||||
label: 'Heading 3',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('paragraph.heading-3'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.paragraph(browserWindow, 'heading 3')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.heading3(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'heading4MenuItem',
|
||||
label: 'Heading 4',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('paragraph.heading-4'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.paragraph(browserWindow, 'heading 4')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.heading4(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'heading5MenuItem',
|
||||
label: 'Heading 5',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('paragraph.heading-5'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.paragraph(browserWindow, 'heading 5')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.heading5(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'heading6MenuItem',
|
||||
label: 'Heading 6',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('paragraph.heading-6'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.paragraph(browserWindow, 'heading 6')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.heading6(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
type: 'separator'
|
||||
@ -58,15 +58,15 @@ export default function (keybindings) {
|
||||
id: 'upgradeHeadingMenuItem',
|
||||
label: 'Promote Heading',
|
||||
accelerator: keybindings.getAccelerator('paragraph.upgrade-heading'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.paragraph(browserWindow, 'upgrade heading')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.increaseHeading(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'degradeHeadingMenuItem',
|
||||
label: 'Demote Heading',
|
||||
accelerator: keybindings.getAccelerator('paragraph.degrade-heading'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.paragraph(browserWindow, 'degrade heading')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.degradeHeading(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
type: 'separator'
|
||||
@ -75,40 +75,40 @@ export default function (keybindings) {
|
||||
label: 'Table',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('paragraph.table'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.paragraph(browserWindow, 'table')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.table(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'codeFencesMenuItem',
|
||||
label: 'Code Fences',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('paragraph.code-fence'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.paragraph(browserWindow, 'pre')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.codeFence(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'quoteBlockMenuItem',
|
||||
label: 'Quote Block',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('paragraph.quote-block'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.paragraph(browserWindow, 'blockquote')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.quoteBlock(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'mathBlockMenuItem',
|
||||
label: 'Math Block',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('paragraph.math-formula'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.paragraph(browserWindow, 'mathblock')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.mathFormula(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'htmlBlockMenuItem',
|
||||
label: 'Html Block',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('paragraph.html-block'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.paragraph(browserWindow, 'html')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.htmlBlock(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
type: 'separator'
|
||||
@ -117,24 +117,24 @@ export default function (keybindings) {
|
||||
label: 'Ordered List',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('paragraph.order-list'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.paragraph(browserWindow, 'ol-order')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.orderedList(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'bulletListMenuItem',
|
||||
label: 'Bullet List',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('paragraph.bullet-list'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.paragraph(browserWindow, 'ul-bullet')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.bulletList(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'taskListMenuItem',
|
||||
label: 'Task List',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('paragraph.task-list'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.paragraph(browserWindow, 'ul-task')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.taskList(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
type: 'separator'
|
||||
@ -143,8 +143,8 @@ export default function (keybindings) {
|
||||
label: 'Loose List Item',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('paragraph.loose-list-item'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.paragraph(browserWindow, 'loose-list-item')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.looseListItem(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
type: 'separator'
|
||||
@ -153,24 +153,24 @@ export default function (keybindings) {
|
||||
label: 'Paragraph',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('paragraph.paragraph'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.paragraph(browserWindow, 'paragraph')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.paragraph(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'horizontalLineMenuItem',
|
||||
label: 'Horizontal Rule',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('paragraph.horizontal-line'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.paragraph(browserWindow, 'hr')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.horizontalLine(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'frontMatterMenuItem',
|
||||
label: 'Front Matter',
|
||||
type: 'checkbox',
|
||||
accelerator: keybindings.getAccelerator('paragraph.front-matter'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.paragraph(browserWindow, 'front-matter')
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.frontMatter(focusedWindow)
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { ipcMain } from 'electron'
|
||||
import * as actions from '../actions/view'
|
||||
|
||||
export default function (keybindings) {
|
||||
@ -7,8 +6,8 @@ export default function (keybindings) {
|
||||
submenu: [{
|
||||
label: 'Command Palette...',
|
||||
accelerator: keybindings.getAccelerator('view.command-palette'),
|
||||
click (menuItem, browserWindow) {
|
||||
actions.showCommandPalette(browserWindow)
|
||||
click (menuItem, focusedWindow) {
|
||||
actions.showCommandPalette(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
type: 'separator'
|
||||
@ -18,12 +17,8 @@ export default function (keybindings) {
|
||||
accelerator: keybindings.getAccelerator('view.source-code-mode'),
|
||||
type: 'checkbox',
|
||||
checked: false,
|
||||
click (item, browserWindow, event) {
|
||||
// if we call this function, the checked state is not set
|
||||
if (!event) {
|
||||
item.checked = !item.checked
|
||||
}
|
||||
actions.typeMode(browserWindow, 'sourceCode', item)
|
||||
click (item, focusedWindow) {
|
||||
actions.toggleSourceCodeMode(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'typewriterModeMenuItem',
|
||||
@ -31,12 +26,8 @@ export default function (keybindings) {
|
||||
accelerator: keybindings.getAccelerator('view.typewriter-mode'),
|
||||
type: 'checkbox',
|
||||
checked: false,
|
||||
click (item, browserWindow, event) {
|
||||
// if we call this function, the checked state is not set
|
||||
if (!event) {
|
||||
item.checked = !item.checked
|
||||
}
|
||||
actions.typeMode(browserWindow, 'typewriter', item)
|
||||
click (item, focusedWindow) {
|
||||
actions.toggleTypewriterMode(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
id: 'focusModeMenuItem',
|
||||
@ -44,12 +35,8 @@ export default function (keybindings) {
|
||||
accelerator: keybindings.getAccelerator('view.focus-mode'),
|
||||
type: 'checkbox',
|
||||
checked: false,
|
||||
click (item, browserWindow, event) {
|
||||
// if we call this function, the checked state is not set
|
||||
if (!event) {
|
||||
item.checked = !item.checked
|
||||
}
|
||||
actions.typeMode(browserWindow, 'focus', item)
|
||||
click (item, focusedWindow) {
|
||||
actions.toggleFocusMode(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
type: 'separator'
|
||||
@ -59,13 +46,8 @@ export default function (keybindings) {
|
||||
accelerator: keybindings.getAccelerator('view.toggle-sidebar'),
|
||||
type: 'checkbox',
|
||||
checked: false,
|
||||
click (item, browserWindow, event) {
|
||||
// if we call this function, the checked state is not set
|
||||
if (!event) {
|
||||
item.checked = !item.checked
|
||||
}
|
||||
|
||||
actions.layout(item, browserWindow, 'showSideBar')
|
||||
click (item, focusedWindow) {
|
||||
actions.toggleSidebar(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
label: 'Show Tab Bar',
|
||||
@ -73,51 +55,41 @@ export default function (keybindings) {
|
||||
accelerator: keybindings.getAccelerator('view.toggle-tabbar'),
|
||||
type: 'checkbox',
|
||||
checked: false,
|
||||
click (item, browserWindow, event) {
|
||||
// if we call this function, the checked state is not set
|
||||
if (!event) {
|
||||
item.checked = !item.checked
|
||||
}
|
||||
|
||||
actions.layout(item, browserWindow, 'showTabBar')
|
||||
click (item, focusedWindow) {
|
||||
actions.toggleTabBar(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
label: 'Toggle Table of Contents',
|
||||
id: 'tocMenuItem',
|
||||
accelerator: keybindings.getAccelerator('view.toggle-toc'),
|
||||
click (_, browserWindow) {
|
||||
actions.layout(null, browserWindow, 'rightColumn', 'toc')
|
||||
click (_, focusedWindow) {
|
||||
actions.showTableOfContents(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
label: 'Reload Images',
|
||||
accelerator: keybindings.getAccelerator('view.reload-images'),
|
||||
click (item, focusedWindow) {
|
||||
if (focusedWindow) {
|
||||
focusedWindow.webContents.send('mt::invalidate-image-cache', {})
|
||||
}
|
||||
actions.reloadImageCache(focusedWindow)
|
||||
}
|
||||
}, {
|
||||
type: 'separator'
|
||||
}]
|
||||
}
|
||||
|
||||
if (global.MARKTEXT_DEBUG) {
|
||||
viewMenu.submenu.push({
|
||||
type: 'separator'
|
||||
})
|
||||
viewMenu.submenu.push({
|
||||
label: 'Show Developer Tools',
|
||||
accelerator: keybindings.getAccelerator('view.toggle-dev-tools'),
|
||||
click (item, focusedWindow) {
|
||||
if (focusedWindow) {
|
||||
focusedWindow.webContents.toggleDevTools()
|
||||
}
|
||||
click (item, win) {
|
||||
actions.debugToggleDevTools(win)
|
||||
}
|
||||
})
|
||||
viewMenu.submenu.push({
|
||||
label: 'Reload window',
|
||||
accelerator: keybindings.getAccelerator('view.dev-reload'),
|
||||
click (item, focusedWindow) {
|
||||
if (focusedWindow) {
|
||||
ipcMain.emit('window-reload-by-id', focusedWindow.id)
|
||||
}
|
||||
actions.debugReloadWindow(focusedWindow)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Menu } from 'electron'
|
||||
import { minimizeWindow, toggleAlwaysOnTop } from '../actions/window'
|
||||
import { minimizeWindow, toggleAlwaysOnTop, toggleFullScreen } from '../actions/window'
|
||||
import { zoomIn, zoomOut } from '../../windows/utils'
|
||||
import { isOsx } from '../../config'
|
||||
|
||||
@ -40,9 +40,9 @@ export default function (keybindings) {
|
||||
}, {
|
||||
label: 'Show in Full Screen',
|
||||
accelerator: keybindings.getAccelerator('window.toggle-full-screen'),
|
||||
click (item, focusedWindow) {
|
||||
if (focusedWindow) {
|
||||
focusedWindow.setFullScreen(!focusedWindow.isFullScreen())
|
||||
click (item, browserWindow) {
|
||||
if (browserWindow) {
|
||||
toggleFullScreen(browserWindow)
|
||||
}
|
||||
}
|
||||
}]
|
||||
|
@ -346,6 +346,7 @@
|
||||
},
|
||||
"spellcheckerLanguage": {
|
||||
"description": "Spelling--The spell checker language",
|
||||
"type": "string",
|
||||
"pattern": "^[a-z]{2,3}(?:[-](?:[0-9]|[a-zA-Z]){2,}){0,2}$",
|
||||
"default": "en-US"
|
||||
},
|
||||
|
@ -5,7 +5,7 @@ const commandDescriptions = Object.freeze({
|
||||
|
||||
'mt.hide': 'MarkText: Hide MarkText',
|
||||
'mt.hide-others': 'MarkText: Hide Others',
|
||||
'file.new-file': 'File: New Window',
|
||||
'file.new-window': 'File: New Window',
|
||||
'file.new-tab': 'File: New Tab',
|
||||
'file.open-file': 'File: Open file',
|
||||
'file.open-folder': 'File: Open Folder',
|
||||
@ -102,7 +102,7 @@ const commandDescriptions = Object.freeze({
|
||||
// # Menu descriptions but not available as command
|
||||
// #
|
||||
|
||||
'view.reload-images': 'View: Clear cache and reload images',
|
||||
'view.reload-images': 'View: Force reload images',
|
||||
|
||||
// ============================================
|
||||
// # Additional command descriptions
|
||||
|
@ -43,7 +43,7 @@ const commands = [
|
||||
ipcRenderer.emit('mt::new-untitled-tab', null)
|
||||
}
|
||||
}, {
|
||||
id: 'file.new-file',
|
||||
id: 'file.new-window',
|
||||
execute: async () => {
|
||||
ipcRenderer.send('mt::cmd-new-editor-window')
|
||||
}
|
||||
@ -581,12 +581,12 @@ const commands = [
|
||||
}, {
|
||||
id: 'view.toggle-sidebar',
|
||||
execute: async () => {
|
||||
bus.$emit('view:toggle-view-layout-entry', 'showSideBar')
|
||||
bus.$emit('view:toggle-layout-entry', 'showSideBar')
|
||||
}
|
||||
}, {
|
||||
id: 'view.toggle-tabbar',
|
||||
execute: async () => {
|
||||
bus.$emit('view:toggle-view-layout-entry', 'showTabBar')
|
||||
bus.$emit('view:toggle-layout-entry', 'showTabBar')
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -125,7 +125,6 @@ export default {
|
||||
dispatch('LISTEN_FOR_TWEET')
|
||||
// module: layout
|
||||
dispatch('LISTEN_FOR_LAYOUT')
|
||||
dispatch('LISTEN_FOR_REQUEST_LAYOUT')
|
||||
// module: listenForMain
|
||||
dispatch('LISTEN_FOR_EDIT')
|
||||
dispatch('LISTEN_FOR_VIEW')
|
||||
|
@ -646,7 +646,7 @@ const actions = {
|
||||
showSideBar: !!sideBarVisibility,
|
||||
showTabBar: !!tabBarVisibility
|
||||
})
|
||||
dispatch('SET_LAYOUT_MENU_ITEM')
|
||||
dispatch('DISPATCH_LAYOUT_MENU_ITEMS')
|
||||
|
||||
commit('SET_MODE', {
|
||||
type: 'sourceCode',
|
||||
@ -701,35 +701,8 @@ const actions = {
|
||||
},
|
||||
|
||||
LISTEN_FOR_SWITCH_TABS ({ commit, state, dispatch }) {
|
||||
ipcRenderer.on('mt::switch-first-tab', e => {
|
||||
dispatch('SWITCH_TABS', 1)
|
||||
})
|
||||
ipcRenderer.on('mt::switch-second-tab', e => {
|
||||
dispatch('SWITCH_TABS', 2)
|
||||
})
|
||||
ipcRenderer.on('mt::switch-third-tab', e => {
|
||||
dispatch('SWITCH_TABS', 3)
|
||||
})
|
||||
ipcRenderer.on('mt::switch-fourth-tab', e => {
|
||||
dispatch('SWITCH_TABS', 4)
|
||||
})
|
||||
ipcRenderer.on('mt::switch-fifth-tab', e => {
|
||||
dispatch('SWITCH_TABS', 5)
|
||||
})
|
||||
ipcRenderer.on('mt::switch-sixth-tab', e => {
|
||||
dispatch('SWITCH_TABS', 6)
|
||||
})
|
||||
ipcRenderer.on('mt::switch-seventh-tab', e => {
|
||||
dispatch('SWITCH_TABS', 7)
|
||||
})
|
||||
ipcRenderer.on('mt::switch-eighth-tab', e => {
|
||||
dispatch('SWITCH_TABS', 8)
|
||||
})
|
||||
ipcRenderer.on('mt::switch-ninth-tab', e => {
|
||||
dispatch('SWITCH_TABS', 9)
|
||||
})
|
||||
ipcRenderer.on('mt::switch-tenth-tab', e => {
|
||||
dispatch('SWITCH_TABS', 10)
|
||||
ipcRenderer.on('mt::switch-tab-by-index', (event, index) => {
|
||||
dispatch('SWITCH_TAB_BY_INDEX', index)
|
||||
})
|
||||
},
|
||||
|
||||
@ -796,29 +769,30 @@ const actions = {
|
||||
console.error(`CYCLE_TABS: Cannot find next tab (index="${nextTabIndex}").`)
|
||||
return
|
||||
}
|
||||
|
||||
commit('SET_CURRENT_FILE', nextTab)
|
||||
dispatch('UPDATE_LINE_ENDING_MENU')
|
||||
},
|
||||
|
||||
// switch tabs with Alt+#num.
|
||||
SWITCH_TABS ({ commit, dispatch, state }, num) {
|
||||
SWITCH_TAB_BY_INDEX ({ commit, dispatch, state }, nextTabIndex) {
|
||||
const { tabs, currentFile } = state
|
||||
if (tabs.length <= 1 || num > tabs.length) {
|
||||
if (nextTabIndex < 0 || nextTabIndex >= tabs.length) {
|
||||
console.warn('Invalid tab index:', nextTabIndex)
|
||||
return
|
||||
}
|
||||
|
||||
const currentIndex = tabs.findIndex(t => t.id === currentFile.id)
|
||||
if (currentIndex === -1) {
|
||||
console.error('CYCLE_TABS: Cannot find current tab index.')
|
||||
console.error('Cannot find current tab index.')
|
||||
return
|
||||
}
|
||||
|
||||
const nextTabIndex = num - 1
|
||||
const nextTab = tabs[nextTabIndex]
|
||||
if (!nextTab || !nextTab.id) {
|
||||
console.error(`CYCLE_TABS: Cannot find next tab (index="${nextTabIndex}").`)
|
||||
console.error(`Cannot find tab by index="${nextTabIndex}".`)
|
||||
return
|
||||
}
|
||||
|
||||
commit('SET_CURRENT_FILE', nextTab)
|
||||
dispatch('UPDATE_LINE_ENDING_MENU')
|
||||
},
|
||||
@ -916,7 +890,7 @@ const actions = {
|
||||
const { tabs } = state
|
||||
if (always || tabs.length === 1) {
|
||||
commit('SET_LAYOUT', { showTabBar: true })
|
||||
dispatch('SET_LAYOUT_MENU_ITEM')
|
||||
dispatch('DISPATCH_LAYOUT_MENU_ITEMS')
|
||||
}
|
||||
},
|
||||
|
||||
@ -1231,7 +1205,7 @@ const actions = {
|
||||
},
|
||||
|
||||
LISTEN_FOR_RELOAD_IMAGES () {
|
||||
ipcRenderer.on('mt::invalidate-image-cache', (e) => {
|
||||
ipcRenderer.on('mt::invalidate-image-cache', () => {
|
||||
bus.$emit('invalidate-image-cache')
|
||||
})
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ const mutations = {
|
||||
}
|
||||
|
||||
const actions = {
|
||||
LISTEN_FOR_LAYOUT ({ state, commit }) {
|
||||
LISTEN_FOR_LAYOUT ({ state, commit, dispatch }) {
|
||||
ipcRenderer.on('mt::set-view-layout', (e, layout) => {
|
||||
if (layout.rightColumn) {
|
||||
commit('SET_LAYOUT', {
|
||||
@ -44,26 +44,27 @@ const actions = {
|
||||
} else {
|
||||
commit('SET_LAYOUT', layout)
|
||||
}
|
||||
dispatch('DISPATCH_LAYOUT_MENU_ITEMS')
|
||||
})
|
||||
|
||||
bus.$on('view:toggle-view-layout-entry', entryName => {
|
||||
ipcRenderer.on('mt::toggle-view-layout-entry', (event, entryName) => {
|
||||
commit('TOGGLE_LAYOUT_ENTRY', entryName)
|
||||
dispatch('DISPATCH_LAYOUT_MENU_ITEMS')
|
||||
})
|
||||
|
||||
bus.$on('view:toggle-layout-entry', entryName => {
|
||||
commit('TOGGLE_LAYOUT_ENTRY', entryName)
|
||||
const item = {}
|
||||
item[entryName] = state[entryName]
|
||||
const { windowId } = global.marktext.env
|
||||
ipcRenderer.send('mt::view-layout-changed', windowId, item)
|
||||
ipcRenderer.send('mt::view-layout-changed', windowId, { [entryName]: state[entryName] })
|
||||
})
|
||||
},
|
||||
LISTEN_FOR_REQUEST_LAYOUT ({ dispatch }) {
|
||||
ipcRenderer.on('mt::request-for-view-layout', () => {
|
||||
dispatch('SET_LAYOUT_MENU_ITEM')
|
||||
})
|
||||
},
|
||||
SET_LAYOUT_MENU_ITEM ({ state }) {
|
||||
|
||||
DISPATCH_LAYOUT_MENU_ITEMS ({ state }) {
|
||||
const { windowId } = global.marktext.env
|
||||
const { showTabBar, showSideBar } = state
|
||||
ipcRenderer.send('mt::view-layout-changed', windowId, { showTabBar, showSideBar })
|
||||
},
|
||||
|
||||
CHANGE_SIDE_BAR_WIDTH ({ commit }, width) {
|
||||
commit('SET_SIDE_BAR_WIDTH', width)
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { ipcRenderer } from 'electron'
|
||||
import bus from '../bus'
|
||||
|
||||
// messages from main process, and do not change the state
|
||||
const state = {}
|
||||
|
||||
const getters = {}
|
||||
@ -21,15 +20,6 @@ const actions = {
|
||||
})
|
||||
},
|
||||
|
||||
LISTEN_FOR_VIEW ({ commit }) {
|
||||
ipcRenderer.on('mt::editor-change-view', (e, data) => {
|
||||
commit('SET_MODE', data)
|
||||
})
|
||||
ipcRenderer.on('mt::show-command-palette', () => {
|
||||
bus.$emit('show-command-palette')
|
||||
})
|
||||
},
|
||||
|
||||
LISTEN_FOR_SHOW_DIALOG ({ commit }) {
|
||||
ipcRenderer.on('mt::about-dialog', e => {
|
||||
bus.$emit('aboutDialog')
|
||||
|
@ -117,7 +117,7 @@ const mutations = {
|
||||
}
|
||||
|
||||
const actions = {
|
||||
ASK_FOR_USER_PREFERENCE ({ commit, state, rootState }) {
|
||||
ASK_FOR_USER_PREFERENCE ({ commit }) {
|
||||
ipcRenderer.send('mt::ask-for-user-preference')
|
||||
ipcRenderer.send('mt::ask-for-user-data')
|
||||
|
||||
@ -143,15 +143,27 @@ const actions = {
|
||||
ipcRenderer.send('mt::select-default-directory-to-open')
|
||||
},
|
||||
|
||||
LISTEN_FOR_VIEW ({ commit, dispatch }) {
|
||||
ipcRenderer.on('mt::show-command-palette', () => {
|
||||
bus.$emit('show-command-palette')
|
||||
})
|
||||
ipcRenderer.on('mt::toggle-view-mode-entry', (event, entryName) => {
|
||||
commit('TOGGLE_VIEW_MODE', entryName)
|
||||
dispatch('DISPATCH_EDITOR_VIEW_STATE', { [entryName]: state[entryName] })
|
||||
})
|
||||
},
|
||||
|
||||
// Toggle a view option and notify main process to toggle menu item.
|
||||
LISTEN_TOGGLE_VIEW ({ commit, state }) {
|
||||
LISTEN_TOGGLE_VIEW ({ commit, dispatch, state }) {
|
||||
bus.$on('view:toggle-view-entry', entryName => {
|
||||
commit('TOGGLE_VIEW_MODE', entryName)
|
||||
const item = {}
|
||||
item[entryName] = state[entryName]
|
||||
const { windowId } = global.marktext.env
|
||||
ipcRenderer.send('mt::view-layout-changed', windowId, item)
|
||||
dispatch('DISPATCH_EDITOR_VIEW_STATE', { [entryName]: state[entryName] })
|
||||
})
|
||||
},
|
||||
|
||||
DISPATCH_EDITOR_VIEW_STATE (_, viewState) {
|
||||
const { windowId } = global.marktext.env
|
||||
ipcRenderer.send('mt::view-layout-changed', windowId, viewState)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ const actions = {
|
||||
showSideBar: true,
|
||||
showTabBar: true
|
||||
})
|
||||
dispatch('SET_LAYOUT_MENU_ITEM')
|
||||
dispatch('DISPATCH_LAYOUT_MENU_ITEMS')
|
||||
})
|
||||
},
|
||||
LISTEN_FOR_UPDATE_PROJECT ({ commit, state, dispatch }) {
|
||||
|
Loading…
Reference in New Issue
Block a user