""" Thread-safe bridge between sync threads and async Textual TUI. """ import queue import time from dataclasses import dataclass, field from enum import Enum from typing import Optional, Any class MessageType(Enum): DEVICE_CONNECTED = "device_connected" DEVICE_DISCONNECTED = "device_disconnected" DEVICE_RECONNECTED = "device_reconnected" DEVICE_INFO_UPDATED = "device_info_updated" DEVICE_EVENT = "device_event" COMMAND_SENT = "command_sent" COMMAND_RESPONSE = "command_response" SYSTEM_MESSAGE = "system_message" ERROR = "error" @dataclass class TUIMessage: """Message from sync thread to async TUI.""" msg_type: MessageType payload: str timestamp: float = field(default_factory=time.time) device_id: Optional[str] = None request_id: Optional[str] = None class TUIBridge: """Thread-safe bridge between sync threads and async Textual app.""" def __init__(self): self._queue: queue.Queue[TUIMessage] = queue.Queue() self._app: Any = None def set_app(self, app): """Called by TUI app on startup.""" self._app = app def post_message(self, msg: TUIMessage): """Called by sync threads (Display class).""" self._queue.put(msg) if self._app: try: self._app.call_from_thread(self._app.process_bridge_queue) except Exception: pass def get_pending_messages(self) -> list[TUIMessage]: """Called by async TUI to drain the queue.""" messages = [] while True: try: messages.append(self._queue.get_nowait()) except queue.Empty: break return messages # Global bridge instance tui_bridge = TUIBridge()