Notify of pokes and private messages on the desktop

While none of the client's windows has the focus, a poke or a private
message shows a desktop notification, which the desktop's notification
centre keeps. A private conversation keeps one notification, updated as
messages come; clicking it brings the window forward with that chat open,
and they all go once a window of the client is in front again.

On Linux they go to the freedesktop.org notification service, spoken to
over the session bus by a small D-Bus client of our own on Java's Unix
sockets, so no library or native code is involved; Plasma also takes a
reply typed into the notification. Elsewhere they are AWT tray messages,
which Windows and macOS put in their notification centres. The options
can turn them off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-26 15:20:51 +00:00
parent a6efc0b8da
commit 02ff63341e
14 changed files with 1019 additions and 5 deletions

View File

@@ -151,6 +151,8 @@ public final class Settings {
public double soundVolume = 1.0;
/** Extra folder to look for sound packs in, on top of the well-known locations. */
public String soundPackDir = "";
/** Whether pokes and private messages show a desktop notification while the window is in the background. */
public boolean desktopNotifications = true;
// ---- icons ----
/** File name of the active icon pack; empty uses the built-in icons. */
public String iconPack = "default_colored_2014.zip";
@@ -264,6 +266,7 @@ public final class Settings {
soundPack = props.getProperty("soundPack", soundPack);
soundVolume = parseD(props.getProperty("soundVolume"), soundVolume);
soundPackDir = props.getProperty("soundPackDir", soundPackDir);
desktopNotifications = parseB(props.getProperty("desktopNotifications"), desktopNotifications);
iconPack = props.getProperty("iconPack", iconPack);
iconPackDir = props.getProperty("iconPackDir", iconPackDir);
appearance = parseEnum(Appearance.class, props.getProperty("appearance"), appearance);
@@ -317,6 +320,7 @@ public final class Settings {
props.setProperty("soundPack", soundPack);
props.setProperty("soundVolume", Double.toString(soundVolume));
props.setProperty("soundPackDir", soundPackDir);
props.setProperty("desktopNotifications", Boolean.toString(desktopNotifications));
props.setProperty("iconPack", iconPack);
props.setProperty("iconPackDir", iconPackDir);
props.setProperty("appearance", appearance.name());