1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
import { ipcMain } from 'electron';
import { comparer } from 'mobx';
import { MessageBus, sessionBus } from 'dbus-next';
import { isLinux } from '../environment';
import TrayIcon from './Tray';
import Ferdium, { type UnreadServices } from './dbus/Ferdium';
export default class DBus {
private bus: MessageBus | null = null;
trayIcon: TrayIcon;
private ferdium: Ferdium | null = null;
muted = false;
unreadDirectMessageCount = 0;
unreadIndirectMessageCount = 0;
unreadServices: UnreadServices = [];
constructor(trayIcon: TrayIcon) {
this.trayIcon = trayIcon;
ipcMain.on('initialAppSettings', (_, appSettings) => {
this.updateSettings(appSettings);
});
ipcMain.on('updateAppSettings', (_, appSettings) => {
this.updateSettings(appSettings);
});
ipcMain.on(
'updateDBusUnread',
(
_,
unreadDirectMessageCount,
unreadIndirectMessageCount,
unreadServices,
) => {
this.setUnread(
unreadDirectMessageCount,
unreadIndirectMessageCount,
unreadServices,
);
},
);
}
private updateSettings(appSettings): void {
const muted = !!appSettings.data.isAppMuted;
if (this.muted !== muted) {
this.muted = muted;
this.ferdium?.emitMutedChanged();
}
}
private setUnread(
unreadDirectMessageCount: number,
unreadIndirectMessageCount: number,
unreadServices: UnreadServices,
): void {
if (
this.unreadDirectMessageCount !== unreadDirectMessageCount ||
this.unreadIndirectMessageCount !== unreadIndirectMessageCount ||
!comparer.structural(this.unreadServices, unreadServices)
) {
this.unreadDirectMessageCount = unreadDirectMessageCount;
this.unreadIndirectMessageCount = unreadIndirectMessageCount;
this.unreadServices = unreadServices;
this.ferdium?.emitUnreadChanged();
}
}
async start() {
if (!isLinux || this.bus) {
return;
}
try {
this.bus = sessionBus();
await this.bus.requestName('org.ferdium.Ferdium', 0);
} catch {
// Error connecting to the bus.
return;
}
this.ferdium = new Ferdium(this);
this.bus.export('/org/ferdium', this.ferdium);
// HACK Hook onto the MessageBus to track StatusNotifierWatchers
// @ts-expect-error Property '_addMatch' does not exist on type 'MessageBus'.
this.bus._addMatch(
"type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',path='/org/freedesktop/DBus',member='NameOwnerChanged'",
);
const mangled = JSON.stringify({
path: '/org/freedesktop/DBus',
interface: 'org.freedesktop.DBus',
member: 'NameOwnerChanged',
});
// @ts-expect-error Property '_signals' does not exist on type 'MessageBus'.
this.bus._signals.on(mangled, (msg: { body: [any, any, any] }) => {
const [name, oldOwner, newOwner] = msg.body;
if (
name === 'org.kde.StatusNotifierWatcher' &&
oldOwner !== newOwner &&
newOwner !== ''
) {
// Leave ample time for the StatusNotifierWatcher to be initialized
setTimeout(() => {
this.trayIcon.recreateIfVisible();
}, 400);
}
});
}
stop() {
if (!this.bus) {
return;
}
this.bus.disconnect();
this.bus = null;
this.ferdium = null;
}
}
|