Add F9/F10 screenshots, fix duplicate widget ID in motor screen

Generate motor.svg and survey.svg for the new TUI screens. Fix
MotorScreen bug: two Horizontal widgets shared id="motor-usals-inputs",
causing MountError. Replaced with classes="usals-input-row" since both
rows need the same styling. Regenerated all 13 screenshots.
This commit is contained in:
Ryan Malloy 2026-02-15 18:05:15 -07:00
parent cc3a0707a1
commit 592898dd7a
16 changed files with 3121 additions and 1545 deletions

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 89 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 84 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 90 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 93 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 89 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 89 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 89 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 83 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 474 KiB

After

Width:  |  Height:  |  Size: 652 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 89 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 90 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 94 KiB

View File

@ -214,6 +214,8 @@ LNB power control, DiSEqC switching, and modulation/FEC configuration — all th
DiSEqC 1.2 positioner motor control with three-column layout: jog/halt controls, stored positions, and USALS GotoX calculator. A live signal bar at the bottom provides real-time SNR, power, lock status, and motor position feedback for hands-free dish alignment. DiSEqC 1.2 positioner motor control with three-column layout: jog/halt controls, stored positions, and USALS GotoX calculator. A live signal bar at the bottom provides real-time SNR, power, lock status, and motor position feedback for hands-free dish alignment.
![Motor control](../../../assets/tui/motor.svg)
- Continuous jog (east/west) with keyboard arrows or button controls - Continuous jog (east/west) with keyboard arrows or button controls
- 3x3 stored position grid for quick satellite recall - 3x3 stored position grid for quick satellite recall
- USALS GotoX calculator with observer longitude input and satellite presets (QO-100, Galaxy 19, AMC-1) - USALS GotoX calculator with observer longitude input and satellite presets (QO-100, Galaxy 19, AMC-1)
@ -235,6 +237,8 @@ The motor continues to drive until explicitly halted or the 30-second safety tim
Automated carrier survey with two tabs: Full Band sweep across the entire IF range, and a QO-100 DATV tab with parameters optimized for the Es'hail-2 wideband transponder. Automated carrier survey with two tabs: Full Band sweep across the entire IF range, and a QO-100 DATV tab with parameters optimized for the Es'hail-2 wideband transponder.
![Carrier survey](../../../assets/tui/survey.svg)
<Tabs> <Tabs>
<TabItem label="Full Band"> <TabItem label="Full Band">
Six-stage survey pipeline: coarse sweep, peak detection, fine sweep, blind scan, TS sample, and catalog assembly. Results display as a spectrum plot and frequency table showing detected carriers with their symbol rate, modulation, lock status, and service names. Six-stage survey pipeline: coarse sweep, peak detection, fine sweep, blind scan, TS sample, and catalog assembly. Results display as a spectrum plot and frequency table showing detected carriers with their symbol rate, modulation, lock status, and service names.

View File

@ -5,7 +5,7 @@ Uses Textual's headless run_test() + Pilot API to programmatically navigate
each screen and export SVG renders. Requires no hardware runs entirely each screen and export SVG renders. Requires no hardware runs entirely
with DemoDevice synthetic signal data. with DemoDevice synthetic signal data.
Output: ../site/src/assets/tui/*.svg (11 screenshots) Output: ../site/src/assets/tui/*.svg (13 screenshots)
Usage: Usage:
cd tui && uv run python scripts/generate_screenshots.py cd tui && uv run python scripts/generate_screenshots.py
@ -122,6 +122,42 @@ async def capture_config_screen() -> None:
_save(svg, "config") _save(svg, "config")
async def capture_motor_screen() -> None:
"""Capture F9 Motor screen — 3-column layout with signal gauge."""
app = _new_app(show_splash=False)
async with app.run_test(size=TERM_SIZE, headless=True) as pilot:
await pilot.pause(MOUNT_PAUSE)
# Switch to Motor screen
await pilot.press("f9")
await pilot.pause(MODE_SWITCH_PAUSE)
# Wait for signal gauge to populate
await pilot.pause(1.0)
svg = app.export_screenshot(title="SkyWalker-1 — Motor Control")
_save(svg, "motor")
async def capture_survey_screen() -> None:
"""Capture F10 Survey screen — Full Band tab with spectrum plot."""
app = _new_app(show_splash=False)
async with app.run_test(size=TERM_SIZE, headless=True) as pilot:
await pilot.pause(MOUNT_PAUSE)
# Switch to Survey screen (Full Band tab is default)
await pilot.press("f10")
await pilot.pause(MODE_SWITCH_PAUSE)
# Wait for demo spectrum data to render
await pilot.pause(1.5)
svg = app.export_screenshot(title="SkyWalker-1 — Carrier Survey")
_save(svg, "survey")
async def capture_dark_mode() -> None: async def capture_dark_mode() -> None:
"""Capture dark-mode toggle with Star Wars notification toast.""" """Capture dark-mode toggle with Star Wars notification toast."""
app = _new_app(show_splash=False) app = _new_app(show_splash=False)
@ -182,6 +218,8 @@ async def main() -> None:
("Device screen (F6)", capture_device_screen), ("Device screen (F6)", capture_device_screen),
("Stream screen (F7)", capture_stream_screen), ("Stream screen (F7)", capture_stream_screen),
("Config screen (F8)", capture_config_screen), ("Config screen (F8)", capture_config_screen),
("Motor screen (F9)", capture_motor_screen),
("Survey screen (F10)", capture_survey_screen),
("Dark mode toggle", capture_dark_mode), ("Dark mode toggle", capture_dark_mode),
("Splash screen", capture_splash), ("Splash screen", capture_splash),
("Star Wars easter egg", capture_starwars), ("Star Wars easter egg", capture_starwars),

View File

@ -91,15 +91,15 @@ class MotorScreen(Container):
border: round #1a3050; border: round #1a3050;
margin: 0 1 0 0; margin: 0 1 0 0;
} }
MotorScreen #motor-usals-inputs { MotorScreen .usals-input-row {
height: auto; height: auto;
} }
MotorScreen #motor-usals-inputs Label { MotorScreen .usals-input-row Label {
color: #506878; color: #506878;
width: auto; width: auto;
margin: 0 1 0 0; margin: 0 1 0 0;
} }
MotorScreen #motor-usals-inputs Input { MotorScreen .usals-input-row Input {
width: 12; width: 12;
margin: 0 1; margin: 0 1;
} }
@ -172,10 +172,10 @@ class MotorScreen(Container):
with Vertical(classes="motor-col"): with Vertical(classes="motor-col"):
with Vertical(classes="motor-panel"): with Vertical(classes="motor-panel"):
yield Label("USALS GotoX", classes="motor-panel-title") yield Label("USALS GotoX", classes="motor-panel-title")
with Horizontal(id="motor-usals-inputs"): with Horizontal(classes="usals-input-row"):
yield Label("Observer Lon:") yield Label("Observer Lon:")
yield Input("-97.5", id="usals-obs-lon") yield Input("-97.5", id="usals-obs-lon")
with Horizontal(id="motor-usals-inputs"): with Horizontal(classes="usals-input-row"):
yield Label("Satellite Lon:") yield Label("Satellite Lon:")
yield Input("25.9", id="usals-sat-lon") yield Input("25.9", id="usals-sat-lon")
yield Button("Calculate & Go", id="usals-go", variant="success") yield Button("Calculate & Go", id="usals-go", variant="success")