diff options
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | docs/DBUS.md | 20 | ||||
-rw-r--r-- | docs/INTERNAL_SERVER.md (renamed from INTERNAL_SERVER.md) | 2 | ||||
-rw-r--r-- | docs/MIGRATION.md (renamed from MIGRATION.md) | 0 | ||||
-rw-r--r-- | docs/dbus/ferdium_bar.py | 102 | ||||
-rw-r--r-- | docs/dbus/org.ferdium.Ferdium.xml | 80 | ||||
-rw-r--r-- | docs/dbus/requirements.txt | 1 | ||||
-rwxr-xr-x | scripts/migration/migrate-unix.sh | 2 | ||||
-rw-r--r-- | scripts/migration/migrate-windows.ps1 | 2 | ||||
-rw-r--r-- | src/lib/DBus.ts | 69 | ||||
-rw-r--r-- | src/lib/dbus/Ferdium.ts | 88 | ||||
-rw-r--r-- | src/stores/ServicesStore.ts | 52 |
12 files changed, 393 insertions, 27 deletions
@@ -62,7 +62,7 @@ _Find answers to frequently asked questions on [ferdium.org/faq](https://ferdium | |||
62 | 62 | ||
63 | ## Migrating from Ferdi | 63 | ## Migrating from Ferdi |
64 | 64 | ||
65 | If you are a pre-existing user of Ferdi, and are thinking of switching to Ferdium, you might want to run [the following scripts](./scripts/migration) to migrate your existing Ferdi profile such that Ferdium can pick up the configurations. (.ps1 for PowerShell/Windows users and .sh for UNIX (Linux and MacOS users). For a more detailed explanation, please see [MIGRATION.md](MIGRATION.md) | 65 | If you are a pre-existing user of Ferdi, and are thinking of switching to Ferdium, you might want to run [the following scripts](./scripts/migration) to migrate your existing Ferdi profile such that Ferdium can pick up the configurations. (.ps1 for PowerShell/Windows users and .sh for UNIX (Linux and MacOS users). For a more detailed explanation, please see [MIGRATION.md](docs/MIGRATION.md) |
66 | 66 | ||
67 | ## Styling | 67 | ## Styling |
68 | 68 | ||
diff --git a/docs/DBUS.md b/docs/DBUS.md new file mode 100644 index 000000000..ffbd61f4b --- /dev/null +++ b/docs/DBUS.md | |||
@@ -0,0 +1,20 @@ | |||
1 | # D-Bus interface | ||
2 | |||
3 | Ferdium exposes an inter-process communication on Linux systems via [D-Bus](https://www.freedesktop.org/wiki/Software/dbus/). | ||
4 | This allows integrating Ferdium with your desktop environment by displaying the number of unread notifications in a status area and muting or unmuting notations. | ||
5 | |||
6 | ## Desktop integration | ||
7 | |||
8 | As an example integration, the [`docs/dbus`](dbus) folder contains a module for status bars written in Python. | ||
9 | To run the example, you'll need Python 3.11 and the [`dbus-next`](https://pypi.org/project/dbus-next/) PyPI package. | ||
10 | |||
11 | The integration uses the [`FerdiumClient`](dbus/ferdium_client.py) client library, which is an asynchronous wrapper over the D-Bus interface. | ||
12 | It illustrates multiple advanced concepts, such as asynchronous communication with Ferdium via `asyncio` and polling the session D-Bus to see if Ferdium is running. | ||
13 | |||
14 | The [`ferdium_bar.py`](dbus/ferdium_bar.py) implements a bar module to use with status bars such as waybar or polybar. See `ferdium_bar.py --help` and `ferdium_bar.py unread --help` for further indications on how to use it. | ||
15 | |||
16 | ## Low-level API | ||
17 | |||
18 | The low-level API exposed over D-Bus is documented in [`org.ferdium.Ferdium.xml](docs/org.ferdium.Ferdium.xml) with standard D-Bus introspection syntax. | ||
19 | |||
20 | Ferdium will take ownership of the bus name `org.ferdium.Ferdium` and expose and object implementing the `org.ferdium.Ferdium` interface at the object path `/org/ferdium`. | ||
diff --git a/INTERNAL_SERVER.md b/docs/INTERNAL_SERVER.md index 1a1284f7e..9e94f9bdf 100644 --- a/INTERNAL_SERVER.md +++ b/docs/INTERNAL_SERVER.md | |||
@@ -1,5 +1,5 @@ | |||
1 | <p align="center"> | 1 | <p align="center"> |
2 | <img src="./src/internal-server/public/images/logo.png" alt="" width="300"/> | 2 | <img src="../src/internal-server/public/images/logo.png" alt="" width="300"/> |
3 | </p> | 3 | </p> |
4 | 4 | ||
5 | # ferdium-internal-server | 5 | # ferdium-internal-server |
diff --git a/MIGRATION.md b/docs/MIGRATION.md index bb1ca315d..bb1ca315d 100644 --- a/MIGRATION.md +++ b/docs/MIGRATION.md | |||
diff --git a/docs/dbus/ferdium_bar.py b/docs/dbus/ferdium_bar.py new file mode 100644 index 000000000..6fd5d8c30 --- /dev/null +++ b/docs/dbus/ferdium_bar.py | |||
@@ -0,0 +1,102 @@ | |||
1 | import asyncio | ||
2 | import argparse | ||
3 | import html | ||
4 | |||
5 | from ferdium_dbus import Client | ||
6 | |||
7 | |||
8 | async def toggle_window(client, args): | ||
9 | """Toggle window visibility""" | ||
10 | |||
11 | await client.toggle_window() | ||
12 | |||
13 | |||
14 | async def toggle_mute(client, args): | ||
15 | """Toggle mute status""" | ||
16 | |||
17 | await client.toggle_mute() | ||
18 | |||
19 | |||
20 | async def unread(client, args): | ||
21 | """Get unread messages count""" | ||
22 | |||
23 | def callback(): | ||
24 | """Print unread count(s)""" | ||
25 | |||
26 | # For each service | ||
27 | counts = {} | ||
28 | for service in client.unread_services: | ||
29 | name, direct, indirect = service | ||
30 | safe_name = html.escape(name) | ||
31 | |||
32 | # If it's exactly the service we're looking for, just return the count | ||
33 | if safe_name == args.services: | ||
34 | count = direct | ||
35 | if not args.direct: | ||
36 | count += indirect | ||
37 | print(count) | ||
38 | return | ||
39 | |||
40 | # If the service in included in the services we're looking for | ||
41 | if args.services in ("total", "all") or safe_name in args.services: | ||
42 | counts[safe_name] = direct | ||
43 | if not args.direct: | ||
44 | counts[safe_name] += indirect | ||
45 | |||
46 | # Get total notifications | ||
47 | if args.services == "total": | ||
48 | print(sum(counts.values())) | ||
49 | return | ||
50 | |||
51 | # Finally, print each service notifications on a different line | ||
52 | print( | ||
53 | "\n".join( | ||
54 | f"{name}: {count}" | ||
55 | for name, count in counts.items() | ||
56 | ) | ||
57 | ) | ||
58 | |||
59 | # Do print counts and keep running if tail mode enabled | ||
60 | callback() | ||
61 | if args.tail: | ||
62 | client.on_change(callback) | ||
63 | await asyncio.get_running_loop().create_future() | ||
64 | |||
65 | |||
66 | async def main(): | ||
67 | """Main cli interface""" | ||
68 | |||
69 | # Define commands | ||
70 | commands = { | ||
71 | "unread": unread, | ||
72 | "toggle-mute": toggle_mute, | ||
73 | "toggle-window": toggle_window, | ||
74 | } | ||
75 | |||
76 | # Arguments parser | ||
77 | argparser = argparse.ArgumentParser(description="Script to interact with Ferdium on your bar") | ||
78 | subparsers = argparser.add_subparsers(dest="command", required=True) | ||
79 | # Unread command | ||
80 | argparser_unread = subparsers.add_parser("unread", help=unread.__doc__) | ||
81 | argparser_unread.add_argument("-s", "--services", default="total", help="Which services to get notifications from {total, all, <name>} (the name can be a comma-separated list)") | ||
82 | argparser_unread.add_argument("-d", "--direct", action="store_true", default=False, help="Get only direct (mentions or DM) messages") | ||
83 | argparser_unread.add_argument("-t", "--tail", action="store_true", default=False, help="Keep running and print on change") | ||
84 | # Toggle mute and toggle window commands | ||
85 | argparser_toggle_mute = subparsers.add_parser("toggle-mute", help=toggle_mute.__doc__) | ||
86 | argparser_toggle_window = subparsers.add_parser("toggle-window", help=toggle_window.__doc__) | ||
87 | # Get args | ||
88 | args = argparser.parse_args() | ||
89 | |||
90 | # Initialise ferdium client | ||
91 | client = Client() | ||
92 | await client.connect() | ||
93 | if not client.running: | ||
94 | print("not running") | ||
95 | return | ||
96 | |||
97 | # Execute command | ||
98 | await commands[args.command](client, args) | ||
99 | |||
100 | |||
101 | if __name__ == "__main__": | ||
102 | asyncio.run(main()) | ||
diff --git a/docs/dbus/org.ferdium.Ferdium.xml b/docs/dbus/org.ferdium.Ferdium.xml new file mode 100644 index 000000000..8c66a9e21 --- /dev/null +++ b/docs/dbus/org.ferdium.Ferdium.xml | |||
@@ -0,0 +1,80 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" | ||
3 | "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> | ||
4 | <node> | ||
5 | <!-- | ||
6 | org.ferdium.Ferdium: | ||
7 | @short_description: Control Ferdium from the desktop | ||
8 | |||
9 | Interface for accessing Ferdium notification state, allowing notification | ||
10 | counts to be displayed in the desktop (e.g., on a status bar) and updating | ||
11 | the muted state of notifications. | ||
12 | |||
13 | The #org.ferdium.UnreadDirectMessageCount, | ||
14 | #org.ferdium.UnreadIndirectMessageCount, and #org.ferdium.UnreadServices | ||
15 | are affected by notification muting and hiding settings of Ferdium. | ||
16 | In particular, they are not updated if #org.ferdium.Muted is #TRUE. | ||
17 | Moreover, services with muted notifications or hidden indirect message | ||
18 | counts will not appear in the respective counts. | ||
19 | This behavior is consistent with the behavior of the Ferdium tray icon. | ||
20 | --> | ||
21 | <interface name="org.ferdium.Ferdium"> | ||
22 | <!-- | ||
23 | ToggleMute: | ||
24 | |||
25 | Toggles the muted state of notifcations. | ||
26 | |||
27 | Use the #org.ferdium.Ferdium.Muted property to get or set the current | ||
28 | muted state. | ||
29 | --> | ||
30 | <method name="ToggleMute" /> | ||
31 | <!-- | ||
32 | ToggleWindow: | ||
33 | |||
34 | Brings the Ferdium window into the foreground if it is not currently | ||
35 | focused. Hides the Ferdium window if is is currently focused. | ||
36 | |||
37 | Calling this method is equivalent to clicking on the Ferdium tray icon. | ||
38 | --> | ||
39 | <method name="ToggleWindow" /> | ||
40 | <!-- | ||
41 | Muted: | ||
42 | |||
43 | Gets or sets the current muted state of notifications. | ||
44 | |||
45 | #TRUE if notifications are currently muted, #FALSE otherwise. | ||
46 | --> | ||
47 | <property name="Muted" type="b" access="readwrite" /> | ||
48 | <!-- | ||
49 | UnreadDirectMessageCount: | ||
50 | |||
51 | The number of unread direct messages. | ||
52 | --> | ||
53 | <property name="UnreadDirectMessageCount" type="u" access="read" /> | ||
54 | <!-- | ||
55 | UnreadIndirectMessageCount: | ||
56 | |||
57 | The number of unread indirect messages. | ||
58 | --> | ||
59 | <property name="UnreadIndirectMessageCount" type="u" access="read" /> | ||
60 | <!-- | ||
61 | UnreadServices: | ||
62 | |||
63 | The list of services with unread messages. | ||
64 | |||
65 | The value of this property is an array of structs corresponding to each | ||
66 | service with unread messages. | ||
67 | The elements of a struct are the following: | ||
68 | |||
69 | 1. The name of the service. | ||
70 | |||
71 | 2. The number of unread direct messages of the service. | ||
72 | |||
73 | 3. The number of unread indirect messages of the service. | ||
74 | |||
75 | Services with no unread direct or indirect messages (i.e., structs with | ||
76 | the second and third element set to 0) are omitted from the array. | ||
77 | --> | ||
78 | <property name="UnreadServices" type="a(suu)" access="read" /> | ||
79 | </interface> | ||
80 | </node> | ||
diff --git a/docs/dbus/requirements.txt b/docs/dbus/requirements.txt new file mode 100644 index 000000000..d08a849d9 --- /dev/null +++ b/docs/dbus/requirements.txt | |||
@@ -0,0 +1 @@ | |||
git+https://github.com/victorbnl/ferdium-dbus-py | |||
diff --git a/scripts/migration/migrate-unix.sh b/scripts/migration/migrate-unix.sh index 37f24a533..c51227f33 100755 --- a/scripts/migration/migrate-unix.sh +++ b/scripts/migration/migrate-unix.sh | |||
@@ -65,6 +65,6 @@ else | |||
65 | echo "WARNING: Your data was partially migrated!" | 65 | echo "WARNING: Your data was partially migrated!" |
66 | echo "It was detected that your account is using Ferdi servers to sync your data." | 66 | echo "It was detected that your account is using Ferdi servers to sync your data." |
67 | echo "Please, check this guide on how to export and import your data manually:" | 67 | echo "Please, check this guide on how to export and import your data manually:" |
68 | echo "https://github.com/ferdium/ferdi/blob/main/MIGRATION.md" | 68 | echo "https://github.com/ferdium/ferdi/blob/main/docs/MIGRATION.md" |
69 | echo "********************************************" | 69 | echo "********************************************" |
70 | fi | 70 | fi |
diff --git a/scripts/migration/migrate-windows.ps1 b/scripts/migration/migrate-windows.ps1 index a7e67b94a..0a793077c 100644 --- a/scripts/migration/migrate-windows.ps1 +++ b/scripts/migration/migrate-windows.ps1 | |||
@@ -39,7 +39,7 @@ if (-not (Test-Path -Path $FERDIUM_PATH/server.sqlite)) { | |||
39 | Write-Host "" | 39 | Write-Host "" |
40 | Write-Host "It was detected that your account is using Ferdi servers to sync your data." | 40 | Write-Host "It was detected that your account is using Ferdi servers to sync your data." |
41 | Write-Host "Please, check this guide on how to export and import your data manually:" | 41 | Write-Host "Please, check this guide on how to export and import your data manually:" |
42 | Write-Host "https://github.com/ferdium/ferdi/blob/main/MIGRATION.md" | 42 | Write-Host "https://github.com/ferdium/ferdi/blob/main/docs/MIGRATION.md" |
43 | Write-Host "" | 43 | Write-Host "" |
44 | Write-Host "********************************************" | 44 | Write-Host "********************************************" |
45 | 45 | ||
diff --git a/src/lib/DBus.ts b/src/lib/DBus.ts index bbff405c4..530e30c85 100644 --- a/src/lib/DBus.ts +++ b/src/lib/DBus.ts | |||
@@ -1,28 +1,92 @@ | |||
1 | import { ipcMain } from 'electron'; | ||
2 | import { comparer } from 'mobx'; | ||
3 | |||
1 | import { MessageBus, sessionBus } from 'dbus-next'; | 4 | import { MessageBus, sessionBus } from 'dbus-next'; |
2 | import { isLinux } from '../environment'; | 5 | import { isLinux } from '../environment'; |
3 | import TrayIcon from './Tray'; | 6 | import TrayIcon from './Tray'; |
7 | import Ferdium, { type UnreadServices } from './dbus/Ferdium'; | ||
4 | 8 | ||
5 | export default class DBus { | 9 | export default class DBus { |
6 | bus: MessageBus | null = null; | 10 | private bus: MessageBus | null = null; |
7 | 11 | ||
8 | trayIcon: TrayIcon; | 12 | trayIcon: TrayIcon; |
9 | 13 | ||
14 | private ferdium: Ferdium | null = null; | ||
15 | |||
16 | muted = false; | ||
17 | |||
18 | unreadDirectMessageCount = 0; | ||
19 | |||
20 | unreadIndirectMessageCount = 0; | ||
21 | |||
22 | unreadServices: UnreadServices = []; | ||
23 | |||
10 | constructor(trayIcon: TrayIcon) { | 24 | constructor(trayIcon: TrayIcon) { |
11 | this.trayIcon = trayIcon; | 25 | this.trayIcon = trayIcon; |
26 | ipcMain.on('initialAppSettings', (_, appSettings) => { | ||
27 | this.updateSettings(appSettings); | ||
28 | }); | ||
29 | ipcMain.on('updateAppSettings', (_, appSettings) => { | ||
30 | this.updateSettings(appSettings); | ||
31 | }); | ||
32 | ipcMain.on( | ||
33 | 'updateDBusUnread', | ||
34 | ( | ||
35 | _, | ||
36 | unreadDirectMessageCount, | ||
37 | unreadIndirectMessageCount, | ||
38 | unreadServices, | ||
39 | ) => { | ||
40 | this.setUnread( | ||
41 | unreadDirectMessageCount, | ||
42 | unreadIndirectMessageCount, | ||
43 | unreadServices, | ||
44 | ); | ||
45 | }, | ||
46 | ); | ||
47 | } | ||
48 | |||
49 | private updateSettings(appSettings): void { | ||
50 | const muted = !!appSettings.data.isAppMuted; | ||
51 | if (this.muted !== muted) { | ||
52 | this.muted = muted; | ||
53 | this.ferdium?.emitMutedChanged(); | ||
54 | } | ||
12 | } | 55 | } |
13 | 56 | ||
14 | start() { | 57 | private setUnread( |
58 | unreadDirectMessageCount: number, | ||
59 | unreadIndirectMessageCount: number, | ||
60 | unreadServices: UnreadServices, | ||
61 | ): void { | ||
62 | if ( | ||
63 | this.unreadDirectMessageCount !== unreadDirectMessageCount || | ||
64 | this.unreadIndirectMessageCount !== unreadIndirectMessageCount || | ||
65 | !comparer.structural(this.unreadServices, unreadServices) | ||
66 | ) { | ||
67 | this.unreadDirectMessageCount = unreadDirectMessageCount; | ||
68 | this.unreadIndirectMessageCount = unreadIndirectMessageCount; | ||
69 | this.unreadServices = unreadServices; | ||
70 | this.ferdium?.emitUnreadChanged(); | ||
71 | } | ||
72 | } | ||
73 | |||
74 | async start() { | ||
15 | if (!isLinux || this.bus) { | 75 | if (!isLinux || this.bus) { |
16 | return; | 76 | return; |
17 | } | 77 | } |
18 | 78 | ||
19 | try { | 79 | try { |
20 | this.bus = sessionBus(); | 80 | this.bus = sessionBus(); |
81 | await this.bus.requestName('org.ferdium.Ferdium', 0); | ||
21 | } catch { | 82 | } catch { |
22 | // Error connecting to the bus. | 83 | // Error connecting to the bus. |
23 | return; | 84 | return; |
24 | } | 85 | } |
25 | 86 | ||
87 | this.ferdium = new Ferdium(this); | ||
88 | this.bus.export('/org/ferdium', this.ferdium); | ||
89 | |||
26 | // HACK Hook onto the MessageBus to track StatusNotifierWatchers | 90 | // HACK Hook onto the MessageBus to track StatusNotifierWatchers |
27 | // @ts-expect-error Property '_addMatch' does not exist on type 'MessageBus'. | 91 | // @ts-expect-error Property '_addMatch' does not exist on type 'MessageBus'. |
28 | this.bus._addMatch( | 92 | this.bus._addMatch( |
@@ -56,5 +120,6 @@ export default class DBus { | |||
56 | 120 | ||
57 | this.bus.disconnect(); | 121 | this.bus.disconnect(); |
58 | this.bus = null; | 122 | this.bus = null; |
123 | this.ferdium = null; | ||
59 | } | 124 | } |
60 | } | 125 | } |
diff --git a/src/lib/dbus/Ferdium.ts b/src/lib/dbus/Ferdium.ts new file mode 100644 index 000000000..b2a9105f4 --- /dev/null +++ b/src/lib/dbus/Ferdium.ts | |||
@@ -0,0 +1,88 @@ | |||
1 | import * as dbus from 'dbus-next'; | ||
2 | |||
3 | import type DBus from '../DBus'; | ||
4 | |||
5 | export type UnreadServices = [string, number, number][]; | ||
6 | |||
7 | export default class Ferdium extends dbus.interface.Interface { | ||
8 | constructor(private readonly dbus: DBus) { | ||
9 | super('org.ferdium.Ferdium'); | ||
10 | } | ||
11 | |||
12 | emitMutedChanged(): void { | ||
13 | Ferdium.emitPropertiesChanged(this, { Muted: this.dbus.muted }, []); | ||
14 | } | ||
15 | |||
16 | get Muted(): boolean { | ||
17 | return this.dbus.muted; | ||
18 | } | ||
19 | |||
20 | set Muted(muted: boolean) { | ||
21 | if (this.dbus.muted !== muted) { | ||
22 | this.ToggleMute(); | ||
23 | } | ||
24 | } | ||
25 | |||
26 | ToggleMute(): void { | ||
27 | this.dbus.trayIcon.mainWindow?.webContents.send('muteApp'); | ||
28 | } | ||
29 | |||
30 | ToggleWindow(): void { | ||
31 | this.dbus.trayIcon._toggleWindow(); | ||
32 | } | ||
33 | |||
34 | emitUnreadChanged(): void { | ||
35 | Ferdium.emitPropertiesChanged( | ||
36 | this, | ||
37 | { | ||
38 | UnreadDirectMessageCount: this.dbus.unreadDirectMessageCount, | ||
39 | UnreadIndirectMessageCount: this.dbus.unreadIndirectMessageCount, | ||
40 | UnreadServices: this.dbus.unreadServices, | ||
41 | }, | ||
42 | [], | ||
43 | ); | ||
44 | } | ||
45 | |||
46 | get UnreadDirectMessageCount(): number { | ||
47 | return this.dbus.unreadDirectMessageCount; | ||
48 | } | ||
49 | |||
50 | get UnreadIndirectMessageCount(): number { | ||
51 | return this.dbus.unreadIndirectMessageCount; | ||
52 | } | ||
53 | |||
54 | get UnreadServices(): UnreadServices { | ||
55 | return this.dbus.unreadServices; | ||
56 | } | ||
57 | } | ||
58 | |||
59 | Ferdium.configureMembers({ | ||
60 | methods: { | ||
61 | ToggleMute: { | ||
62 | inSignature: '', | ||
63 | outSignature: '', | ||
64 | }, | ||
65 | ToggleWindow: { | ||
66 | inSignature: '', | ||
67 | outSignature: '', | ||
68 | }, | ||
69 | }, | ||
70 | properties: { | ||
71 | Muted: { | ||
72 | signature: 'b', | ||
73 | access: dbus.interface.ACCESS_READWRITE, | ||
74 | }, | ||
75 | UnreadDirectMessageCount: { | ||
76 | signature: 'u', | ||
77 | access: dbus.interface.ACCESS_READ, | ||
78 | }, | ||
79 | UnreadIndirectMessageCount: { | ||
80 | signature: 'u', | ||
81 | access: dbus.interface.ACCESS_READ, | ||
82 | }, | ||
83 | UnreadServices: { | ||
84 | signature: 'a(suu)', | ||
85 | access: dbus.interface.ACCESS_READ, | ||
86 | }, | ||
87 | }, | ||
88 | }); | ||
diff --git a/src/stores/ServicesStore.ts b/src/stores/ServicesStore.ts index 0ab4dbc5b..829c64d76 100644 --- a/src/stores/ServicesStore.ts +++ b/src/stores/ServicesStore.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { shell } from 'electron'; | 1 | import { ipcRenderer, shell } from 'electron'; |
2 | import { action, reaction, computed, observable, makeObservable } from 'mobx'; | 2 | import { action, reaction, computed, observable, makeObservable } from 'mobx'; |
3 | import { debounce, remove } from 'lodash'; | 3 | import { debounce, remove } from 'lodash'; |
4 | import ms from 'ms'; | 4 | import ms from 'ms'; |
@@ -23,6 +23,7 @@ import { cleanseJSObject } from '../jsUtils'; | |||
23 | import { SPELLCHECKER_LOCALES } from '../i18n/languages'; | 23 | import { SPELLCHECKER_LOCALES } from '../i18n/languages'; |
24 | import { ferdiumVersion } from '../environment-remote'; | 24 | import { ferdiumVersion } from '../environment-remote'; |
25 | import TypedStore from './lib/TypedStore'; | 25 | import TypedStore from './lib/TypedStore'; |
26 | import type { UnreadServices } from '../lib/dbus/Ferdium'; | ||
26 | 27 | ||
27 | const debug = require('../preload-safe-debug')('Ferdium:ServiceStore'); | 28 | const debug = require('../preload-safe-debug')('Ferdium:ServiceStore'); |
28 | 29 | ||
@@ -1230,26 +1231,29 @@ export default class ServicesStore extends TypedStore { | |||
1230 | const { showMessageBadgeWhenMuted } = this.stores.settings.all.app; | 1231 | const { showMessageBadgeWhenMuted } = this.stores.settings.all.app; |
1231 | const { showMessageBadgesEvenWhenMuted } = this.stores.ui; | 1232 | const { showMessageBadgesEvenWhenMuted } = this.stores.ui; |
1232 | 1233 | ||
1233 | const unreadDirectMessageCount = this.allDisplayed | 1234 | const unreadServices: UnreadServices = []; |
1234 | .filter( | 1235 | let unreadDirectMessageCount = 0; |
1235 | s => | 1236 | let unreadIndirectMessageCount = 0; |
1236 | (showMessageBadgeWhenMuted || s.isNotificationEnabled) && | 1237 | |
1237 | showMessageBadgesEvenWhenMuted && | 1238 | if (showMessageBadgesEvenWhenMuted) { |
1238 | s.isBadgeEnabled, | 1239 | for (const s of this.allDisplayed) { |
1239 | ) | 1240 | if (s.isBadgeEnabled) { |
1240 | .map(s => s.unreadDirectMessageCount) | 1241 | const direct = |
1241 | .reduce((a, b) => a + b, 0); | 1242 | showMessageBadgeWhenMuted || s.isNotificationEnabled |
1242 | 1243 | ? s.unreadDirectMessageCount | |
1243 | const unreadIndirectMessageCount = this.allDisplayed | 1244 | : 0; |
1244 | .filter( | 1245 | const indirect = |
1245 | s => | 1246 | showMessageBadgeWhenMuted && s.isIndirectMessageBadgeEnabled |
1246 | showMessageBadgeWhenMuted && | 1247 | ? s.unreadIndirectMessageCount |
1247 | showMessageBadgesEvenWhenMuted && | 1248 | : 0; |
1248 | s.isBadgeEnabled && | 1249 | unreadDirectMessageCount += direct; |
1249 | s.isIndirectMessageBadgeEnabled, | 1250 | unreadIndirectMessageCount += indirect; |
1250 | ) | 1251 | if (direct > 0 || indirect > 0) { |
1251 | .map(s => s.unreadIndirectMessageCount) | 1252 | unreadServices.push([s.name, direct, indirect]); |
1252 | .reduce((a, b) => a + b, 0); | 1253 | } |
1254 | } | ||
1255 | } | ||
1256 | } | ||
1253 | 1257 | ||
1254 | // We can't just block this earlier, otherwise the mobx reaction won't be aware of the vars to watch in some cases | 1258 | // We can't just block this earlier, otherwise the mobx reaction won't be aware of the vars to watch in some cases |
1255 | if (showMessageBadgesEvenWhenMuted) { | 1259 | if (showMessageBadgesEvenWhenMuted) { |
@@ -1257,6 +1261,12 @@ export default class ServicesStore extends TypedStore { | |||
1257 | unreadDirectMessageCount, | 1261 | unreadDirectMessageCount, |
1258 | unreadIndirectMessageCount, | 1262 | unreadIndirectMessageCount, |
1259 | }); | 1263 | }); |
1264 | ipcRenderer.send( | ||
1265 | 'updateDBusUnread', | ||
1266 | unreadDirectMessageCount, | ||
1267 | unreadIndirectMessageCount, | ||
1268 | unreadServices, | ||
1269 | ); | ||
1260 | } | 1270 | } |
1261 | } | 1271 | } |
1262 | 1272 | ||