Switch tray to GTK status icon

This commit is contained in:
Thales Maciel 2026-02-07 15:59:13 -03:00
parent b5bd0071f0
commit be0444ec52
4 changed files with 139 additions and 76 deletions

View file

@ -1,52 +1,57 @@
from __future__ import annotations
from dataclasses import dataclass
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import GLib, Gtk
from pathlib import Path
from threading import Thread
import pystray
from PIL import Image
@dataclass
class TrayIcons:
idle: Image.Image
recording: Image.Image
transcribing: Image.Image
processing: Image.Image
class Tray:
def __init__(self, state_getter, on_quit):
self.state_getter = state_getter
self.on_quit = on_quit
self.base = Path(__file__).parent / "assets"
self.icon = Gtk.StatusIcon()
self.icon.set_visible(True)
self.icon.connect("popup-menu", self._on_menu)
self.menu = Gtk.Menu()
quit_item = Gtk.MenuItem(label="Quit")
quit_item.connect("activate", lambda *_: self.on_quit())
self.menu.append(quit_item)
self.menu.show_all()
def _on_menu(self, _icon, _button, _time):
self.menu.popup(None, None, None, None, 0, _time)
def load_icons() -> TrayIcons:
base = Path(__file__).parent / "assets"
return TrayIcons(
idle=Image.open(base / "idle.png"),
recording=Image.open(base / "recording.png"),
transcribing=Image.open(base / "transcribing.png"),
processing=Image.open(base / "processing.png"),
)
def _icon_path(self, state: str) -> str:
if state == "recording":
return str(self.base / "recording.png")
if state == "transcribing":
return str(self.base / "transcribing.png")
if state == "processing":
return str(self.base / "processing.png")
return str(self.base / "idle.png")
def _title(self, state: str) -> str:
if state == "recording":
return "Recording"
if state == "transcribing":
return "Transcribing"
if state == "processing":
return "AI Processing"
return "Idle"
def update(self):
state = self.state_getter()
self.icon.set_from_file(self._icon_path(state))
self.icon.set_tooltip_text(self._title(state))
return True
def run_tray(state_getter, on_quit):
icons = load_icons()
icon = pystray.Icon("lel", icons.idle, "lel")
def update():
while True:
state = state_getter()
if state == "recording":
icon.icon = icons.recording
icon.title = "Recording"
elif state == "transcribing":
icon.icon = icons.transcribing
icon.title = "Transcribing"
elif state == "processing":
icon.icon = icons.processing
icon.title = "AI Processing"
else:
icon.icon = icons.idle
icon.title = "Idle"
icon.update_menu()
icon.menu = pystray.Menu(pystray.MenuItem("Quit", lambda: on_quit()))
Thread(target=update, daemon=True).start()
icon.run()
tray = Tray(state_getter, on_quit)
tray.update()
GLib.timeout_add(250, tray.update)
Gtk.main()