blitztext-app-linux/linux/blitztext/notify.py
mARTin-B78 6448711f65 Stop notification storms: transient notifications, single instance, no empty-result alerts
- notify-send notifications are now transient (boolean:transient:true) with a
  2.5s expiry, so they no longer pile up in the message tray / lock screen.
- Single-instance guard (abstract unix socket) in the entry point: a second
  `tray`/`gui`/`run` launch exits instead of starting a duplicate daemon — the
  duplicate caused two wakeword listeners + two recorders.
- Empty/quiet/keyword-only results now only log, instead of firing a desktop
  notification on every (often false) wakeword trigger.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 10:42:13 +02:00

38 lines
1.3 KiB
Python

"""Lightweight desktop feedback via notify-send, with stdout fallback."""
from __future__ import annotations
import shutil
import subprocess
import sys
_HAVE_NOTIFY = shutil.which("notify-send") is not None
_APP = "Blitztext"
# Reuse one notification bubble instead of stacking them.
_REPLACE_ID = "99317"
def notify(title: str, body: str = "", *, urgency: str = "normal", enabled: bool = True,
transient: bool = True) -> None:
if enabled and _HAVE_NOTIFY:
try:
args = [
"notify-send",
"--app-name", _APP,
"--urgency", urgency,
"--expire-time", "2500",
# Replace the previous bubble instead of stacking.
"--hint", f"string:x-canonical-private-synchronous:{_REPLACE_ID}",
]
if transient:
# Don't keep it in the notification log / lock screen.
args += ["--hint", "boolean:transient:true"]
args += [title, body]
subprocess.run(args, check=False)
return
except OSError:
pass
# Always echo to the console too — useful when running in a terminal.
line = f"[{_APP}] {title}" + (f"{body}" if body else "")
print(line, file=sys.stderr, flush=True)