aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/Menu.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/Menu.js')
-rw-r--r--src/lib/Menu.js259
1 files changed, 259 insertions, 0 deletions
diff --git a/src/lib/Menu.js b/src/lib/Menu.js
new file mode 100644
index 000000000..9f23c4d70
--- /dev/null
+++ b/src/lib/Menu.js
@@ -0,0 +1,259 @@
1import { remote, shell } from 'electron';
2import { autorun, computed, observable, toJS } from 'mobx';
3
4import { isDevMode, isMac } from '../environment';
5
6const { app, Menu } = remote;
7
8const template = [
9 {
10 label: 'Edit',
11 submenu: [
12 {
13 role: 'undo',
14 },
15 {
16 role: 'redo',
17 },
18 {
19 type: 'separator',
20 },
21 {
22 role: 'cut',
23 },
24 {
25 role: 'copy',
26 },
27 {
28 role: 'paste',
29 },
30 {
31 role: 'pasteandmatchstyle',
32 },
33 {
34 role: 'delete',
35 },
36 {
37 role: 'selectall',
38 },
39 ],
40 },
41 {
42 label: 'View',
43 submenu: [
44 {
45 type: 'separator',
46 },
47 {
48 role: 'resetzoom',
49 },
50 {
51 role: 'zoomin',
52 },
53 {
54 role: 'zoomout',
55 },
56 {
57 type: 'separator',
58 },
59 {
60 role: 'togglefullscreen',
61 },
62 ],
63 },
64 {
65 label: 'Services',
66 submenu: [],
67 },
68 {
69 role: 'window',
70 submenu: [
71 {
72 role: 'minimize',
73 },
74 {
75 role: 'close',
76 },
77 ],
78 },
79 {
80 role: 'help',
81 submenu: [
82 {
83 label: 'Learn More',
84 click() { shell.openExternal('http://meetfranz.com'); },
85 },
86 ],
87 },
88];
89
90export default class FranzMenu {
91 @observable tpl = template;
92
93 constructor(stores, actions) {
94 this.stores = stores;
95 this.actions = actions;
96
97 autorun(this._build.bind(this));
98 }
99
100 _build() {
101 const tpl = toJS(this.tpl);
102
103 if (isDevMode) {
104 tpl[1].submenu.push({
105 role: 'toggledevtools',
106 }, {
107 label: 'Toggle Service Developer Tools',
108 accelerator: 'CmdOrCtrl+Shift+Alt+i',
109 click: () => {
110 this.actions.service.openDevToolsForActiveService();
111 },
112 });
113 }
114
115 tpl[1].submenu.unshift({
116 label: 'Reload Service',
117 id: 'reloadService',
118 accelerator: 'CmdOrCtrl+R',
119 click: () => {
120 if (this.stores.user.isLoggedIn
121 && this.stores.services.enabled.length > 0) {
122 this.actions.service.reloadActive();
123 } else {
124 window.location.reload();
125 }
126 },
127 }, {
128 label: 'Reload Franz',
129 accelerator: 'CmdOrCtrl+Shift+R',
130 click: () => {
131 window.location.reload();
132 },
133 });
134
135 if (isMac) {
136 tpl.unshift({
137 label: app.getName(),
138 submenu: [
139 {
140 role: 'about',
141 },
142 {
143 type: 'separator',
144 },
145 {
146 label: 'Settings',
147 accelerator: 'CmdOrCtrl+,',
148 click: () => {
149 this.actions.ui.openSettings({ path: '' });
150 },
151 },
152 {
153 type: 'separator',
154 },
155 {
156 role: 'services',
157 submenu: [],
158 },
159 {
160 type: 'separator',
161 },
162 {
163 role: 'hide',
164 },
165 {
166 role: 'hideothers',
167 },
168 {
169 role: 'unhide',
170 },
171 {
172 type: 'separator',
173 },
174 {
175 role: 'quit',
176 },
177 ],
178 });
179 // Edit menu.
180 tpl[1].submenu.push(
181 {
182 type: 'separator',
183 },
184 {
185 label: 'Speech',
186 submenu: [
187 {
188 role: 'startspeaking',
189 },
190 {
191 role: 'stopspeaking',
192 },
193 ],
194 },
195 );
196 // Window menu.
197 tpl[3].submenu = [
198 {
199 // label: 'Close',
200 accelerator: 'CmdOrCtrl+W',
201 role: 'close',
202 },
203 {
204 // label: 'Minimize',
205 accelerator: 'CmdOrCtrl+M',
206 role: 'minimize',
207 },
208 {
209 // label: 'Zoom',
210 role: 'zoom',
211 },
212 {
213 type: 'separator',
214 },
215 {
216 // label: 'Bring All to Front',
217 role: 'front',
218 },
219 ];
220 }
221
222 const serviceTpl = this.serviceTpl;
223
224 serviceTpl.unshift({
225 label: 'Add new Service',
226 accelerator: 'CmdOrCtrl+N',
227 click: () => {
228 this.actions.ui.openSettings({ path: 'recipes' });
229 },
230 }, {
231 type: 'separator',
232 });
233
234 if (serviceTpl.length > 0) {
235 tpl[isMac ? 3 : 2].submenu = toJS(this.serviceTpl);
236 }
237
238 const menu = Menu.buildFromTemplate(tpl);
239 Menu.setApplicationMenu(menu);
240 }
241
242 @computed get serviceTpl() {
243 const services = this.stores.services.enabled;
244
245 if (this.stores.user.isLoggedIn) {
246 return services.map((service, i) => ({
247 label: service.name,
248 accelerator: i <= 9 ? `CmdOrCtrl+${i + 1}` : null,
249 type: 'radio',
250 checked: service.isActive,
251 click: () => {
252 this.actions.service.setActive({ serviceId: service.id });
253 },
254 }));
255 }
256
257 return [];
258 }
259}