diff options
Diffstat (limited to 'src/lib/Menu.js')
-rw-r--r-- | src/lib/Menu.js | 598 |
1 files changed, 510 insertions, 88 deletions
diff --git a/src/lib/Menu.js b/src/lib/Menu.js index 703060dc1..76b0f28d5 100644 --- a/src/lib/Menu.js +++ b/src/lib/Menu.js | |||
@@ -1,113 +1,477 @@ | |||
1 | import { remote, shell } from 'electron'; | 1 | import { remote, shell } from 'electron'; |
2 | import { autorun, computed, observable, toJS } from 'mobx'; | 2 | import { observable, autorun, computed } from 'mobx'; |
3 | import { defineMessages } from 'react-intl'; | ||
3 | 4 | ||
4 | import { isMac } from '../environment'; | 5 | import { isMac, ctrlKey, cmdKey } from '../environment'; |
5 | 6 | ||
6 | const { app, Menu, dialog } = remote; | 7 | const { app, Menu, dialog } = remote; |
7 | 8 | ||
8 | const template = [ | 9 | const menuItems = defineMessages({ |
10 | edit: { | ||
11 | id: 'menu.edit', | ||
12 | defaultMessage: '!!!Edit', | ||
13 | }, | ||
14 | undo: { | ||
15 | id: 'menu.edit.undo', | ||
16 | defaultMessage: '!!!Undo', | ||
17 | }, | ||
18 | redo: { | ||
19 | id: 'menu.edit.redo', | ||
20 | defaultMessage: '!!!Redo', | ||
21 | }, | ||
22 | cut: { | ||
23 | id: 'menu.edit.cut', | ||
24 | defaultMessage: '!!!Cut', | ||
25 | }, | ||
26 | copy: { | ||
27 | id: 'menu.edit.copy', | ||
28 | defaultMessage: '!!!Copy', | ||
29 | }, | ||
30 | paste: { | ||
31 | id: 'menu.edit.paste', | ||
32 | defaultMessage: '!!!Paste', | ||
33 | }, | ||
34 | pasteAndMatchStyle: { | ||
35 | id: 'menu.edit.pasteAndMatchStyle', | ||
36 | defaultMessage: '!!!Paste And Match Style', | ||
37 | }, | ||
38 | delete: { | ||
39 | id: 'menu.edit.delete', | ||
40 | defaultMessage: '!!!Delete', | ||
41 | }, | ||
42 | selectAll: { | ||
43 | id: 'menu.edit.selectAll', | ||
44 | defaultMessage: '!!!Select All', | ||
45 | }, | ||
46 | speech: { | ||
47 | id: 'menu.edit.speech', | ||
48 | defaultMessage: '!!!Speech', | ||
49 | }, | ||
50 | startSpeaking: { | ||
51 | id: 'menu.edit.startSpeaking', | ||
52 | defaultMessage: '!!!Start Speaking', | ||
53 | }, | ||
54 | stopSpeaking: { | ||
55 | id: 'menu.edit.stopSpeaking', | ||
56 | defaultMessage: '!!!Stop Speaking', | ||
57 | }, | ||
58 | startDictation: { | ||
59 | id: 'menu.edit.startDictation', | ||
60 | defaultMessage: '!!!Start Dictation', | ||
61 | }, | ||
62 | emojiSymbols: { | ||
63 | id: 'menu.edit.emojiSymbols', | ||
64 | defaultMessage: '!!!Emoji & Symbols', | ||
65 | }, | ||
66 | resetZoom: { | ||
67 | id: 'menu.view.resetZoom', | ||
68 | defaultMessage: '!!!Actual Size', | ||
69 | }, | ||
70 | zoomIn: { | ||
71 | id: 'menu.view.zoomIn', | ||
72 | defaultMessage: '!!!Zoom In', | ||
73 | }, | ||
74 | zoomOut: { | ||
75 | id: 'menu.view.zoomOut', | ||
76 | defaultMessage: '!!!Zoom Out', | ||
77 | }, | ||
78 | enterFullScreen: { | ||
79 | id: 'menu.view.enterFullScreen', | ||
80 | defaultMessage: '!!!Enter Full Screen', | ||
81 | }, | ||
82 | exitFullScreen: { | ||
83 | id: 'menu.view.exitFullScreen', | ||
84 | defaultMessage: '!!!Exit Full Screen', | ||
85 | }, | ||
86 | toggleFullScreen: { | ||
87 | id: 'menu.view.toggleFullScreen', | ||
88 | defaultMessage: '!!!Toggle Full Screen', | ||
89 | }, | ||
90 | toggleDevTools: { | ||
91 | id: 'menu.view.toggleDevTools', | ||
92 | defaultMessage: '!!!Toggle Developer Tools', | ||
93 | }, | ||
94 | toggleServiceDevTools: { | ||
95 | id: 'menu.view.toggleServiceDevTools', | ||
96 | defaultMessage: '!!!Toggle Service Developer Tools', | ||
97 | }, | ||
98 | reloadService: { | ||
99 | id: 'menu.view.reloadService', | ||
100 | defaultMessage: '!!!Reload Service', | ||
101 | }, | ||
102 | reloadFranz: { | ||
103 | id: 'menu.view.reloadFranz', | ||
104 | defaultMessage: '!!!Reload Franz', | ||
105 | }, | ||
106 | minimize: { | ||
107 | id: 'menu.window.minimize', | ||
108 | defaultMessage: '!!!Minimize', | ||
109 | }, | ||
110 | close: { | ||
111 | id: 'menu.window.close', | ||
112 | defaultMessage: '!!!Close', | ||
113 | }, | ||
114 | learnMore: { | ||
115 | id: 'menu.help.learnMore', | ||
116 | defaultMessage: '!!!Learn More', | ||
117 | }, | ||
118 | changelog: { | ||
119 | id: 'menu.help.changelog', | ||
120 | defaultMessage: '!!!Changelog', | ||
121 | }, | ||
122 | support: { | ||
123 | id: 'menu.help.support', | ||
124 | defaultMessage: '!!!Support', | ||
125 | }, | ||
126 | tos: { | ||
127 | id: 'menu.help.tos', | ||
128 | defaultMessage: '!!!Terms of Service', | ||
129 | }, | ||
130 | privacy: { | ||
131 | id: 'menu.help.privacy', | ||
132 | defaultMessage: '!!!Privacy Statement', | ||
133 | }, | ||
134 | file: { | ||
135 | id: 'menu.file', | ||
136 | defaultMessage: '!!!File', | ||
137 | }, | ||
138 | view: { | ||
139 | id: 'menu.view', | ||
140 | defaultMessage: '!!!View', | ||
141 | }, | ||
142 | services: { | ||
143 | id: 'menu.services', | ||
144 | defaultMessage: '!!!Services', | ||
145 | }, | ||
146 | window: { | ||
147 | id: 'menu.window', | ||
148 | defaultMessage: '!!!Window', | ||
149 | }, | ||
150 | help: { | ||
151 | id: 'menu.help', | ||
152 | defaultMessage: '!!!Help', | ||
153 | }, | ||
154 | about: { | ||
155 | id: 'menu.app.about', | ||
156 | defaultMessage: '!!!About Franz', | ||
157 | }, | ||
158 | settings: { | ||
159 | id: 'menu.app.settings', | ||
160 | defaultMessage: '!!!Settings', | ||
161 | }, | ||
162 | hide: { | ||
163 | id: 'menu.app.hide', | ||
164 | defaultMessage: '!!!Hide', | ||
165 | }, | ||
166 | hideOthers: { | ||
167 | id: 'menu.app.hideOthers', | ||
168 | defaultMessage: '!!!Hide Others', | ||
169 | }, | ||
170 | unhide: { | ||
171 | id: 'menu.app.unhide', | ||
172 | defaultMessage: '!!!Unhide', | ||
173 | }, | ||
174 | quit: { | ||
175 | id: 'menu.app.quit', | ||
176 | defaultMessage: '!!!Quit', | ||
177 | }, | ||
178 | addNewService: { | ||
179 | id: 'menu.services.addNewService', | ||
180 | defaultMessage: '!!!Add New Service...', | ||
181 | }, | ||
182 | }); | ||
183 | |||
184 | function getActiveWebview() { | ||
185 | return window.franz.stores.services.active.webview; | ||
186 | } | ||
187 | |||
188 | const _templateFactory = intl => [ | ||
9 | { | 189 | { |
10 | label: 'Edit', | 190 | label: intl.formatMessage(menuItems.edit), |
11 | submenu: [ | 191 | submenu: [ |
12 | { | 192 | { |
193 | label: intl.formatMessage(menuItems.undo), | ||
13 | role: 'undo', | 194 | role: 'undo', |
14 | }, | 195 | }, |
15 | { | 196 | { |
197 | label: intl.formatMessage(menuItems.redo), | ||
16 | role: 'redo', | 198 | role: 'redo', |
17 | }, | 199 | }, |
18 | { | 200 | { |
19 | type: 'separator', | 201 | type: 'separator', |
20 | }, | 202 | }, |
21 | { | 203 | { |
22 | role: 'cut', | 204 | label: intl.formatMessage(menuItems.cut), |
205 | accelerator: 'Cmd+X', | ||
206 | selector: 'cut:', | ||
23 | }, | 207 | }, |
24 | { | 208 | { |
25 | label: 'Copy', | 209 | label: intl.formatMessage(menuItems.copy), |
26 | accelerator: 'Cmd+C', | 210 | accelerator: 'Cmd+C', |
27 | selector: 'copy:', | 211 | selector: 'copy:', |
28 | }, | 212 | }, |
29 | { | 213 | { |
30 | label: 'Paste', | 214 | label: intl.formatMessage(menuItems.paste), |
31 | accelerator: 'Cmd+V', | 215 | accelerator: 'Cmd+V', |
32 | selector: 'paste:', | 216 | selector: 'paste:', |
33 | }, | 217 | }, |
34 | { | 218 | { |
35 | role: 'pasteandmatchstyle', | 219 | label: intl.formatMessage(menuItems.pasteAndMatchStyle), |
220 | accelerator: 'Cmd+Shift+V', | ||
221 | selector: 'pasteAndMatchStyle:', | ||
36 | }, | 222 | }, |
37 | { | 223 | { |
224 | label: intl.formatMessage(menuItems.delete), | ||
38 | role: 'delete', | 225 | role: 'delete', |
39 | }, | 226 | }, |
40 | { | 227 | { |
41 | role: 'selectall', | 228 | label: intl.formatMessage(menuItems.selectAll), |
229 | accelerator: 'Cmd+A', | ||
230 | selector: 'selectAll:', | ||
42 | }, | 231 | }, |
43 | ], | 232 | ], |
44 | }, | 233 | }, |
45 | { | 234 | { |
46 | label: 'View', | 235 | label: intl.formatMessage(menuItems.view), |
47 | submenu: [ | 236 | submenu: [ |
48 | { | 237 | { |
49 | type: 'separator', | 238 | type: 'separator', |
50 | }, | 239 | }, |
51 | { | 240 | { |
241 | label: intl.formatMessage(menuItems.resetZoom), | ||
52 | role: 'resetzoom', | 242 | role: 'resetzoom', |
53 | }, | 243 | }, |
54 | { | 244 | { |
245 | label: intl.formatMessage(menuItems.zoomIn), | ||
246 | // accelerator: 'Cmd+=', | ||
55 | role: 'zoomin', | 247 | role: 'zoomin', |
56 | accelerator: 'CommandOrControl+=', | ||
57 | }, | 248 | }, |
58 | { | 249 | { |
250 | label: intl.formatMessage(menuItems.zoomOut), | ||
59 | role: 'zoomout', | 251 | role: 'zoomout', |
60 | }, | 252 | }, |
61 | { | 253 | { |
62 | type: 'separator', | 254 | type: 'separator', |
63 | }, | 255 | }, |
64 | { | 256 | { |
257 | label: app.mainWindow.isFullScreen() // label doesn't work, gets overridden by Electron | ||
258 | ? intl.formatMessage(menuItems.exitFullScreen) | ||
259 | : intl.formatMessage(menuItems.enterFullScreen), | ||
65 | role: 'togglefullscreen', | 260 | role: 'togglefullscreen', |
66 | }, | 261 | }, |
67 | ], | 262 | ], |
68 | }, | 263 | }, |
69 | { | 264 | { |
70 | label: 'Services', | 265 | label: intl.formatMessage(menuItems.services), |
71 | submenu: [], | 266 | submenu: [], |
72 | }, | 267 | }, |
73 | { | 268 | { |
269 | label: intl.formatMessage(menuItems.window), | ||
74 | role: 'window', | 270 | role: 'window', |
75 | submenu: [ | 271 | submenu: [ |
76 | { | 272 | { |
273 | label: intl.formatMessage(menuItems.minimize), | ||
77 | role: 'minimize', | 274 | role: 'minimize', |
78 | }, | 275 | }, |
79 | { | 276 | { |
277 | label: intl.formatMessage(menuItems.close), | ||
80 | role: 'close', | 278 | role: 'close', |
81 | }, | 279 | }, |
82 | ], | 280 | ], |
83 | }, | 281 | }, |
84 | { | 282 | { |
283 | label: intl.formatMessage(menuItems.help), | ||
85 | role: 'help', | 284 | role: 'help', |
86 | submenu: [ | 285 | submenu: [ |
87 | { | 286 | { |
88 | label: 'Learn More', | 287 | label: intl.formatMessage(menuItems.learnMore), |
89 | click() { shell.openExternal('http://meetfranz.com'); }, | 288 | click() { shell.openExternal('https://meetfranz.com'); }, |
90 | }, | 289 | }, |
91 | { | 290 | { |
92 | label: 'Changelog', | 291 | label: intl.formatMessage(menuItems.changelog), |
93 | click() { shell.openExternal('https://github.com/meetfranz/franz/blob/master/CHANGELOG.md'); }, | 292 | click() { shell.openExternal('https://github.com/meetfranz/franz/blob/master/CHANGELOG.md'); }, |
94 | }, | 293 | }, |
95 | { | 294 | { |
96 | type: 'separator', | 295 | type: 'separator', |
97 | }, | 296 | }, |
98 | { | 297 | { |
99 | label: 'Support', | 298 | label: intl.formatMessage(menuItems.support), |
100 | click() { shell.openExternal('http://meetfranz.com/support'); }, | 299 | click() { shell.openExternal('https://meetfranz.com/support'); }, |
101 | }, | 300 | }, |
102 | { | 301 | { |
103 | type: 'separator', | 302 | type: 'separator', |
104 | }, | 303 | }, |
105 | { | 304 | { |
106 | label: 'Terms of Service', | 305 | label: intl.formatMessage(menuItems.tos), |
107 | click() { shell.openExternal('https://meetfranz.com/terms'); }, | 306 | click() { shell.openExternal('https://meetfranz.com/terms'); }, |
108 | }, | 307 | }, |
109 | { | 308 | { |
110 | label: 'Privacy Statement', | 309 | label: intl.formatMessage(menuItems.privacy), |
310 | click() { shell.openExternal('https://meetfranz.com/privacy'); }, | ||
311 | }, | ||
312 | ], | ||
313 | }, | ||
314 | ]; | ||
315 | |||
316 | const _titleBarTemplateFactory = intl => [ | ||
317 | { | ||
318 | label: intl.formatMessage(menuItems.edit), | ||
319 | submenu: [ | ||
320 | { | ||
321 | label: intl.formatMessage(menuItems.undo), | ||
322 | accelerator: `${ctrlKey}+Z`, | ||
323 | click() { | ||
324 | getActiveWebview().undo(); | ||
325 | }, | ||
326 | }, | ||
327 | { | ||
328 | label: intl.formatMessage(menuItems.redo), | ||
329 | accelerator: `${ctrlKey}+Y`, | ||
330 | click() { | ||
331 | getActiveWebview().redo(); | ||
332 | }, | ||
333 | }, | ||
334 | { | ||
335 | type: 'separator', | ||
336 | }, | ||
337 | { | ||
338 | label: intl.formatMessage(menuItems.cut), | ||
339 | accelerator: `${ctrlKey}+X`, | ||
340 | click() { | ||
341 | getActiveWebview().cut(); | ||
342 | }, | ||
343 | }, | ||
344 | { | ||
345 | label: intl.formatMessage(menuItems.copy), | ||
346 | accelerator: `${ctrlKey}+C`, | ||
347 | click() { | ||
348 | getActiveWebview().copy(); | ||
349 | }, | ||
350 | }, | ||
351 | { | ||
352 | label: intl.formatMessage(menuItems.paste), | ||
353 | accelerator: `${ctrlKey}+V`, | ||
354 | click() { | ||
355 | getActiveWebview().paste(); | ||
356 | }, | ||
357 | }, | ||
358 | { | ||
359 | label: intl.formatMessage(menuItems.pasteAndMatchStyle), | ||
360 | accelerator: `${ctrlKey}+Shift+V`, | ||
361 | click() { | ||
362 | getActiveWebview().pasteAndMatchStyle(); | ||
363 | }, | ||
364 | }, | ||
365 | { | ||
366 | label: intl.formatMessage(menuItems.delete), | ||
367 | click() { | ||
368 | getActiveWebview().delete(); | ||
369 | }, | ||
370 | }, | ||
371 | { | ||
372 | label: intl.formatMessage(menuItems.selectAll), | ||
373 | accelerator: `${ctrlKey}+A`, | ||
374 | click() { | ||
375 | getActiveWebview().selectAll(); | ||
376 | }, | ||
377 | }, | ||
378 | ], | ||
379 | }, | ||
380 | { | ||
381 | label: intl.formatMessage(menuItems.view), | ||
382 | submenu: [ | ||
383 | { | ||
384 | type: 'separator', | ||
385 | }, | ||
386 | { | ||
387 | label: intl.formatMessage(menuItems.resetZoom), | ||
388 | accelerator: `${ctrlKey}+0`, | ||
389 | click() { | ||
390 | getActiveWebview().setZoomLevel(0); | ||
391 | }, | ||
392 | }, | ||
393 | { | ||
394 | label: intl.formatMessage(menuItems.zoomIn), | ||
395 | accelerator: `${ctrlKey}+Plus`, | ||
396 | click() { | ||
397 | getActiveWebview().getZoomLevel((zoomLevel) => { | ||
398 | getActiveWebview().setZoomLevel(zoomLevel === 5 ? zoomLevel : zoomLevel + 1); | ||
399 | }); | ||
400 | }, | ||
401 | }, | ||
402 | { | ||
403 | label: intl.formatMessage(menuItems.zoomOut), | ||
404 | accelerator: `${ctrlKey}+-`, | ||
405 | click() { | ||
406 | getActiveWebview().getZoomLevel((zoomLevel) => { | ||
407 | getActiveWebview().setZoomLevel(zoomLevel === -5 ? zoomLevel : zoomLevel - 1); | ||
408 | }); | ||
409 | }, | ||
410 | }, | ||
411 | { | ||
412 | type: 'separator', | ||
413 | }, | ||
414 | { | ||
415 | label: app.mainWindow.isFullScreen() // label doesn't work, gets overridden by Electron | ||
416 | ? intl.formatMessage(menuItems.exitFullScreen) | ||
417 | : intl.formatMessage(menuItems.enterFullScreen), | ||
418 | accelerator: 'F11', | ||
419 | click(menuItem, browserWindow) { | ||
420 | browserWindow.setFullScreen(!browserWindow.isFullScreen()); | ||
421 | }, | ||
422 | }, | ||
423 | ], | ||
424 | }, | ||
425 | { | ||
426 | label: intl.formatMessage(menuItems.services), | ||
427 | submenu: [], | ||
428 | }, | ||
429 | { | ||
430 | label: intl.formatMessage(menuItems.window), | ||
431 | submenu: [ | ||
432 | { | ||
433 | label: intl.formatMessage(menuItems.minimize), | ||
434 | accelerator: 'Ctrl+M', | ||
435 | click(menuItem, browserWindow) { | ||
436 | browserWindow.minimize(); | ||
437 | }, | ||
438 | }, | ||
439 | { | ||
440 | label: intl.formatMessage(menuItems.close), | ||
441 | accelerator: 'Ctrl+W', | ||
442 | click(menuItem, browserWindow) { | ||
443 | browserWindow.close(); | ||
444 | }, | ||
445 | }, | ||
446 | ], | ||
447 | }, | ||
448 | { | ||
449 | label: '?', | ||
450 | submenu: [ | ||
451 | { | ||
452 | label: intl.formatMessage(menuItems.learnMore), | ||
453 | click() { shell.openExternal('https://meetfranz.com'); }, | ||
454 | }, | ||
455 | { | ||
456 | label: intl.formatMessage(menuItems.changelog), | ||
457 | click() { shell.openExternal('https://github.com/meetfranz/franz/blob/master/CHANGELOG.md'); }, | ||
458 | }, | ||
459 | { | ||
460 | type: 'separator', | ||
461 | }, | ||
462 | { | ||
463 | label: intl.formatMessage(menuItems.support), | ||
464 | click() { shell.openExternal('https://meetfranz.com/support'); }, | ||
465 | }, | ||
466 | { | ||
467 | type: 'separator', | ||
468 | }, | ||
469 | { | ||
470 | label: intl.formatMessage(menuItems.tos), | ||
471 | click() { shell.openExternal('https://meetfranz.com/terms'); }, | ||
472 | }, | ||
473 | { | ||
474 | label: intl.formatMessage(menuItems.privacy), | ||
111 | click() { shell.openExternal('https://meetfranz.com/privacy'); }, | 475 | click() { shell.openExternal('https://meetfranz.com/privacy'); }, |
112 | }, | 476 | }, |
113 | ], | 477 | ], |
@@ -115,7 +479,7 @@ const template = [ | |||
115 | ]; | 479 | ]; |
116 | 480 | ||
117 | export default class FranzMenu { | 481 | export default class FranzMenu { |
118 | @observable tpl = template; | 482 | @observable currentTemplate = []; |
119 | 483 | ||
120 | constructor(stores, actions) { | 484 | constructor(stores, actions) { |
121 | this.stores = stores; | 485 | this.stores = stores; |
@@ -124,23 +488,45 @@ export default class FranzMenu { | |||
124 | autorun(this._build.bind(this)); | 488 | autorun(this._build.bind(this)); |
125 | } | 489 | } |
126 | 490 | ||
491 | rebuild() { | ||
492 | this._build(); | ||
493 | } | ||
494 | |||
495 | get template() { | ||
496 | return this.currentTemplate.toJS(); | ||
497 | } | ||
498 | |||
127 | _build() { | 499 | _build() { |
128 | const tpl = toJS(this.tpl); | 500 | // console.log(window.franz); |
501 | const serviceTpl = Object.assign([], this.serviceTpl); // need to clone object so we don't modify computed (cached) object | ||
502 | |||
503 | if (window.franz === undefined) { | ||
504 | return; | ||
505 | } | ||
506 | |||
507 | const intl = window.franz.intl; | ||
508 | const tpl = isMac ? _templateFactory(intl) : _titleBarTemplateFactory(intl); | ||
129 | 509 | ||
130 | tpl[1].submenu.push({ | 510 | tpl[1].submenu.push({ |
131 | role: 'toggledevtools', | 511 | type: 'separator', |
132 | }, { | 512 | }, { |
133 | label: 'Toggle Service Developer Tools', | 513 | label: intl.formatMessage(menuItems.toggleDevTools), |
134 | accelerator: 'CmdOrCtrl+Shift+Alt+i', | 514 | accelerator: `${cmdKey}+Alt+I`, |
515 | click: (menuItem, browserWindow) => { | ||
516 | browserWindow.webContents.toggleDevTools(); | ||
517 | }, | ||
518 | }, { | ||
519 | label: intl.formatMessage(menuItems.toggleServiceDevTools), | ||
520 | accelerator: `${cmdKey}+Shift+Alt+I`, | ||
135 | click: () => { | 521 | click: () => { |
136 | this.actions.service.openDevToolsForActiveService(); | 522 | this.actions.service.openDevToolsForActiveService(); |
137 | }, | 523 | }, |
138 | }); | 524 | }); |
139 | 525 | ||
140 | tpl[1].submenu.unshift({ | 526 | tpl[1].submenu.unshift({ |
141 | label: 'Reload Service', | 527 | label: intl.formatMessage(menuItems.reloadService), |
142 | id: 'reloadService', | 528 | id: 'reloadService', // TODO: needed? |
143 | accelerator: 'CmdOrCtrl+R', | 529 | accelerator: `${cmdKey}+R`, |
144 | click: () => { | 530 | click: () => { |
145 | if (this.stores.user.isLoggedIn | 531 | if (this.stores.user.isLoggedIn |
146 | && this.stores.services.enabled.length > 0) { | 532 | && this.stores.services.enabled.length > 0) { |
@@ -150,93 +536,128 @@ export default class FranzMenu { | |||
150 | } | 536 | } |
151 | }, | 537 | }, |
152 | }, { | 538 | }, { |
153 | label: 'Reload Franz', | 539 | label: intl.formatMessage(menuItems.reloadFranz), |
154 | accelerator: 'CmdOrCtrl+Shift+R', | 540 | accelerator: `${cmdKey}+Shift+R`, |
155 | click: () => { | 541 | click: () => { |
156 | window.location.reload(); | 542 | window.location.reload(); |
157 | }, | 543 | }, |
158 | }); | 544 | }); |
159 | 545 | ||
160 | if (isMac) { | 546 | tpl.unshift({ |
161 | tpl.unshift({ | 547 | label: isMac ? app.getName() : intl.formatMessage(menuItems.file), |
162 | label: app.getName(), | 548 | submenu: [ |
163 | submenu: [ | 549 | { |
164 | { | 550 | label: intl.formatMessage(menuItems.about), |
165 | role: 'about', | 551 | role: 'about', |
166 | }, | 552 | }, |
167 | { | 553 | { |
168 | type: 'separator', | 554 | type: 'separator', |
169 | }, | 555 | }, |
170 | { | 556 | { |
171 | label: 'Settings', | 557 | label: intl.formatMessage(menuItems.settings), |
172 | accelerator: 'CmdOrCtrl+,', | 558 | accelerator: 'CmdOrCtrl+,', |
173 | click: () => { | 559 | click: () => { |
174 | this.actions.ui.openSettings({ path: 'app' }); | 560 | this.actions.ui.openSettings({ path: 'app' }); |
175 | }, | ||
176 | }, | ||
177 | { | ||
178 | type: 'separator', | ||
179 | }, | ||
180 | { | ||
181 | role: 'services', | ||
182 | submenu: [], | ||
183 | }, | ||
184 | { | ||
185 | type: 'separator', | ||
186 | }, | ||
187 | { | ||
188 | role: 'hide', | ||
189 | }, | ||
190 | { | ||
191 | role: 'hideothers', | ||
192 | }, | ||
193 | { | ||
194 | role: 'unhide', | ||
195 | }, | ||
196 | { | ||
197 | type: 'separator', | ||
198 | }, | 561 | }, |
199 | { | 562 | }, |
200 | role: 'quit', | 563 | { |
564 | type: 'separator', | ||
565 | }, | ||
566 | { | ||
567 | label: intl.formatMessage(menuItems.services), | ||
568 | role: 'services', | ||
569 | submenu: [], | ||
570 | }, | ||
571 | { | ||
572 | type: 'separator', | ||
573 | }, | ||
574 | { | ||
575 | label: intl.formatMessage(menuItems.hide), | ||
576 | role: 'hide', | ||
577 | }, | ||
578 | { | ||
579 | label: intl.formatMessage(menuItems.hideOthers), | ||
580 | role: 'hideothers', | ||
581 | }, | ||
582 | { | ||
583 | label: intl.formatMessage(menuItems.unhide), | ||
584 | role: 'unhide', | ||
585 | }, | ||
586 | { | ||
587 | type: 'separator', | ||
588 | }, | ||
589 | { | ||
590 | label: intl.formatMessage(menuItems.quit), | ||
591 | role: 'quit', | ||
592 | click: () => { | ||
593 | app.quit(); | ||
201 | }, | 594 | }, |
202 | ], | 595 | }, |
203 | }); | 596 | ], |
597 | }); | ||
598 | |||
599 | const about = { | ||
600 | label: intl.formatMessage(menuItems.about), | ||
601 | click: () => { | ||
602 | dialog.showMessageBox({ | ||
603 | type: 'info', | ||
604 | title: 'Franz', | ||
605 | message: 'Franz', | ||
606 | detail: `Version: ${remote.app.getVersion()}\nRelease: ${process.versions.electron} / ${process.platform} / ${process.arch}`, | ||
607 | }); | ||
608 | }, | ||
609 | }; | ||
610 | |||
611 | if (isMac) { | ||
204 | // Edit menu. | 612 | // Edit menu. |
205 | tpl[1].submenu.push( | 613 | tpl[1].submenu.push( |
206 | { | 614 | { |
207 | type: 'separator', | 615 | type: 'separator', |
208 | }, | 616 | }, |
209 | { | 617 | { |
210 | label: 'Speech', | 618 | label: intl.formatMessage(menuItems.speech), |
211 | submenu: [ | 619 | submenu: [ |
212 | { | 620 | { |
621 | label: intl.formatMessage(menuItems.startSpeaking), | ||
213 | role: 'startspeaking', | 622 | role: 'startspeaking', |
214 | }, | 623 | }, |
215 | { | 624 | { |
625 | label: intl.formatMessage(menuItems.stopSpeaking), | ||
216 | role: 'stopspeaking', | 626 | role: 'stopspeaking', |
217 | }, | 627 | }, |
218 | ], | 628 | ], |
219 | }, | 629 | }, |
220 | ); | 630 | ); |
631 | |||
632 | tpl[4].submenu.unshift(about, { | ||
633 | type: 'separator', | ||
634 | }); | ||
221 | } else { | 635 | } else { |
222 | tpl[4].submenu.unshift({ | 636 | tpl[0].submenu = [ |
223 | role: 'about', | 637 | { |
224 | click: () => { | 638 | label: intl.formatMessage(menuItems.settings), |
225 | dialog.showMessageBox({ | 639 | accelerator: 'Ctrl+P', |
226 | type: 'info', | 640 | click: () => { |
227 | title: 'Franz', | 641 | this.actions.ui.openSettings({ path: 'app' }); |
228 | message: 'Franz', | 642 | }, |
229 | detail: `Version: ${remote.app.getVersion()}\nRelease: ${process.versions.electron} / ${process.platform} / ${process.arch}`, | ||
230 | }); | ||
231 | }, | 643 | }, |
232 | }); | 644 | { |
233 | } | 645 | type: 'separator', |
646 | }, | ||
647 | { | ||
648 | label: intl.formatMessage(menuItems.quit), | ||
649 | role: 'quit', | ||
650 | }, | ||
651 | ]; | ||
234 | 652 | ||
235 | const serviceTpl = this.serviceTpl; | 653 | tpl[5].submenu.push({ |
654 | type: 'separator', | ||
655 | }, about); | ||
656 | } | ||
236 | 657 | ||
237 | serviceTpl.unshift({ | 658 | serviceTpl.unshift({ |
238 | label: 'Add new Service', | 659 | label: intl.formatMessage(menuItems.addNewService), |
239 | accelerator: 'CmdOrCtrl+N', | 660 | accelerator: `${cmdKey}+N`, |
240 | click: () => { | 661 | click: () => { |
241 | this.actions.ui.openSettings({ path: 'recipes' }); | 662 | this.actions.ui.openSettings({ path: 'recipes' }); |
242 | }, | 663 | }, |
@@ -245,9 +666,10 @@ export default class FranzMenu { | |||
245 | }); | 666 | }); |
246 | 667 | ||
247 | if (serviceTpl.length > 0) { | 668 | if (serviceTpl.length > 0) { |
248 | tpl[isMac ? 3 : 2].submenu = toJS(this.serviceTpl); | 669 | tpl[3].submenu = serviceTpl; |
249 | } | 670 | } |
250 | 671 | ||
672 | this.currentTemplate = tpl; | ||
251 | const menu = Menu.buildFromTemplate(tpl); | 673 | const menu = Menu.buildFromTemplate(tpl); |
252 | Menu.setApplicationMenu(menu); | 674 | Menu.setApplicationMenu(menu); |
253 | } | 675 | } |
@@ -258,7 +680,7 @@ export default class FranzMenu { | |||
258 | if (this.stores.user.isLoggedIn) { | 680 | if (this.stores.user.isLoggedIn) { |
259 | return services.map((service, i) => ({ | 681 | return services.map((service, i) => ({ |
260 | label: this._getServiceName(service), | 682 | label: this._getServiceName(service), |
261 | accelerator: i <= 9 ? `CmdOrCtrl+${i + 1}` : null, | 683 | accelerator: i <= 9 ? `${cmdKey}+${i + 1}` : null, |
262 | type: 'radio', | 684 | type: 'radio', |
263 | checked: service.isActive, | 685 | checked: service.isActive, |
264 | click: () => { | 686 | click: () => { |