Dashboard: advertise scroll keys only when the overview overflows
The footer named "↑↓ PgUp/PgDn scroll" unconditionally, even on a tall terminal where the whole overview fits and those keys do nothing. Gate the scroll atom on the body actually being taller than its viewport, so Esc is the only key advertised when there is nothing to scroll. Add a reusable Screen.content_overflows predicate (from the metrics the frame already records each paint) for the pattern, so any scrolling screen can gate its footer the same way. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
79fb014c52
commit
8daf3f1294
3 files changed
+37
-1
No files matched your search
@@ -121,7 +121,20 @@ class DashboardScreen(Screen):
|
||||
"""The live mesh overview. Renders state and scrolls; the opener feeds it."""
|
||||
|
||||
floating = False
|
||||
footer_hint = "↑↓ PgUp/PgDn scroll · Esc back"
|
||||
|
||||
@property
|
||||
def footer_hint(self) -> str: # type: ignore[override]
|
||||
"""The footer keys — advertising scroll only when the overview actually overflows.
|
||||
|
||||
The dashboard is one scrolling body, but on a tall terminal it often fits whole; a
|
||||
static ``↑↓ PgUp/PgDn scroll`` then names keys that do nothing. Show that atom only
|
||||
while the content is taller than the viewport (see
|
||||
:attr:`~meshterm.ui.tui.screen.Screen.content_overflows`); otherwise Esc is the only
|
||||
key that acts.
|
||||
"""
|
||||
if self.content_overflows:
|
||||
return "↑↓ PgUp/PgDn scroll · Esc back"
|
||||
return "Esc back"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
||||
@@ -208,6 +208,18 @@ class Screen:
|
||||
"""Lines a PageUp/PageDown moves: a screenful, bar one row kept for continuity."""
|
||||
return max(1, self._scroll_viewport - 1)
|
||||
|
||||
@property
|
||||
def content_overflows(self) -> bool:
|
||||
"""Whether the last-rendered body is taller than its viewport — i.e. it can scroll.
|
||||
|
||||
The reusable gate for the app-wide rule that a footer only advertises a key that
|
||||
would do something: a screen whose body fits has nothing to scroll, so it drops its
|
||||
``↑↓ PgUp/PgDn scroll`` atom (see :attr:`DashboardScreen.footer_hint`). Reads the
|
||||
metrics the frame recorded on the *previous* paint (:meth:`note_metrics`), so it is
|
||||
honest one frame after a resize — the frame repaints again immediately.
|
||||
"""
|
||||
return self._scroll_total > self._scroll_viewport
|
||||
|
||||
def scroll_by(self, delta: int, total: int, viewport: int) -> None:
|
||||
"""Adjust :attr:`scroll` by ``delta`` lines, clamped to the given content bounds."""
|
||||
self.scroll = _clamp_scroll(self.scroll + delta, total, viewport)
|
||||
|
||||
@@ -58,6 +58,17 @@ def _stripped(lines: list[str]) -> list[str]:
|
||||
# --- the screen ----------------------------------------------------------------------
|
||||
|
||||
|
||||
def test_footer_advertises_scroll_only_when_the_overview_overflows() -> None:
|
||||
"""The scroll keys join the footer only when the body is taller than the viewport."""
|
||||
screen = _screen()
|
||||
# Fits (the frame recorded a body no taller than the viewport): Esc alone acts.
|
||||
screen.note_metrics(total=10, viewport=20)
|
||||
assert screen.footer_hint == "Esc back"
|
||||
# Overflows: the scroll atom appears, ahead of Esc.
|
||||
screen.note_metrics(total=40, viewport=20)
|
||||
assert screen.footer_hint == "↑↓ PgUp/PgDn scroll · Esc back"
|
||||
|
||||
|
||||
def test_dashboard_renders_all_three_sections() -> None:
|
||||
"""Activity, Traffic, and RF health all render from a seeded window.
|
||||
|
||||
|
||||
Reference in new issue
Block a user