feat(src/window/spotlight/plugins): implement is_active detection and notification handling for caffeine plugin
Add CaptureNotifier import and send notifications when caffeine is enabled or disabled. Introduce is_active() static method to check inhibition status via PID file and process cmdline. Replace previous _read_pid() usage with is_active(). Enhance _humanize to properly format "0s" and hour-only durations. Update activation logic to use the new method and trigger appropriate notifications.
This commit is contained in:
1 file changed
+39
-6
@@ -4,6 +4,7 @@ import subprocess
|
||||
|
||||
from fabric.utils import logger
|
||||
|
||||
from shared.capture import CaptureNotifier
|
||||
from utils.functions import format_duration, parse_timeout_string
|
||||
from window.spotlight.api import SearchResult, SpotlightPlugin
|
||||
|
||||
@@ -12,11 +13,12 @@ _PID_FILE = os.path.join(
|
||||
)
|
||||
_INHIBIT_WHAT = "idle:sleep"
|
||||
_INHIBIT_WHY = "Modus Caffeine"
|
||||
# Spotlight exits on dismiss, so we pin an effectively infinite sleep for
|
||||
# indefinite mode instead of relying on an in-process timer.
|
||||
_INDEFINITE_SECS = 100_000_000
|
||||
|
||||
|
||||
_notifier = CaptureNotifier(app_name="Modus Caffeine")
|
||||
|
||||
|
||||
class CaffeinePlugin(SpotlightPlugin):
|
||||
id = "caffeine"
|
||||
name = "Caffeine"
|
||||
@@ -67,6 +69,21 @@ class CaffeinePlugin(SpotlightPlugin):
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def is_active() -> bool:
|
||||
"""Check if caffeine inhibition is currently active."""
|
||||
try:
|
||||
with open(_PID_FILE) as f:
|
||||
pid = int(f.read().strip())
|
||||
except (OSError, ValueError):
|
||||
return False
|
||||
try:
|
||||
with open(f"/proc/{pid}/cmdline", "rb") as f:
|
||||
data = f.read().decode(errors="ignore")
|
||||
return "systemd-inhibit" in data and _INHIBIT_WHY in data
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
# --- duration parsing ----------------------------------------------
|
||||
|
||||
@staticmethod
|
||||
@@ -77,11 +94,8 @@ class CaffeinePlugin(SpotlightPlugin):
|
||||
@staticmethod
|
||||
def _humanize(secs: int) -> str:
|
||||
result = format_duration(secs)
|
||||
# format_duration returns "N/A" for 0, but we want "0s"
|
||||
if result == "N/A":
|
||||
return "0s"
|
||||
# format_duration returns "Xh Ym" or "Xm", we want shorter format
|
||||
# For hours only: "1h" instead of "1h 0m"
|
||||
if "h" in result and "m" in result:
|
||||
hours = result.split("h")[0]
|
||||
return f"{hours}h"
|
||||
@@ -111,15 +125,34 @@ class CaffeinePlugin(SpotlightPlugin):
|
||||
|
||||
def _apply(self, arg: str) -> None:
|
||||
arg = (arg or "").strip().lower()
|
||||
was_active = self.is_active()
|
||||
if arg in ("", "on"):
|
||||
self._spawn(_INDEFINITE_SECS)
|
||||
if not was_active:
|
||||
_notifier.notify(
|
||||
"Caffeine Enabled",
|
||||
"Stay awake until turned off",
|
||||
icon="user-available-symbolic",
|
||||
)
|
||||
return
|
||||
if arg == "off":
|
||||
self._kill_existing()
|
||||
if was_active:
|
||||
_notifier.notify(
|
||||
"Caffeine Disabled",
|
||||
"Idle and sleep allowed again",
|
||||
icon="user-away-symbolic",
|
||||
)
|
||||
return
|
||||
secs = self._parse_duration(arg)
|
||||
if secs is not None:
|
||||
self._spawn(secs)
|
||||
if not was_active:
|
||||
_notifier.notify(
|
||||
"Caffeine Enabled",
|
||||
f"Stay awake for {self._humanize(secs)}",
|
||||
icon="user-available-symbolic",
|
||||
)
|
||||
return
|
||||
logger.warning(f"[Caffeine] unknown argument: {arg!r}")
|
||||
|
||||
@@ -184,7 +217,7 @@ class CaffeinePlugin(SpotlightPlugin):
|
||||
q = q[len(kw) :].strip()
|
||||
break
|
||||
|
||||
active = self._read_pid() is not None
|
||||
active = self.is_active()
|
||||
|
||||
if not q or q in ("caffeine", "caff"):
|
||||
return self._menu(active)
|
||||
|
||||
Reference in new issue
Block a user