fix: get menu item by id (#270)

This commit is contained in:
Felix Häusler 2018-05-17 04:29:07 +02:00 committed by 冉四夕
parent 0b46fe2f2d
commit 8255ae73b8
8 changed files with 96 additions and 71 deletions

View File

@ -1,21 +1,21 @@
import { ipcMain } from 'electron' import { ipcMain } from 'electron'
import { getMenuItem } from '../utils' import { getMenuItemById } from '../utils'
const FORMAT_MAP = { const MENU_ID_FORMAT_MAP = {
'Strong': 'strong', 'strongMenuItem': 'strong',
'Emphasis': 'em', 'emphasisMenuItem': 'em',
'Inline Code': 'inline_code', 'inlineCodeMenuItem': 'inline_code',
'Strike': 'del', 'strikeMenuItem': 'del',
'Hyperlink': 'link', 'hyperlinkMenuItem': 'link',
'Image': 'image' 'imageMenuItem': 'image'
} }
const selectFormat = formats => { const selectFormat = formats => {
const formatMenuItem = getMenuItem('Format') const formatMenuItem = getMenuItemById('formatMenuItem')
formatMenuItem.submenu.items.forEach(item => (item.checked = false)) formatMenuItem.submenu.items.forEach(item => (item.checked = false))
formatMenuItem.submenu.items formatMenuItem.submenu.items
.forEach(item => { .forEach(item => {
if (formats.some(format => format.type === FORMAT_MAP[item.label])) { if (item.id && formats.some(format => format.type === MENU_ID_FORMAT_MAP[item.id])) {
item.checked = true item.checked = true
} }
}) })

View File

@ -1,52 +1,54 @@
import { ipcMain } from 'electron' import { ipcMain } from 'electron'
import { getMenuItem } from '../utils' import { getMenuItemById } from '../utils'
const DISABLE_LABELS = [ const DISABLE_LABELS = [
// paragraph menu items // paragraph menu items
'Heading 1', 'Heading 2', 'Heading 3', 'Heading 4', 'Heading 5', 'Heading 6', 'heading1MenuItem', 'heading2MenuItem', 'heading3MenuItem', 'heading4MenuItem',
'Upgrade Heading Level', 'Degrade Heading Level', 'heading5MenuItem', 'heading6MenuItem',
'Table', 'upgradeHeadingMenuItem', 'degradeHeadingMenuItem',
'tableMenuItem',
// formats menu items // formats menu items
'Hyperlink', 'Image' 'hyperlinkMenuItem', 'imageMenuItem'
] ]
const LABEL_MAP = { const MENU_ID_MAP = {
'Heading 1': 'h1', 'heading1MenuItem': 'h1',
'Heading 2': 'h2', 'heading2MenuItem': 'h2',
'Heading 3': 'h3', 'heading3MenuItem': 'h3',
'Heading 4': 'h4', 'heading4MenuItem': 'h4',
'Heading 5': 'h5', 'heading5MenuItem': 'h5',
'Heading 6': 'h6', 'heading6MenuItem': 'h6',
'Table': 'figure', 'tableMenuItem': 'figure',
'Code Fences': 'pre', 'codeFencesMenuItem': 'pre',
'Quote Block': 'blockquote', 'quoteBlockMenuItem': 'blockquote',
'Order List': 'ol', 'orderListMenuItem': 'ol',
'Bullet List': 'ul', 'bulletListMenuItem': 'ul',
'Task List': 'ul', 'taskListMenuItem': 'ul',
'Paragraph': 'p', 'paragraphMenuItem': 'p',
'Horizontal Line': 'hr', 'horizontalLineMenuItem': 'hr',
'YAML Front Matter': 'pre' 'frontMatterMenuItem': 'pre'
} }
const setParagraphMenuItemStatus = bool => { const setParagraphMenuItemStatus = bool => {
const paragraphMenuItem = getMenuItem('Paragraph') const paragraphMenuItem = getMenuItemById('paragraphMenuEntry')
paragraphMenuItem.submenu.items paragraphMenuItem.submenu.items
.forEach(item => (item.enabled = bool)) .forEach(item => (item.enabled = bool))
} }
const disableNoMultiple = (disableLabels) => { const disableNoMultiple = disableLabels => {
const paragraphMenuItem = getMenuItem('Paragraph') const paragraphMenuItem = getMenuItemById('paragraphMenuEntry')
paragraphMenuItem.submenu.items paragraphMenuItem.submenu.items
.filter(item => disableLabels.includes(item.label)) .filter(item => item.id && disableLabels.includes(item.id))
.forEach(item => (item.enabled = false)) .forEach(item => (item.enabled = false))
} }
const setCheckedMenuItem = affiliation => { const setCheckedMenuItem = affiliation => {
const paragraphMenuItem = getMenuItem('Paragraph') const paragraphMenuItem = getMenuItemById('paragraphMenuEntry')
paragraphMenuItem.submenu.items.forEach(item => (item.checked = false)) paragraphMenuItem.submenu.items.forEach(item => (item.checked = false))
paragraphMenuItem.submenu.items.forEach(item => { paragraphMenuItem.submenu.items.forEach(item => {
if (item.label === 'Loose List Item') { if (!item.id) {
return false
} else if (item.id === 'looseListItemMenuItem') {
let checked = false let checked = false
if (affiliation.length >= 1 && /ul|ol/.test(affiliation[0].type)) { if (affiliation.length >= 1 && /ul|ol/.test(affiliation[0].type)) {
checked = affiliation[0].children[0].isLooseListItem checked = affiliation[0].children[0].isLooseListItem
@ -57,18 +59,18 @@ const setCheckedMenuItem = affiliation => {
} else if (affiliation.some(b => { } else if (affiliation.some(b => {
if (b.type === 'ul') { if (b.type === 'ul') {
if (b.listType === 'bullet') { if (b.listType === 'bullet') {
return item.label === 'Bullet List' return item.id === 'bulletListMenuItem'
} else { } else {
return item.label === 'Task List' return item.id === 'taskListMenuItem'
} }
} else if (b.type === 'pre' && b.functionType) { } else if (b.type === 'pre' && b.functionType) {
if (b.functionType === 'frontmatter') { if (b.functionType === 'frontmatter') {
return item.label === 'YAML Front Matter' return item.id === 'frontMatterMenuItem'
} else if (b.functionType === 'code') { } else if (b.functionType === 'code') {
return item.label === 'Code Fences' return item.id === 'codeFencesMenuItem'
} }
} else { } else {
return b.type === LABEL_MAP[item.label] return b.type === MENU_ID_MAP[item.id]
} }
})) { })) {
item.checked = true item.checked = true
@ -82,7 +84,7 @@ export const paragraph = (win, type) => {
ipcMain.on('AGANI::selection-change', (e, { start, end, affiliation }) => { ipcMain.on('AGANI::selection-change', (e, { start, end, affiliation }) => {
// format menu // format menu
const formatMenuItem = getMenuItem('Format') const formatMenuItem = getMenuItemById('formatMenuItem')
formatMenuItem.submenu.items.forEach(item => (item.enabled = true)) formatMenuItem.submenu.items.forEach(item => (item.enabled = true))
// handle menu checked // handle menu checked
setCheckedMenuItem(affiliation) setCheckedMenuItem(affiliation)
@ -96,10 +98,10 @@ ipcMain.on('AGANI::selection-change', (e, { start, end, affiliation }) => {
setParagraphMenuItemStatus(false) setParagraphMenuItemStatus(false)
} else if (start.key !== end.key) { } else if (start.key !== end.key) {
formatMenuItem.submenu.items formatMenuItem.submenu.items
.filter(item => DISABLE_LABELS.includes(item.label)) .filter(item => item.id && DISABLE_LABELS.includes(item.id))
.forEach(item => (item.enabled = false)) .forEach(item => (item.enabled = false))
disableNoMultiple(DISABLE_LABELS) disableNoMultiple(DISABLE_LABELS)
} else if (!affiliation.slice(0, 3).some(p => /ul|ol/.test(p.type))) { } else if (!affiliation.slice(0, 3).some(p => /ul|ol/.test(p.type))) {
disableNoMultiple(['Loose List Item']) disableNoMultiple(['looseListItemMenuItem'])
} }
}) })

View File

@ -1,23 +1,19 @@
import { ipcMain, BrowserWindow } from 'electron' import { ipcMain, BrowserWindow } from 'electron'
import { getMenuItem } from '../utils' import { getMenuItemById } from '../utils'
const HASH = { const sourceCodeModeMenuItemId = 'sourceCodeModeMenuItem'
'Source Code Mode': 'sourceCode', const typewriterModeMenuItemId = 'typewriterModeMenuItem'
'Typewriter Mode': 'typewriter', const focusModeMenuItemId = 'focusModeMenuItem'
'Focus Mode': 'focus'
}
export const typeMode = (win, item, type) => { export const typeMode = (win, item, type) => {
const { checked } = item const { checked } = item
win.webContents.send('AGANI::view', { type, checked }) win.webContents.send('AGANI::view', { type, checked })
if (type === 'sourceCode') { if (type === 'sourceCode') {
const viewMenuItem = getMenuItem('View') const typewriterModeMenuItem = getMenuItemById(typewriterModeMenuItemId)
viewMenuItem.submenu.items.forEach(item => { const focusModeMenuItem = getMenuItemById(focusModeMenuItemId)
if (/typewriter|focus/.test(HASH[item.label])) { typewriterModeMenuItem.enabled = !checked
item.enabled = !checked focusModeMenuItem.enabled = !checked
}
})
} }
} }
@ -26,14 +22,14 @@ export const changeFont = win => {
} }
ipcMain.on('AGANI::ask-for-mode', e => { ipcMain.on('AGANI::ask-for-mode', e => {
// format menu const sourceCodeModeMenuItem = getMenuItemById(sourceCodeModeMenuItemId)
const viewMenuItem = getMenuItem('View') const typewriterModeMenuItem = getMenuItemById(typewriterModeMenuItemId)
const modes = {} const focusModeMenuItem = getMenuItemById(focusModeMenuItemId)
viewMenuItem.submenu.items.forEach(item => { const modes = {
if (HASH[item.label]) { sourceCode: sourceCodeModeMenuItem.checked,
modes[HASH[item.label]] = item.checked typewriter: typewriterModeMenuItem.checked,
} focus: focusModeMenuItem.checked
}) }
const win = BrowserWindow.fromWebContents(e.sender) const win = BrowserWindow.fromWebContents(e.sender)
win.webContents.send('AGANI::res-for-mode', modes) win.webContents.send('AGANI::res-for-mode', modes)
}) })

View File

@ -50,7 +50,7 @@ export default {
actions.edit(browserWindow, 'fineNext') actions.edit(browserWindow, 'fineNext')
} }
}, { }, {
label: 'FindPrev', label: 'Find Previous',
accelerator: 'Shift+CmdOrCtrl+U', accelerator: 'Shift+CmdOrCtrl+U',
click: (menuItem, browserWindow) => { click: (menuItem, browserWindow) => {
actions.edit(browserWindow, 'findPrev') actions.edit(browserWindow, 'findPrev')

View File

@ -1,8 +1,10 @@
import * as actions from '../actions/format' import * as actions from '../actions/format'
export default { export default {
id: 'formatMenuItem',
label: 'Format', label: 'Format',
submenu: [{ submenu: [{
id: 'strongMenuItem',
label: 'Strong', label: 'Strong',
type: 'checkbox', type: 'checkbox',
accelerator: 'Shift+CmdOrCtrl+B', accelerator: 'Shift+CmdOrCtrl+B',
@ -10,6 +12,7 @@ export default {
actions.format(browserWindow, 'strong') actions.format(browserWindow, 'strong')
} }
}, { }, {
id: 'emphasisMenuItem',
label: 'Emphasis', label: 'Emphasis',
type: 'checkbox', type: 'checkbox',
accelerator: 'CmdOrCtrl+E', accelerator: 'CmdOrCtrl+E',
@ -17,6 +20,7 @@ export default {
actions.format(browserWindow, 'em') actions.format(browserWindow, 'em')
} }
}, { }, {
id: 'inlineCodeMenuItem',
label: 'Inline Code', label: 'Inline Code',
type: 'checkbox', type: 'checkbox',
accelerator: 'CmdOrCtrl+`', accelerator: 'CmdOrCtrl+`',
@ -26,6 +30,7 @@ export default {
}, { }, {
type: 'separator' type: 'separator'
}, { }, {
id: 'strikeMenuItem',
label: 'Strike', label: 'Strike',
type: 'checkbox', type: 'checkbox',
accelerator: 'CmdOrCtrl+D', accelerator: 'CmdOrCtrl+D',
@ -33,6 +38,7 @@ export default {
actions.format(browserWindow, 'del') actions.format(browserWindow, 'del')
} }
}, { }, {
id: 'hyperlinkMenuItem',
label: 'Hyperlink', label: 'Hyperlink',
type: 'checkbox', type: 'checkbox',
accelerator: 'CmdOrCtrl+L', accelerator: 'CmdOrCtrl+L',
@ -40,6 +46,7 @@ export default {
actions.format(browserWindow, 'link') actions.format(browserWindow, 'link')
} }
}, { }, {
id: 'imageMenuItem',
label: 'Image', label: 'Image',
type: 'checkbox', type: 'checkbox',
accelerator: 'Shift+CmdOrCtrl+I', accelerator: 'Shift+CmdOrCtrl+I',

View File

@ -1,8 +1,10 @@
import * as actions from '../actions/paragraph' import * as actions from '../actions/paragraph'
export default { export default {
id: 'paragraphMenuEntry',
label: 'Paragraph', label: 'Paragraph',
submenu: [{ submenu: [{
id: 'heading1MenuItem',
label: 'Heading 1', label: 'Heading 1',
type: 'checkbox', type: 'checkbox',
accelerator: 'CmdOrCtrl+1', accelerator: 'CmdOrCtrl+1',
@ -10,6 +12,7 @@ export default {
actions.paragraph(browserWindow, 'heading 1') actions.paragraph(browserWindow, 'heading 1')
} }
}, { }, {
id: 'heading2MenuItem',
label: 'Heading 2', label: 'Heading 2',
type: 'checkbox', type: 'checkbox',
accelerator: 'CmdOrCtrl+2', accelerator: 'CmdOrCtrl+2',
@ -17,6 +20,7 @@ export default {
actions.paragraph(browserWindow, 'heading 2') actions.paragraph(browserWindow, 'heading 2')
} }
}, { }, {
id: 'heading3MenuItem',
label: 'Heading 3', label: 'Heading 3',
type: 'checkbox', type: 'checkbox',
accelerator: 'CmdOrCtrl+3', accelerator: 'CmdOrCtrl+3',
@ -24,6 +28,7 @@ export default {
actions.paragraph(browserWindow, 'heading 3') actions.paragraph(browserWindow, 'heading 3')
} }
}, { }, {
id: 'heading4MenuItem',
label: 'Heading 4', label: 'Heading 4',
type: 'checkbox', type: 'checkbox',
accelerator: 'CmdOrCtrl+4', accelerator: 'CmdOrCtrl+4',
@ -31,6 +36,7 @@ export default {
actions.paragraph(browserWindow, 'heading 4') actions.paragraph(browserWindow, 'heading 4')
} }
}, { }, {
id: 'heading5MenuItem',
label: 'Heading 5', label: 'Heading 5',
type: 'checkbox', type: 'checkbox',
accelerator: 'CmdOrCtrl+5', accelerator: 'CmdOrCtrl+5',
@ -38,6 +44,7 @@ export default {
actions.paragraph(browserWindow, 'heading 5') actions.paragraph(browserWindow, 'heading 5')
} }
}, { }, {
id: 'heading6MenuItem',
label: 'Heading 6', label: 'Heading 6',
type: 'checkbox', type: 'checkbox',
accelerator: 'CmdOrCtrl+6', accelerator: 'CmdOrCtrl+6',
@ -47,12 +54,14 @@ export default {
}, { }, {
type: 'separator' type: 'separator'
}, { }, {
id: 'upgradeHeadingMenuItem',
label: 'Upgrade Heading', label: 'Upgrade Heading',
accelerator: 'CmdOrCtrl+=', accelerator: 'CmdOrCtrl+=',
click (menuItem, browserWindow) { click (menuItem, browserWindow) {
actions.paragraph(browserWindow, 'upgrade heading') actions.paragraph(browserWindow, 'upgrade heading')
} }
}, { }, {
id: 'degradeHeadingMenuItem',
label: 'Degrade Heading', label: 'Degrade Heading',
accelerator: 'CmdOrCtrl+-', accelerator: 'CmdOrCtrl+-',
click (menuItem, browserWindow) { click (menuItem, browserWindow) {
@ -61,6 +70,7 @@ export default {
}, { }, {
type: 'separator' type: 'separator'
}, { }, {
id: 'tableMenuItem',
label: 'Table', label: 'Table',
type: 'checkbox', type: 'checkbox',
accelerator: 'CmdOrCtrl+T', accelerator: 'CmdOrCtrl+T',
@ -68,6 +78,7 @@ export default {
actions.paragraph(browserWindow, 'table') actions.paragraph(browserWindow, 'table')
} }
}, { }, {
id: 'codeFencesMenuItem',
label: 'Code Fences', label: 'Code Fences',
type: 'checkbox', type: 'checkbox',
accelerator: 'Alt+CmdOrCtrl+C', accelerator: 'Alt+CmdOrCtrl+C',
@ -75,6 +86,7 @@ export default {
actions.paragraph(browserWindow, 'pre') actions.paragraph(browserWindow, 'pre')
} }
}, { }, {
id: 'quoteBlockMenuItem',
label: 'Quote Block', label: 'Quote Block',
type: 'checkbox', type: 'checkbox',
accelerator: 'Alt+CmdOrCtrl+Q', accelerator: 'Alt+CmdOrCtrl+Q',
@ -84,6 +96,7 @@ export default {
}, { }, {
type: 'separator' type: 'separator'
}, { }, {
id: 'orderListMenuItem',
label: 'Order List', label: 'Order List',
type: 'checkbox', type: 'checkbox',
accelerator: 'Alt+CmdOrCtrl+O', accelerator: 'Alt+CmdOrCtrl+O',
@ -91,6 +104,7 @@ export default {
actions.paragraph(browserWindow, 'ol-order') actions.paragraph(browserWindow, 'ol-order')
} }
}, { }, {
id: 'bulletListMenuItem',
label: 'Bullet List', label: 'Bullet List',
type: 'checkbox', type: 'checkbox',
accelerator: 'Alt+CmdOrCtrl+U', accelerator: 'Alt+CmdOrCtrl+U',
@ -98,6 +112,7 @@ export default {
actions.paragraph(browserWindow, 'ul-bullet') actions.paragraph(browserWindow, 'ul-bullet')
} }
}, { }, {
id: 'taskListMenuItem',
label: 'Task List', label: 'Task List',
type: 'checkbox', type: 'checkbox',
accelerator: 'Alt+CmdOrCtrl+X', accelerator: 'Alt+CmdOrCtrl+X',
@ -107,6 +122,7 @@ export default {
}, { }, {
type: 'separator' type: 'separator'
}, { }, {
id: 'looseListItemMenuItem',
label: 'Loose List Item', label: 'Loose List Item',
type: 'checkbox', type: 'checkbox',
accelerator: 'Alt+CmdOrCtrl+L', accelerator: 'Alt+CmdOrCtrl+L',
@ -116,6 +132,7 @@ export default {
}, { }, {
type: 'separator' type: 'separator'
}, { }, {
id: 'paragraphMenuItem',
label: 'Paragraph', label: 'Paragraph',
type: 'checkbox', type: 'checkbox',
accelerator: 'CmdOrCtrl+0', accelerator: 'CmdOrCtrl+0',
@ -123,6 +140,7 @@ export default {
actions.paragraph(browserWindow, 'paragraph') actions.paragraph(browserWindow, 'paragraph')
} }
}, { }, {
id: 'horizontalLineMenuItem',
label: 'Horizontal Line', label: 'Horizontal Line',
type: 'checkbox', type: 'checkbox',
accelerator: 'Alt+CmdOrCtrl+-', accelerator: 'Alt+CmdOrCtrl+-',
@ -130,6 +148,7 @@ export default {
actions.paragraph(browserWindow, 'hr') actions.paragraph(browserWindow, 'hr')
} }
}, { }, {
id: 'frontMatterMenuItem',
label: 'YAML Front Matter', label: 'YAML Front Matter',
type: 'checkbox', type: 'checkbox',
accelerator: 'Alt+CmdOrCtrl+Y', accelerator: 'Alt+CmdOrCtrl+Y',

View File

@ -28,6 +28,7 @@ let viewMenu = {
}, { }, {
type: 'separator' type: 'separator'
}, { }, {
id: 'sourceCodeModeMenuItem',
label: 'Source Code Mode', label: 'Source Code Mode',
accelerator: 'CmdOrCtrl+U', accelerator: 'CmdOrCtrl+U',
type: 'checkbox', type: 'checkbox',
@ -36,6 +37,7 @@ let viewMenu = {
actions.typeMode(browserWindow, item, 'sourceCode') actions.typeMode(browserWindow, item, 'sourceCode')
} }
}, { }, {
id: 'typewriterModeMenuItem',
label: 'Typewriter Mode', label: 'Typewriter Mode',
accelerator: 'Shift+CmdOrCtrl+T', accelerator: 'Shift+CmdOrCtrl+T',
type: 'checkbox', type: 'checkbox',
@ -44,6 +46,7 @@ let viewMenu = {
actions.typeMode(browserWindow, item, 'typewriter') actions.typeMode(browserWindow, item, 'typewriter')
} }
}, { }, {
id: 'focusModeMenuItem',
label: 'Focus Mode', label: 'Focus Mode',
accelerator: 'Shift+CmdOrCtrl+F', accelerator: 'Shift+CmdOrCtrl+F',
type: 'checkbox', type: 'checkbox',

View File

@ -19,11 +19,9 @@ export const getPath = directory => {
return app.getPath(directory) return app.getPath(directory)
} }
export const getMenuItem = menuName => { export const getMenuItemById = menuId => {
// TODO(fxha): Please use menu id attribute to find menu entries. This will
// cause problems with internationalization later!
const menus = Menu.getApplicationMenu() const menus = Menu.getApplicationMenu()
return menus.items.find(menu => menu.label === menuName) return menus.getMenuItemById(menuId)
} }
export const log = data => { export const log = data => {