aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar haraldox <hnaumann+github@gmail.com>2018-02-23 12:12:54 +0100
committerLibravatar haraldox <hnaumann+github@gmail.com>2018-02-23 12:12:54 +0100
commitae1014ed7d8f2532c4ec33b530662665dc16b141 (patch)
tree73f936db1a3bb797da6e29db3f53ad8e2a0f2678 /src
parentMerge branch 'fix/copy-paste' into feature/titlebar (diff)
downloadferdium-app-ae1014ed7d8f2532c4ec33b530662665dc16b141.tar.gz
ferdium-app-ae1014ed7d8f2532c4ec33b530662665dc16b141.tar.zst
ferdium-app-ae1014ed7d8f2532c4ec33b530662665dc16b141.zip
complete titlebar for Windows & Linux
Diffstat (limited to 'src')
-rw-r--r--src/components/layout/AppLayout.js4
-rw-r--r--src/environment.js1
-rw-r--r--src/index.js4
-rw-r--r--src/lib/Menu.js318
4 files changed, 261 insertions, 66 deletions
diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js
index 6162840be..686476317 100644
--- a/src/components/layout/AppLayout.js
+++ b/src/components/layout/AppLayout.js
@@ -7,6 +7,8 @@ import { TitleBar } from 'electron-react-titlebar';
7import InfoBar from '../ui/InfoBar'; 7import InfoBar from '../ui/InfoBar';
8import globalMessages from '../../i18n/globalMessages'; 8import globalMessages from '../../i18n/globalMessages';
9 9
10import { isMac } from '../../environment';
11
10function createMarkup(HTMLString) { 12function createMarkup(HTMLString) {
11 return { __html: HTMLString }; 13 return { __html: HTMLString };
12} 14}
@@ -88,7 +90,7 @@ export default class AppLayout extends Component {
88 return ( 90 return (
89 <div> 91 <div>
90 <div className="app"> 92 <div className="app">
91 <TitleBar menu={window.franz.menu.template} icon={'assets/images/logo.svg'} /> 93 {!isMac && <TitleBar menu={window.franz.menu.template} icon={'assets/images/logo.svg'} />}
92 <div className="app__content"> 94 <div className="app__content">
93 {sidebar} 95 {sidebar}
94 <div className="app__service"> 96 <div className="app__service">
diff --git a/src/environment.js b/src/environment.js
index 4dca0807d..e1762129b 100644
--- a/src/environment.js
+++ b/src/environment.js
@@ -14,6 +14,7 @@ export const isWindows = platform === 'win32';
14export const isLinux = platform === 'linux'; 14export const isLinux = platform === 'linux';
15 15
16export const ctrlKey = isMac ? '⌘' : 'Ctrl'; 16export const ctrlKey = isMac ? '⌘' : 'Ctrl';
17export const cmdKey = isMac ? 'Cmd' : 'Ctrl';
17 18
18let api; 19let api;
19if (!isDevMode || (isDevMode && useLiveAPI)) { 20if (!isDevMode || (isDevMode && useLiveAPI)) {
diff --git a/src/index.js b/src/index.js
index e8818af96..2acb8e2cb 100644
--- a/src/index.js
+++ b/src/index.js
@@ -4,7 +4,7 @@ import path from 'path';
4 4
5import windowStateKeeper from 'electron-window-state'; 5import windowStateKeeper from 'electron-window-state';
6 6
7import { isDevMode, isWindows } from './environment'; 7import { isDevMode, isMac, isWindows } from './environment';
8import ipcApi from './electron/ipc-api'; 8import ipcApi from './electron/ipc-api';
9import Tray from './lib/Tray'; 9import Tray from './lib/Tray';
10import Settings from './electron/Settings'; 10import Settings from './electron/Settings';
@@ -72,7 +72,7 @@ const createWindow = () => {
72 height: mainWindowState.height, 72 height: mainWindowState.height,
73 minWidth: 600, 73 minWidth: 600,
74 minHeight: 500, 74 minHeight: 500,
75 titleBarStyle: process.env.OS_PLATFORM || process.platform === 'win32' ? '' : 'hidden', 75 titleBarStyle: isMac ? 'hidden' : '',
76 frame: false, 76 frame: false,
77 backgroundColor: '#3498db', 77 backgroundColor: '#3498db',
78 autoHideMenuBar: true, 78 autoHideMenuBar: true,
diff --git a/src/lib/Menu.js b/src/lib/Menu.js
index 2bdd36b2c..475352bba 100644
--- a/src/lib/Menu.js
+++ b/src/lib/Menu.js
@@ -1,10 +1,14 @@
1import { remote, shell } from 'electron'; 1import { remote, shell } from 'electron';
2import { autorun, computed, observable, toJS } from 'mobx'; 2import { autorun, computed, observable, toJS } from 'mobx';
3 3
4import { isMac } from '../environment'; 4import { isMac, ctrlKey, cmdKey } from '../environment';
5 5
6const { app, Menu, dialog } = remote; 6const { app, Menu, dialog } = remote;
7 7
8function getActiveWebview() {
9 return window.franz.stores.services.active.webview;
10}
11
8const template = [ 12const template = [
9 { 13 {
10 label: 'Edit', 14 label: 'Edit',
@@ -114,8 +118,161 @@ const template = [
114 }, 118 },
115]; 119];
116 120
121const titleBarTemplate = [
122 {
123 label: 'Edit',
124 submenu: [
125 {
126 label: 'Undo',
127 accelerator: `${ctrlKey}+Z`,
128 click() {
129 getActiveWebview().undo();
130 },
131 },
132 {
133 label: 'Redo',
134 accelerator: `${ctrlKey}+Y`,
135 click() {
136 getActiveWebview().redo();
137 },
138 },
139 {
140 type: 'separator',
141 },
142 {
143 label: 'Cut',
144 accelerator: `${ctrlKey}+X`,
145 click() {
146 getActiveWebview().cut();
147 },
148 },
149 {
150 label: 'Copy',
151 accelerator: `${ctrlKey}+C`,
152 click() {
153 getActiveWebview().copy();
154 },
155 },
156 {
157 label: 'Paste',
158 accelerator: `${ctrlKey}+V`,
159 click() {
160 getActiveWebview().paste();
161 },
162 },
163 {
164 label: 'Paste and Match Style',
165 accelerator: `${ctrlKey}+Shift+V`,
166 click() {
167 getActiveWebview().pasteAndMatchStyle();
168 },
169 },
170 {
171 label: 'Delete',
172 click() {
173 getActiveWebview().delete();
174 },
175 },
176 {
177 label: 'Select All',
178 accelerator: `${ctrlKey}+A`,
179 click() {
180 getActiveWebview().selectAll();
181 },
182 },
183 ],
184 },
185 {
186 label: 'View',
187 submenu: [
188 {
189 type: 'separator',
190 },
191 {
192 label: 'Reset Zoom',
193 accelerator: `${ctrlKey}+0`,
194 click() {
195 getActiveWebview().setZoomLevel(0);
196 },
197 },
198 {
199 label: 'Zoom in',
200 accelerator: `${ctrlKey}+=`,
201 click() {
202 getActiveWebview().getZoomLevel((zoomLevel) => {
203 getActiveWebview().setZoomLevel(zoomLevel === 5 ? zoomLevel : zoomLevel + 1);
204 });
205 },
206 },
207 {
208 label: 'Zoom out',
209 accelerator: `${ctrlKey}+-`,
210 click() {
211 getActiveWebview().getZoomLevel((zoomLevel) => {
212 getActiveWebview().setZoomLevel(zoomLevel === -5 ? zoomLevel : zoomLevel - 1);
213 });
214 },
215 },
216 ],
217 },
218 {
219 label: 'Services',
220 submenu: [],
221 },
222 {
223 label: 'Window',
224 submenu: [
225 {
226 label: 'Minimize',
227 accelerator: 'Alt+M',
228 click(menuItem, browserWindow) {
229 browserWindow.minimize();
230 },
231 },
232 {
233 label: 'Close',
234 accelerator: 'Alt+W',
235 click(menuItem, browserWindow) {
236 browserWindow.close();
237 },
238 },
239 ],
240 },
241 {
242 label: '?',
243 submenu: [
244 {
245 label: 'Learn More',
246 click() { shell.openExternal('http://meetfranz.com'); },
247 },
248 {
249 label: 'Changelog',
250 click() { shell.openExternal('https://github.com/meetfranz/franz/blob/master/CHANGELOG.md'); },
251 },
252 {
253 type: 'separator',
254 },
255 {
256 label: 'Support',
257 click() { shell.openExternal('http://meetfranz.com/support'); },
258 },
259 {
260 type: 'separator',
261 },
262 {
263 label: 'Terms of Service',
264 click() { shell.openExternal('https://meetfranz.com/terms'); },
265 },
266 {
267 label: 'Privacy Statement',
268 click() { shell.openExternal('https://meetfranz.com/privacy'); },
269 },
270 ],
271 },
272];
273
117export default class FranzMenu { 274export default class FranzMenu {
118 @observable tpl = template; 275 @observable tpl = isMac ? template : titleBarTemplate;
119 @observable currentTemplate = null; 276 @observable currentTemplate = null;
120 277
121 constructor(stores, actions) { 278 constructor(stores, actions) {
@@ -133,10 +290,16 @@ export default class FranzMenu {
133 const tpl = toJS(this.tpl); 290 const tpl = toJS(this.tpl);
134 291
135 tpl[1].submenu.push({ 292 tpl[1].submenu.push({
136 role: 'toggledevtools', 293 type: 'separator',
294 }, {
295 label: 'Toggle Developer Tools',
296 accelerator: `${cmdKey}+Alt+I`,
297 click: (menuItem, browserWindow) => {
298 browserWindow.webContents.toggleDevTools();
299 },
137 }, { 300 }, {
138 label: 'Toggle Service Developer Tools', 301 label: 'Open Service Developer Tools',
139 accelerator: 'CmdOrCtrl+Shift+Alt+i', 302 accelerator: `${cmdKey}+Shift+Alt+I`,
140 click: () => { 303 click: () => {
141 this.actions.service.openDevToolsForActiveService(); 304 this.actions.service.openDevToolsForActiveService();
142 }, 305 },
@@ -145,7 +308,7 @@ export default class FranzMenu {
145 tpl[1].submenu.unshift({ 308 tpl[1].submenu.unshift({
146 label: 'Reload Service', 309 label: 'Reload Service',
147 id: 'reloadService', 310 id: 'reloadService',
148 accelerator: 'CmdOrCtrl+R', 311 accelerator: `${cmdKey}+R`,
149 click: () => { 312 click: () => {
150 if (this.stores.user.isLoggedIn 313 if (this.stores.user.isLoggedIn
151 && this.stores.services.enabled.length > 0) { 314 && this.stores.services.enabled.length > 0) {
@@ -156,56 +319,69 @@ export default class FranzMenu {
156 }, 319 },
157 }, { 320 }, {
158 label: 'Reload Franz', 321 label: 'Reload Franz',
159 accelerator: 'CmdOrCtrl+Shift+R', 322 accelerator: `${cmdKey}+Shift+R`,
160 click: () => { 323 click: () => {
161 window.location.reload(); 324 window.location.reload();
162 }, 325 },
163 }); 326 });
164 327
165 if (isMac) { 328 tpl.unshift({
166 tpl.unshift({ 329 label: isMac ? app.getName() : 'File',
167 label: app.getName(), 330 submenu: [
168 submenu: [ 331 {
169 { 332 role: 'about',
170 role: 'about', 333 },
171 }, 334 {
172 { 335 type: 'separator',
173 type: 'separator', 336 },
174 }, 337 {
175 { 338 label: 'Settings',
176 label: 'Settings', 339 accelerator: 'CmdOrCtrl+,',
177 accelerator: 'CmdOrCtrl+,', 340 click: () => {
178 click: () => { 341 this.actions.ui.openSettings({ path: 'app' });
179 this.actions.ui.openSettings({ path: 'app' });
180 },
181 },
182 {
183 type: 'separator',
184 },
185 {
186 role: 'services',
187 submenu: [],
188 },
189 {
190 type: 'separator',
191 },
192 {
193 role: 'hide',
194 },
195 {
196 role: 'hideothers',
197 },
198 {
199 role: 'unhide',
200 },
201 {
202 type: 'separator',
203 },
204 {
205 role: 'quit',
206 }, 342 },
207 ], 343 },
208 }); 344 {
345 type: 'separator',
346 },
347 {
348 role: 'services',
349 submenu: [],
350 },
351 {
352 type: 'separator',
353 },
354 {
355 role: 'hide',
356 },
357 {
358 role: 'hideothers',
359 },
360 {
361 role: 'unhide',
362 },
363 {
364 type: 'separator',
365 },
366 {
367 role: 'quit',
368 },
369 ],
370 });
371
372 const about = {
373 label: 'About Franz',
374 click: () => {
375 dialog.showMessageBox({
376 type: 'info',
377 title: 'Franz',
378 message: 'Franz',
379 detail: `Version: ${remote.app.getVersion()}\nRelease: ${process.versions.electron} / ${process.platform} / ${process.arch}`,
380 });
381 },
382 };
383
384 if (isMac) {
209 // Edit menu. 385 // Edit menu.
210 tpl[1].submenu.push( 386 tpl[1].submenu.push(
211 { 387 {
@@ -223,25 +399,41 @@ export default class FranzMenu {
223 ], 399 ],
224 }, 400 },
225 ); 401 );
402
403 tpl[4].submenu.unshift(about, {
404 type: 'separator',
405 });
226 } else { 406 } else {
227 tpl[4].submenu.unshift({ 407 tpl[0].submenu = [
228 role: 'about', 408 {
229 click: () => { 409 label: 'Preferences...',
230 dialog.showMessageBox({ 410 accelerator: 'Ctrl+P',
231 type: 'info', 411 click: () => {
232 title: 'Franz', 412 this.actions.ui.openSettings({ path: 'app' });
233 message: 'Franz', 413 },
234 detail: `Version: ${remote.app.getVersion()}\nRelease: ${process.versions.electron} / ${process.platform} / ${process.arch}`,
235 });
236 }, 414 },
237 }); 415 {
416 type: 'separator',
417 },
418 {
419 label: 'Quit',
420 accelerator: 'Alt+F4',
421 click: () => {
422 app.quit();
423 },
424 },
425 ];
426
427 tpl[5].submenu.push({
428 type: 'separator',
429 }, about);
238 } 430 }
239 431
240 const serviceTpl = this.serviceTpl; 432 const serviceTpl = this.serviceTpl;
241 433
242 serviceTpl.unshift({ 434 serviceTpl.unshift({
243 label: 'Add new Service', 435 label: 'Add new Service',
244 accelerator: 'CmdOrCtrl+N', 436 accelerator: `${cmdKey}+N`,
245 click: () => { 437 click: () => {
246 this.actions.ui.openSettings({ path: 'recipes' }); 438 this.actions.ui.openSettings({ path: 'recipes' });
247 }, 439 },
@@ -250,7 +442,7 @@ export default class FranzMenu {
250 }); 442 });
251 443
252 if (serviceTpl.length > 0) { 444 if (serviceTpl.length > 0) {
253 tpl[isMac ? 3 : 2].submenu = toJS(this.serviceTpl); 445 tpl[3].submenu = toJS(this.serviceTpl);
254 } 446 }
255 447
256 this.currentTemplate = tpl; 448 this.currentTemplate = tpl;
@@ -264,7 +456,7 @@ export default class FranzMenu {
264 if (this.stores.user.isLoggedIn) { 456 if (this.stores.user.isLoggedIn) {
265 return services.map((service, i) => ({ 457 return services.map((service, i) => ({
266 label: this._getServiceName(service), 458 label: this._getServiceName(service),
267 accelerator: i <= 9 ? `CmdOrCtrl+${i + 1}` : null, 459 accelerator: i <= 9 ? `${cmdKey}+${i + 1}` : null,
268 type: 'radio', 460 type: 'radio',
269 checked: service.isActive, 461 checked: service.isActive,
270 click: () => { 462 click: () => {