Refactor Docker and Local Setup Commands

- Enhanced the docker_setup.py to streamline image building and pulling processes with improved logging and error handling.
- Introduced a new LogScreen for better user feedback during long-running tasks.
- Updated local_setup.py to utilize logging for installation steps and improved error handling.
- Refactored robot_setup.py to simplify configuration saving and user interaction.
- Added a new LogScreen class in tui.py for consistent logging across different setup processes.
- Modified install.sh to adjust the installation directory for better organization.
This commit is contained in:
Даниил Грабарь
2026-05-20 17:41:11 +03:00
parent bbfec17876
commit 5f16825cf7
6 changed files with 507 additions and 502 deletions
+58 -2
View File
@@ -1,12 +1,12 @@
from __future__ import annotations
from typing import List, Optional
from typing import Callable, List, Optional
from textual import on
from textual.app import ComposeResult
from textual.binding import Binding
from textual.screen import Screen
from textual.widgets import Footer, Input, RadioButton, RadioSet, Static
from textual.widgets import Footer, Input, RadioButton, RadioSet, RichLog, Static
SCREEN_CSS = """
Screen {
@@ -36,6 +36,16 @@ RadioSet {
Input {
margin-bottom: 1;
}
LogScreen #log {
height: 1fr;
border: none;
padding: 0 1;
margin-top: 1;
}
LogScreen #hint {
margin-top: 1;
color: $text;
}
"""
@@ -114,3 +124,49 @@ class InputScreen(Screen[Optional[str]]):
def action_abort(self) -> None:
self.app.exit(None)
class LogScreen(Screen[bool]):
"""Streams task output into a scrollable log; press Enter to close when done."""
BINDINGS = [Binding("enter,escape", "close", "Close", show=False)]
def __init__(self, title: str, task: Callable[[LogScreen], None]):
super().__init__()
self._title = title
self._run_fn = task
self._finished = False
def compose(self) -> ComposeResult:
yield Static(self._title, id="step")
yield RichLog(id="log", highlight=True, markup=True, wrap=True)
yield Static("", id="hint")
yield Footer()
def on_mount(self) -> None:
self.query_one(RichLog).focus()
self.app.run_worker(lambda: self._run_fn(self), thread=True)
def write(self, line: str) -> None:
"""Thread-safe: append a line to the log."""
self.app.call_from_thread(self._append, line)
def _append(self, line: str) -> None:
self.query_one(RichLog).write(line)
def finish(self, success: bool) -> None:
"""Thread-safe: mark task done and prompt the user to close."""
self.app.call_from_thread(self._do_finish, success)
def _do_finish(self, success: bool) -> None:
self._finished = True
msg = (
"[green]Done![/green] Press [bold]Enter[/bold] to close."
if success
else "[red]Failed.[/red] Press [bold]Enter[/bold] to close."
)
self.query_one("#hint", Static).update(msg)
def action_close(self) -> None:
if self._finished:
self.dismiss(True)