diff options
author | Stefan Malzner <stefan@adlk.io> | 2017-10-13 12:29:40 +0200 |
---|---|---|
committer | Stefan Malzner <stefan@adlk.io> | 2017-10-13 12:29:40 +0200 |
commit | 58cda9cc7fb79ca9df6746de7f9662bc08dc156a (patch) | |
tree | 1211600c2a5d3b5f81c435c6896618111a611720 /src/electron | |
download | ferdium-app-58cda9cc7fb79ca9df6746de7f9662bc08dc156a.tar.gz ferdium-app-58cda9cc7fb79ca9df6746de7f9662bc08dc156a.tar.zst ferdium-app-58cda9cc7fb79ca9df6746de7f9662bc08dc156a.zip |
initial commit
Diffstat (limited to 'src/electron')
-rw-r--r-- | src/electron/Settings.js | 15 | ||||
-rw-r--r-- | src/electron/exception.js | 4 | ||||
-rw-r--r-- | src/electron/ipc-api/appIndicator.js | 80 | ||||
-rw-r--r-- | src/electron/ipc-api/autoUpdate.js | 54 | ||||
-rw-r--r-- | src/electron/ipc-api/index.js | 9 | ||||
-rw-r--r-- | src/electron/ipc-api/settings.js | 10 | ||||
-rw-r--r-- | src/electron/ipc-api/tray.js | 48 | ||||
-rw-r--r-- | src/electron/webview-ime-focus.js | 40 |
8 files changed, 260 insertions, 0 deletions
diff --git a/src/electron/Settings.js b/src/electron/Settings.js new file mode 100644 index 000000000..049a08296 --- /dev/null +++ b/src/electron/Settings.js | |||
@@ -0,0 +1,15 @@ | |||
1 | export default class Settings { | ||
2 | store = {}; | ||
3 | |||
4 | set(settings) { | ||
5 | this.store = Object.assign(this.store, settings); | ||
6 | } | ||
7 | |||
8 | all() { | ||
9 | return this.store; | ||
10 | } | ||
11 | |||
12 | get(key) { | ||
13 | return this.store[key]; | ||
14 | } | ||
15 | } | ||
diff --git a/src/electron/exception.js b/src/electron/exception.js new file mode 100644 index 000000000..0065e2604 --- /dev/null +++ b/src/electron/exception.js | |||
@@ -0,0 +1,4 @@ | |||
1 | process.on('uncaughtException', (err) => { | ||
2 | // handle the error safely | ||
3 | console.error(err); | ||
4 | }); | ||
diff --git a/src/electron/ipc-api/appIndicator.js b/src/electron/ipc-api/appIndicator.js new file mode 100644 index 000000000..576234d25 --- /dev/null +++ b/src/electron/ipc-api/appIndicator.js | |||
@@ -0,0 +1,80 @@ | |||
1 | import { app, ipcMain, Tray, Menu } from 'electron'; | ||
2 | import path from 'path'; | ||
3 | |||
4 | const INDICATOR_TRAY_PLAIN = 'tray'; | ||
5 | const INDICATOR_TRAY_UNREAD = 'tray-unread'; | ||
6 | const INDICATOR_TASKBAR = 'taskbar'; | ||
7 | |||
8 | const FILE_EXTENSION = process.platform === 'win32' ? 'ico' : 'png'; | ||
9 | let trayIcon; | ||
10 | |||
11 | function getAsset(type, asset) { | ||
12 | return path.join( | ||
13 | __dirname, '..', '..', 'assets', 'images', type, process.platform, `${asset}.${FILE_EXTENSION}`, | ||
14 | ); | ||
15 | } | ||
16 | |||
17 | export default (params) => { | ||
18 | trayIcon = new Tray(getAsset('tray', INDICATOR_TRAY_PLAIN)); | ||
19 | const trayMenuTemplate = [ | ||
20 | { | ||
21 | label: 'Show Franz', | ||
22 | click() { | ||
23 | params.mainWindow.show(); | ||
24 | }, | ||
25 | }, { | ||
26 | label: 'Quit Franz', | ||
27 | click() { | ||
28 | app.quit(); | ||
29 | }, | ||
30 | }, | ||
31 | ]; | ||
32 | |||
33 | const trayMenu = Menu.buildFromTemplate(trayMenuTemplate); | ||
34 | trayIcon.setContextMenu(trayMenu); | ||
35 | |||
36 | trayIcon.on('click', () => { | ||
37 | params.mainWindow.show(); | ||
38 | }); | ||
39 | |||
40 | ipcMain.on('updateAppIndicator', (event, args) => { | ||
41 | // Update badge | ||
42 | if (process.platform === 'darwin' | ||
43 | && typeof (args.indicator) === 'string') { | ||
44 | app.dock.setBadge(args.indicator); | ||
45 | } | ||
46 | |||
47 | if ((process.platform === 'darwin' | ||
48 | || process.platform === 'linux') | ||
49 | && typeof (args.indicator) === 'number' | ||
50 | ) { | ||
51 | app.setBadgeCount(args.indicator); | ||
52 | } | ||
53 | |||
54 | if (process.platform === 'win32') { | ||
55 | if (typeof args.indicator === 'number' | ||
56 | && args.indicator !== 0) { | ||
57 | params.mainWindow.setOverlayIcon( | ||
58 | getAsset('taskbar', `${INDICATOR_TASKBAR}-${(args.indicator >= 10 ? 10 : args.indicator)}`), | ||
59 | '', | ||
60 | ); | ||
61 | } else if (typeof args.indicator === 'string') { | ||
62 | params.mainWindow.setOverlayIcon( | ||
63 | getAsset('taskbar', `${INDICATOR_TASKBAR}-alert`), | ||
64 | '', | ||
65 | ); | ||
66 | } else { | ||
67 | params.mainWindow.setOverlayIcon(null, ''); | ||
68 | } | ||
69 | } | ||
70 | |||
71 | // Update system tray | ||
72 | trayIcon.setImage(getAsset('tray', args.indicator !== 0 ? INDICATOR_TRAY_UNREAD : INDICATOR_TRAY_PLAIN)); | ||
73 | |||
74 | if (process.platform === 'darwin') { | ||
75 | trayIcon.setPressedImage( | ||
76 | getAsset('tray', `${args.indicator !== 0 ? INDICATOR_TRAY_UNREAD : INDICATOR_TRAY_PLAIN}-active`), | ||
77 | ); | ||
78 | } | ||
79 | }); | ||
80 | }; | ||
diff --git a/src/electron/ipc-api/autoUpdate.js b/src/electron/ipc-api/autoUpdate.js new file mode 100644 index 000000000..7bc193e2d --- /dev/null +++ b/src/electron/ipc-api/autoUpdate.js | |||
@@ -0,0 +1,54 @@ | |||
1 | import { app, ipcMain } from 'electron'; | ||
2 | import { autoUpdater } from 'electron-updater'; | ||
3 | |||
4 | export default (params) => { | ||
5 | if (process.platform === 'darwin' || process.platform === 'win32') { | ||
6 | // autoUpdater.setFeedURL(updateUrl); | ||
7 | ipcMain.on('autoUpdate', (event, args) => { | ||
8 | try { | ||
9 | autoUpdater.allowPrerelease = Boolean(params.settings.get('beta')); | ||
10 | if (args.action === 'check') { | ||
11 | autoUpdater.checkForUpdates(); | ||
12 | } else if (args.action === 'install') { | ||
13 | console.log('install update'); | ||
14 | autoUpdater.quitAndInstall(); | ||
15 | // we need to send a quit event | ||
16 | setTimeout(() => { | ||
17 | app.quit(); | ||
18 | }, 20); | ||
19 | } | ||
20 | } catch (e) { | ||
21 | console.error(e); | ||
22 | event.sender.send('autoUpdate', { error: true }); | ||
23 | } | ||
24 | }); | ||
25 | |||
26 | autoUpdater.on('update-not-available', () => { | ||
27 | console.log('update-not-available'); | ||
28 | params.mainWindow.webContents.send('autoUpdate', { available: false }); | ||
29 | }); | ||
30 | |||
31 | autoUpdater.on('update-available', () => { | ||
32 | console.log('update-available'); | ||
33 | params.mainWindow.webContents.send('autoUpdate', { available: true }); | ||
34 | }); | ||
35 | |||
36 | autoUpdater.on('download-progress', (progressObj) => { | ||
37 | let logMessage = `Download speed: ${progressObj.bytesPerSecond}`; | ||
38 | logMessage = `${logMessage} - Downloaded ${progressObj.percent}%`; | ||
39 | logMessage = `${logMessage} (${progressObj.transferred}/${progressObj.total})`; | ||
40 | |||
41 | console.log(logMessage); | ||
42 | }); | ||
43 | |||
44 | autoUpdater.on('update-downloaded', () => { | ||
45 | console.log('update-downloaded'); | ||
46 | params.mainWindow.webContents.send('autoUpdate', { downloaded: true }); | ||
47 | }); | ||
48 | |||
49 | autoUpdater.on('error', () => { | ||
50 | console.log('update-error'); | ||
51 | params.mainWindow.webContents.send('autoUpdate', { error: true }); | ||
52 | }); | ||
53 | } | ||
54 | }; | ||
diff --git a/src/electron/ipc-api/index.js b/src/electron/ipc-api/index.js new file mode 100644 index 000000000..4ea6d1475 --- /dev/null +++ b/src/electron/ipc-api/index.js | |||
@@ -0,0 +1,9 @@ | |||
1 | import autoUpdate from './autoUpdate'; | ||
2 | import settings from './settings'; | ||
3 | import appIndicator from './appIndicator'; | ||
4 | |||
5 | export default (params) => { | ||
6 | settings(params); | ||
7 | autoUpdate(params); | ||
8 | appIndicator(params); | ||
9 | }; | ||
diff --git a/src/electron/ipc-api/settings.js b/src/electron/ipc-api/settings.js new file mode 100644 index 000000000..1d7eafa6c --- /dev/null +++ b/src/electron/ipc-api/settings.js | |||
@@ -0,0 +1,10 @@ | |||
1 | import { ipcMain } from 'electron'; | ||
2 | |||
3 | export default (params) => { | ||
4 | if (process.platform === 'darwin' || process.platform === 'win32') { | ||
5 | // eslint-disable-next-line | ||
6 | ipcMain.on('settings', (event, args) => { | ||
7 | params.settings.set(args); | ||
8 | }); | ||
9 | } | ||
10 | }; | ||
diff --git a/src/electron/ipc-api/tray.js b/src/electron/ipc-api/tray.js new file mode 100644 index 000000000..43364c0ed --- /dev/null +++ b/src/electron/ipc-api/tray.js | |||
@@ -0,0 +1,48 @@ | |||
1 | import { Tray, Menu, ipcMain } from 'electron'; | ||
2 | import path from 'path'; | ||
3 | |||
4 | const INDICATOR_PLAIN = 'franz-taskbar'; | ||
5 | const INDICATOR_UNREAD = 'franz-taskbar-unread'; | ||
6 | |||
7 | const FILE_EXTENSION = process.platform === 'win32' ? 'ico' : 'png'; | ||
8 | |||
9 | let trayIcon; | ||
10 | |||
11 | function getAsset(asset) { | ||
12 | return path.join( | ||
13 | __dirname, '..', '..', 'assets', 'images', 'tray', process.platform, `${asset}.${FILE_EXTENSION}`, | ||
14 | ); | ||
15 | } | ||
16 | |||
17 | export default (params) => { | ||
18 | // if (process.platform === 'win32' || process.platform === 'linux') { | ||
19 | trayIcon = new Tray(getAsset(INDICATOR_PLAIN)); | ||
20 | const trayMenuTemplate = [ | ||
21 | { | ||
22 | label: 'Show Franz', | ||
23 | click() { | ||
24 | params.mainWindow.show(); | ||
25 | }, | ||
26 | }, { | ||
27 | label: 'Quit Franz', | ||
28 | click() { | ||
29 | params.app.quit(); | ||
30 | }, | ||
31 | }, | ||
32 | ]; | ||
33 | |||
34 | const trayMenu = Menu.buildFromTemplate(trayMenuTemplate); | ||
35 | trayIcon.setContextMenu(trayMenu); | ||
36 | |||
37 | trayIcon.on('click', () => { | ||
38 | params.mainWindow.show(); | ||
39 | }); | ||
40 | |||
41 | ipcMain.on('updateTrayIconIndicator', (event, args) => { | ||
42 | trayIcon.setImage(getAsset(args.count !== 0 ? INDICATOR_UNREAD : INDICATOR_PLAIN)); | ||
43 | |||
44 | if (process.platform === 'darwin') { | ||
45 | trayIcon.setPressedImage(getAsset(`${args.count !== 0 ? INDICATOR_UNREAD : INDICATOR_PLAIN}-active`)); | ||
46 | } | ||
47 | }); | ||
48 | }; | ||
diff --git a/src/electron/webview-ime-focus.js b/src/electron/webview-ime-focus.js new file mode 100644 index 000000000..1213b518e --- /dev/null +++ b/src/electron/webview-ime-focus.js | |||
@@ -0,0 +1,40 @@ | |||
1 | const { releaseDocumentFocus } = require('./webview-ime-focus-helpers'); | ||
2 | |||
3 | function giveWebviewDocumentFocus(element) { | ||
4 | releaseDocumentFocus(); | ||
5 | |||
6 | window.requestAnimationFrame(() => { | ||
7 | element.send('claim-document-focus'); | ||
8 | }); | ||
9 | } | ||
10 | |||
11 | function elementIsUnfocusedWebview(element) { | ||
12 | return element.tagName === 'WEBVIEW' && !element.getWebContents().isFocused(); | ||
13 | } | ||
14 | |||
15 | function webviewDidAutofocus(element) { | ||
16 | function didKeyDown() { | ||
17 | element.removeEventListener('keydown', didKeyDown, true); | ||
18 | giveWebviewDocumentFocus(element); | ||
19 | } | ||
20 | |||
21 | element.addEventListener('keydown', didKeyDown, true); | ||
22 | } | ||
23 | |||
24 | function handleAutofocus(element) { | ||
25 | element.addEventListener('ipc-message', (event) => { | ||
26 | if (event.channel === 'autofocus') { | ||
27 | element.focus(); | ||
28 | webviewDidAutofocus(element); | ||
29 | } | ||
30 | }); | ||
31 | } | ||
32 | |||
33 | function didMouseDown(event) { | ||
34 | if (elementIsUnfocusedWebview(event.target)) { | ||
35 | giveWebviewDocumentFocus(event.target); | ||
36 | } | ||
37 | } | ||
38 | |||
39 | document.addEventListener('mousedown', didMouseDown, true); | ||
40 | document.querySelectorAll('webview').forEach(handleAutofocus); | ||