""" `meshbay-cli` with no argument: a full-screen terminal interface. Textual, because it runs on the same asyncio loop as aiortc and httpx rather than beside them, and on Linux terminals and Windows' consoles alike. Signed in already, it opens on the two panes — or, for `meshbay-cli chat` with no group, on the groups to chat in (`tui/chat.py`); otherwise on the sign-in screen first. Nothing is printed while it runs — a line on stderr would tear the screen — so the log goes to a file in the CLI's data directory instead. """ import logging from textual.app import App from ..client.account import Account, no_passphrase from ..client.hub import Hub from ..client.store import data_dir from ..commands.context import Context from ..errors import CliError from .screens import DeviceCode, MainScreen, SignInScreen class MeshBayApp(App): TITLE = "MeshBay" def __init__(self, ctx: Context, home=MainScreen): super().__init__() self.ctx = ctx self.hub = ctx.hub # The screen a signed-in account lands on, made from the account. self.home = home async def use_hub(self, url: str) -> None: if url != self.hub.url: await self.hub.aclose() self.hub = Hub(url) self.ctx.hub = self.hub self.ctx.hub_url = url def on_mount(self) -> None: account = None if self.ctx.store.peek().get("hub") == self.hub.url: try: account = Account.open(self.hub, None, no_passphrase, self.ctx.store) except CliError as e: self.notify(e.message, severity="warning", markup=False) if account is not None and account.remembered: self.start(account) else: self.push_screen(SignInScreen()) def start(self, account: Account) -> None: account.on_device_code = DeviceCode(self) if isinstance(self.screen, SignInScreen): self.switch_screen(self.home(account)) else: self.push_screen(self.home(account)) def _log_to_file() -> None: root = logging.getLogger() for h in list(root.handlers): root.removeHandler(h) try: directory = data_dir() directory.mkdir(parents=True, exist_ok=True) handler = logging.FileHandler(directory / "interactive.log", encoding="utf-8") except OSError: handler = logging.NullHandler() handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(name)s: %(message)s")) root.addHandler(handler) async def run_interactive(ctx: Context, home=MainScreen) -> int: _log_to_file() await MeshBayApp(ctx, home).run_async() return 0