# firmware_test: TUI app screens styling & app_logo
This commit is contained in:
parent
86df36fab7
commit
0132d8056d
6 changed files with 102 additions and 20 deletions
|
|
@ -15,8 +15,8 @@ Screen {
|
|||
AppFrame {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: 160;
|
||||
max-height: 50;
|
||||
max-width: 112;
|
||||
max-height: 35;
|
||||
border: heavy $primary;
|
||||
background: $surface;
|
||||
padding: 1 2;
|
||||
|
|
@ -25,19 +25,31 @@ AppFrame {
|
|||
/* ── WaitingScreen ──────────────────────────────────────── */
|
||||
|
||||
#waiting-frame {
|
||||
align: center middle;
|
||||
align: center top;
|
||||
}
|
||||
|
||||
#waiting-logo {
|
||||
width: 52;
|
||||
height: 7;
|
||||
border: round $primary;
|
||||
padding: 1 2;
|
||||
content-align: center middle;
|
||||
color: $primary;
|
||||
#waiting-logo-row {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
margin-top: 1;
|
||||
}
|
||||
|
||||
#waiting-logo-art {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#waiting-version-row {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
margin-top: 1;
|
||||
}
|
||||
|
||||
#waiting-version {
|
||||
color: $warning;
|
||||
text-style: bold;
|
||||
text-align: center;
|
||||
margin-bottom: 1;
|
||||
}
|
||||
|
||||
#waiting-reason {
|
||||
margin-top: 1;
|
||||
padding: 1 2;
|
||||
|
|
@ -163,6 +175,11 @@ AppFrame {
|
|||
margin-right: 2;
|
||||
}
|
||||
|
||||
#post-flash-title-row,
|
||||
#post-flash-instruction-row {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
/* ── DiagScreen ─────────────────────────────────────────── */
|
||||
|
||||
#diag-frame {
|
||||
|
|
|
|||
33
tools/production/app/boot_art.py
Normal file
33
tools/production/app/boot_art.py
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
"""
|
||||
boot_art.py — ASCII-логотип компании для WaitingScreen.
|
||||
|
||||
Сгенерирован программно (coverage-based растеризация logo.png в
|
||||
символы плотности + разделение по цвету blue/dark), затем зафиксирован
|
||||
как статичная строка — рантайм-зависимости на Pillow/etc. не требуется.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
LOGO_ART = """
|
||||
[grey37]........[/grey37][#3ca0dc].**:+*::*+.[/#3ca0dc][grey37]..........[/grey37]
|
||||
[grey37]........[/grey37][#3ca0dc].##:*#++#*.[/#3ca0dc][grey37]..........[/grey37]
|
||||
[grey37].........[/grey37][#3ca0dc]*#[/#3ca0dc][grey37].[/grey37][#3ca0dc]:#..#+[/#3ca0dc][grey37]...........[/grey37]
|
||||
[grey37].......[/grey37][#3ca0dc].+#:[/#3ca0dc][grey37].[/grey37][#3ca0dc]:#..#+[/#3ca0dc][grey37]...........[/grey37]
|
||||
[grey37].....[/grey37][#3ca0dc].+#+..:#*..#+[/#3ca0dc][grey37]...........[/grey37]
|
||||
[grey37]...[/grey37][#3ca0dc].+#+..:**:..*#.[/#3ca0dc][white].:.[/white][grey37]........[/grey37]
|
||||
[grey37].[/grey37][#3ca0dc].+#+..:#*:..*#+.[/#3ca0dc][white]+@@+[/white][grey37]........[/grey37]
|
||||
[grey37].[/grey37][#3ca0dc]##..:#*.[/#3ca0dc][grey37].[/grey37][#3ca0dc].*#+.[/#3ca0dc][white]%@@@@%[/white][grey37].[/grey37][white]::.[/white][grey37]....[/grey37]
|
||||
[grey37].[/grey37][#3ca0dc]#*[/#3ca0dc][grey37].[/grey37][#3ca0dc]:#:[/#3ca0dc][grey37].[/grey37][#3ca0dc].*#+.[/#3ca0dc][white]+@@@@@@%[/white][grey37].[/grey37][white]+@...[/white][grey37]..[/grey37]
|
||||
[grey37].[/grey37][#3ca0dc]#*[/#3ca0dc][grey37].[/grey37][#3ca0dc]+#..#+.[/#3ca0dc][grey37]........[/grey37][white]%%[/white][grey37].[/grey37][white]+@..%.[/white][grey37].[/grey37]
|
||||
[grey37].[/grey37][#3ca0dc]#*[/#3ca0dc][grey37].[/grey37][#3ca0dc]+#.:#:[/#3ca0dc][grey37].........[/grey37][white]%%[/white][grey37].[/grey37][white]+@..@:[/white][grey37].[/grey37]
|
||||
[grey37].[/grey37][#3ca0dc]**[/#3ca0dc][grey37].[/grey37][#3ca0dc]+#.:#:[/#3ca0dc][grey37]........[/grey37][white].%%[/white][grey37].[/grey37][white]+@..@:[/white][grey37].[/grey37]
|
||||
[grey37].[/grey37][#3ca0dc]..[/#3ca0dc][grey37].[/grey37][#3ca0dc]+#.:#*+++++.[/#3ca0dc][white].:@%.[/white][grey37].[/grey37][white]+@..@:[/white][grey37].[/grey37]
|
||||
[grey37]....[/grey37][#3ca0dc].*.:#####+.[/#3ca0dc][white]+@%.[/white][grey37].[/grey37][white]:%%:[/white][grey37].[/grey37][white]:@:[/white][grey37].[/grey37]
|
||||
[grey37]......[/grey37][#3ca0dc].:###+.[/#3ca0dc][white]+@%.[/white][grey37].[/grey37][white].%%:..+@+.[/white][grey37].[/grey37]
|
||||
[grey37].......[/grey37][#3ca0dc].:+.[/#3ca0dc][white]:@%.[/white][grey37].[/grey37][white].%@:..+@+.[/white][grey37]...[/grey37]
|
||||
[grey37]...........[/grey37][white]@%[/white][grey37].[/grey37][white].%@:..+@+.[/white][grey37].....[/grey37]
|
||||
[grey37]...........[/grey37][white]@%[/white][grey37].[/grey37][white]%@..+@+.[/white][grey37].......[/grey37]
|
||||
[grey37]...........[/grey37][white]@%[/white][grey37].[/grey37][white]%@[/white][grey37].[/grey37][white]:@:[/white][grey37].........[/grey37]
|
||||
[grey37]..........[/grey37][white].@%.%@.+@+[/white][grey37].........[/grey37]
|
||||
[grey37]..........[/grey37][white]:@@:@@+%@%.[/white][grey37]........[/grey37]
|
||||
""".strip("\n")
|
||||
|
|
@ -19,7 +19,7 @@ post_flash.py — экран-промпт после успешной проши
|
|||
from __future__ import annotations
|
||||
|
||||
from textual.app import ComposeResult
|
||||
from textual.containers import Horizontal
|
||||
from textual.containers import Center, Horizontal
|
||||
from textual.message import Message
|
||||
from textual.screen import Screen
|
||||
from textual.timer import Timer
|
||||
|
|
@ -49,8 +49,10 @@ class PostFlashScreen(Screen):
|
|||
|
||||
def compose(self) -> ComposeResult:
|
||||
with AppFrame(id="post-flash-frame"):
|
||||
with Center(id="post-flash-title-row"):
|
||||
yield Label("✅ firmware_test успешно записан", id="post-flash-title")
|
||||
|
||||
with Center(id="post-flash-instruction-row"):
|
||||
yield Static(
|
||||
"Переведите плату в нормальный режим:\nBOOT_MOD_1 → GND → Reset",
|
||||
id="post-flash-instruction",
|
||||
|
|
|
|||
|
|
@ -14,25 +14,53 @@ waiting.py — экран ожидания подключения платы.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from textual.app import ComposeResult
|
||||
from textual.containers import Center
|
||||
from textual.css.query import NoMatches
|
||||
from textual.message import Message
|
||||
from textual.screen import Screen
|
||||
from textual.timer import Timer
|
||||
from textual.widgets import Static
|
||||
|
||||
from ..boot_art import LOGO_ART
|
||||
from ..flasher import Flasher
|
||||
from ..models import AppMode
|
||||
from ..widgets import AppFrame
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_DETECT_INTERVAL_S = 1.5
|
||||
_SPIN_INTERVAL_S = 0.1
|
||||
_REASON_DISPLAY_S = 4.0
|
||||
_SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]
|
||||
|
||||
|
||||
def _read_app_version() -> str:
|
||||
"""
|
||||
Прочитать версию service-tui из pyproject.toml.
|
||||
|
||||
Не используем importlib.metadata — проект не устанавливается как пакет
|
||||
(tool.uv.package = false), метаданные могут отсутствовать. Читаем файл
|
||||
напрямую через tomllib (stdlib, requires-python >= 3.11 уже задан).
|
||||
"""
|
||||
pyproject_path = Path(__file__).resolve().parents[2] / "pyproject.toml"
|
||||
try:
|
||||
with pyproject_path.open("rb") as f:
|
||||
data = tomllib.load(f)
|
||||
return data.get("project", {}).get("version", "0.0.0")
|
||||
except Exception as exc:
|
||||
logger.warning("Не удалось прочитать версию из %s: %s", pyproject_path, exc)
|
||||
return "0.0.0"
|
||||
|
||||
|
||||
_APP_VERSION = _read_app_version()
|
||||
|
||||
|
||||
class WaitingScreen(Screen):
|
||||
"""
|
||||
Экран ожидания.
|
||||
|
|
@ -58,7 +86,9 @@ class WaitingScreen(Screen):
|
|||
|
||||
def compose(self) -> ComposeResult:
|
||||
with AppFrame(id="waiting-frame"):
|
||||
yield Static("TFT Indicator Board\nService Tool", id="waiting-logo")
|
||||
yield Static(f"service_tool v{_APP_VERSION}", id="waiting-version")
|
||||
with Center(id="waiting-logo-row"):
|
||||
yield Static(LOGO_ART, id="waiting-logo-art")
|
||||
yield Static("", id="waiting-reason", classes="hidden")
|
||||
yield Static("Подключите плату индикатора к USB...", id="waiting-hint")
|
||||
yield Static(_SPINNER_FRAMES[0], id="waiting-spinner")
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[project]
|
||||
name = "service-tui"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
description = "TUI сервисного инженера для диагностики платы MIMXRT1052"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = [
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ wheels = [
|
|||
|
||||
[[package]]
|
||||
name = "service-tui"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "pyinstaller" },
|
||||
|
|
|
|||
Loading…
Reference in a new issue