"""Tray-App und App-Zustände für whisper-local.""" import enum import threading from typing import Callable class AppState(enum.Enum): WAITING = "waiting" RECORDING = "recording" TRANSCRIBING = "transcribing" class PystrayApp: """Tray-Icon via pystray — cross-platform (Windows + Linux).""" def __init__(self, on_settings: Callable[[], None], on_quit: Callable[[], None]): self._on_settings = on_settings self._on_quit = on_quit self._icon = None def start(self) -> None: """Startet pystray in einem Daemon-Thread.""" import pystray from whisper_local.tray._icon import create_icon menu = pystray.Menu( pystray.MenuItem("Einstellungen", self._menu_settings), pystray.MenuItem("Beenden", self._menu_quit), ) self._icon = pystray.Icon( "whisper-local", create_icon(AppState.WAITING), "whisper-local", menu, ) thread = threading.Thread(target=self._icon.run, daemon=True) thread.start() def set_state(self, state: AppState) -> None: """Tauscht das Icon aus (thread-sicher).""" if self._icon is not None: from whisper_local.tray._icon import create_icon self._icon.icon = create_icon(state) def _menu_settings(self, icon, item) -> None: self._on_settings() def _menu_quit(self, icon, item) -> None: if self._icon is not None: self._icon.stop() self._on_quit() class NoOpTray: """Platzhalter-Implementierung für nicht-Windows-Plattformen.""" def start(self) -> None: pass def set_state(self, state: AppState) -> None: pass