diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/index.js | 8 | ||||
-rw-r--r-- | src/lib/DBus.js | 49 | ||||
-rw-r--r-- | src/lib/Tray.js | 43 |
3 files changed, 92 insertions, 8 deletions
diff --git a/src/index.js b/src/index.js index 484191f2e..9dfbb4d8f 100644 --- a/src/index.js +++ b/src/index.js | |||
@@ -35,6 +35,7 @@ import { | |||
35 | import { mainIpcHandler as basicAuthHandler } from './features/basicAuth'; | 35 | import { mainIpcHandler as basicAuthHandler } from './features/basicAuth'; |
36 | import ipcApi from './electron/ipc-api'; | 36 | import ipcApi from './electron/ipc-api'; |
37 | import Tray from './lib/Tray'; | 37 | import Tray from './lib/Tray'; |
38 | import DBus from './lib/DBus'; | ||
38 | import Settings from './electron/Settings'; | 39 | import Settings from './electron/Settings'; |
39 | import handleDeepLink from './electron/deepLinking'; | 40 | import handleDeepLink from './electron/deepLinking'; |
40 | import { isPositionValid } from './electron/windowUtils'; | 41 | import { isPositionValid } from './electron/windowUtils'; |
@@ -213,6 +214,9 @@ const createWindow = () => { | |||
213 | // Initialize System Tray | 214 | // Initialize System Tray |
214 | const trayIcon = new Tray(); | 215 | const trayIcon = new Tray(); |
215 | 216 | ||
217 | // Initialize DBus interface | ||
218 | const dbus = new DBus(trayIcon); | ||
219 | |||
216 | // Initialize ipcApi | 220 | // Initialize ipcApi |
217 | ipcApi({ | 221 | ipcApi({ |
218 | mainWindow, | 222 | mainWindow, |
@@ -223,6 +227,9 @@ const createWindow = () => { | |||
223 | trayIcon, | 227 | trayIcon, |
224 | }); | 228 | }); |
225 | 229 | ||
230 | // Connect to the DBus after ipcApi took care of the System Tray | ||
231 | dbus.start(); | ||
232 | |||
226 | // Manage Window State | 233 | // Manage Window State |
227 | mainWindowState.manage(mainWindow); | 234 | mainWindowState.manage(mainWindow); |
228 | 235 | ||
@@ -265,6 +272,7 @@ const createWindow = () => { | |||
265 | mainWindow.hide(); | 272 | mainWindow.hide(); |
266 | } | 273 | } |
267 | } else { | 274 | } else { |
275 | dbus.stop(); | ||
268 | app.quit(); | 276 | app.quit(); |
269 | } | 277 | } |
270 | }); | 278 | }); |
diff --git a/src/lib/DBus.js b/src/lib/DBus.js new file mode 100644 index 000000000..957912efa --- /dev/null +++ b/src/lib/DBus.js | |||
@@ -0,0 +1,49 @@ | |||
1 | import { | ||
2 | sessionBus, | ||
3 | } from 'dbus-next'; | ||
4 | import { | ||
5 | isLinux, | ||
6 | } from '../environment'; | ||
7 | |||
8 | export default class DBus { | ||
9 | bus = null; | ||
10 | |||
11 | constructor(trayIcon) { | ||
12 | this.trayIcon = trayIcon; | ||
13 | } | ||
14 | |||
15 | start() { | ||
16 | if (!isLinux || this.bus) return; | ||
17 | |||
18 | try { | ||
19 | this.bus = sessionBus(); | ||
20 | } catch { | ||
21 | // Error connecting to the bus. | ||
22 | return; | ||
23 | } | ||
24 | |||
25 | // HACK Hook onto the MessageBus to track StatusNotifierWatchers | ||
26 | this.bus._addMatch("type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',path='/org/freedesktop/DBus',member='NameOwnerChanged'"); | ||
27 | const mangled = JSON.stringify({ | ||
28 | path: '/org/freedesktop/DBus', | ||
29 | interface: 'org.freedesktop.DBus', | ||
30 | member: 'NameOwnerChanged', | ||
31 | }); | ||
32 | this.bus._signals.on(mangled, (msg) => { | ||
33 | const [name, oldOwner, newOwner] = msg.body; | ||
34 | if (name === 'org.kde.StatusNotifierWatcher' && oldOwner !== newOwner && newOwner !== '') { | ||
35 | // Leave ample time for the StatusNotifierWatcher to be initialized | ||
36 | setTimeout(() => { | ||
37 | this.trayIcon.recreateIfVisible(); | ||
38 | }, 400); | ||
39 | } | ||
40 | }); | ||
41 | } | ||
42 | |||
43 | stop() { | ||
44 | if (!this.bus) return; | ||
45 | |||
46 | this.bus.disconnect(); | ||
47 | this.bus = null; | ||
48 | } | ||
49 | } | ||
diff --git a/src/lib/Tray.js b/src/lib/Tray.js index 0afb6289b..c6d9db004 100644 --- a/src/lib/Tray.js +++ b/src/lib/Tray.js | |||
@@ -22,6 +22,8 @@ export default class TrayIcon { | |||
22 | 22 | ||
23 | trayMenu = null; | 23 | trayMenu = null; |
24 | 24 | ||
25 | visible = false; | ||
26 | |||
25 | trayMenuTemplate = [ | 27 | trayMenuTemplate = [ |
26 | { | 28 | { |
27 | label: 'Show Ferdi', | 29 | label: 'Show Ferdi', |
@@ -50,7 +52,19 @@ export default class TrayIcon { | |||
50 | }, | 52 | }, |
51 | ]; | 53 | ]; |
52 | 54 | ||
55 | constructor() { | ||
56 | ipcMain.on('initialAppSettings', (event, appSettings) => { | ||
57 | this._updateTrayMenu(appSettings); | ||
58 | }); | ||
59 | |||
60 | ipcMain.on('updateAppSettings', (event, appSettings) => { | ||
61 | this._updateTrayMenu(appSettings); | ||
62 | }); | ||
63 | } | ||
64 | |||
53 | _updateTrayMenu(appSettings) { | 65 | _updateTrayMenu(appSettings) { |
66 | if (!this.trayIcon) return; | ||
67 | |||
54 | if (appSettings.type === 'app') { | 68 | if (appSettings.type === 'app') { |
55 | const { isAppMuted } = appSettings.data; | 69 | const { isAppMuted } = appSettings.data; |
56 | this.trayMenuTemplate[1].label = isAppMuted ? 'Enable Notifications && Audio' : 'Disable Notifications && Audio'; | 70 | this.trayMenuTemplate[1].label = isAppMuted ? 'Enable Notifications && Audio' : 'Disable Notifications && Audio'; |
@@ -62,6 +76,11 @@ export default class TrayIcon { | |||
62 | } | 76 | } |
63 | 77 | ||
64 | show() { | 78 | show() { |
79 | this.visible = true; | ||
80 | this._show(); | ||
81 | } | ||
82 | |||
83 | _show() { | ||
65 | if (this.trayIcon) return; | 84 | if (this.trayIcon) return; |
66 | 85 | ||
67 | this.trayIcon = new Tray(this._getAsset('tray', INDICATOR_TRAY_PLAIN)); | 86 | this.trayIcon = new Tray(this._getAsset('tray', INDICATOR_TRAY_PLAIN)); |
@@ -73,14 +92,6 @@ export default class TrayIcon { | |||
73 | this.trayIcon.setContextMenu(this.trayMenu); | 92 | this.trayIcon.setContextMenu(this.trayMenu); |
74 | } | 93 | } |
75 | 94 | ||
76 | ipcMain.on('initialAppSettings', (event, appSettings) => { | ||
77 | this._updateTrayMenu(appSettings); | ||
78 | }); | ||
79 | |||
80 | ipcMain.on('updateAppSettings', (event, appSettings) => { | ||
81 | this._updateTrayMenu(appSettings); | ||
82 | }); | ||
83 | |||
84 | this.trayIcon.on('click', () => { | 95 | this.trayIcon.on('click', () => { |
85 | if (app.mainWindow.isMinimized()) { | 96 | if (app.mainWindow.isMinimized()) { |
86 | app.mainWindow.restore(); | 97 | app.mainWindow.restore(); |
@@ -106,6 +117,11 @@ export default class TrayIcon { | |||
106 | } | 117 | } |
107 | 118 | ||
108 | hide() { | 119 | hide() { |
120 | this.visible = false; | ||
121 | this._hide(); | ||
122 | } | ||
123 | |||
124 | _hide() { | ||
109 | if (!this.trayIcon) return; | 125 | if (!this.trayIcon) return; |
110 | 126 | ||
111 | this.trayIcon.destroy(); | 127 | this.trayIcon.destroy(); |
@@ -117,6 +133,17 @@ export default class TrayIcon { | |||
117 | } | 133 | } |
118 | } | 134 | } |
119 | 135 | ||
136 | recreateIfVisible() { | ||
137 | if (this.visible) { | ||
138 | this._hide(); | ||
139 | setTimeout(() => { | ||
140 | if (this.visible) { | ||
141 | this._show(); | ||
142 | } | ||
143 | }, 100); | ||
144 | } | ||
145 | } | ||
146 | |||
120 | setIndicator(indicator) { | 147 | setIndicator(indicator) { |
121 | this.indicator = indicator; | 148 | this.indicator = indicator; |
122 | this._refreshIcon(); | 149 | this._refreshIcon(); |