From a8ce329758678f880ffa73e8b6511bee2d6558db Mon Sep 17 00:00:00 2001 From: Jean-Pierre Martineau Date: Sun, 4 Oct 2026 02:34:36 -0400 Subject: [PATCH] The handhelds' dashboard drops "one minute per dot column" The activity heading's aside ended "one minute per dot column". The PicoCalc and the Cardputer draw braille as solid tiles, so there are no dots there to count, and on 53 columns the words cost the heading its line. Where braille is solid the aside is "every packet heard" alone; the axis under the chart still marks the minutes. The desktop keeps it. Co-Authored-By: Claude Opus 5.5 (1M context) --- meshterm/ui/dashboard_screen.py | 25 ++++++++++++++++++++----- tests/test_dashboard.py | 18 ++++++++++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/meshterm/ui/dashboard_screen.py b/meshterm/ui/dashboard_screen.py index 80b0b2e..db85967 100644 --- a/meshterm/ui/dashboard_screen.py +++ b/meshterm/ui/dashboard_screen.py @@ -53,6 +53,7 @@ from ..core.events import MeshEvent from ..core.models import NODE_TYPE_REPEATER, Observation, utcnow from ..core.regions import Scope from ..persistence.repository import OBSERVATION_WINDOW +from ..platforms import Platform, on_platform from ..services.monitor_service import ACTIVITY_BUCKET_S, ACTIVITY_BUCKETS from .braillechart import axis_chart, axis_chrome, axis_label_w, meter, timeline_rows from .packet_viewer import KIND_STYLES, payload_marks @@ -125,6 +126,24 @@ _GRID_LABEL_W = 9 #: The screen's title, before any scope atom. _TITLE = "Dashboard — mesh overview" +#: What the whole-mesh activity chart counts, as the heading's aside says it. The desktop +#: adds the chart's unit, ``one minute per dot column``; a font that draws braille solid +#: (the PicoCalc's, the Cardputer's — :attr:`~meshterm.platforms.Platform.solid_braille`) +#: has no dots to count, and on 53 columns the words cost the heading its line +#: (JP, 2026-10-04). The axis under the chart still marks the minutes. +_ACTIVITY_ASIDE = "every packet heard · one minute per dot column" + + +@on_platform +def _bind_activity_aside(platform: Platform) -> None: + """Bind the activity heading's aside to the platform's braille (runs now and on switch).""" + global _ACTIVITY_ASIDE + _ACTIVITY_ASIDE = ( + "every packet heard" + if platform.solid_braille + else "every packet heard · one minute per dot column" + ) + class _ScopeDigest(NamedTuple): """One scope view's numbers over the window, in the shapes the sections draw. @@ -429,11 +448,7 @@ class DashboardScreen(Screen): heading = Text("Activity", style="accent") # A narrowed view spends the aside on what it counts, which the reader has to be # told; the minute per column is on the axis beneath either way. - what = ( - "floods in this scope · last 2 h" - if self._scope - else "every packet heard · one minute per dot column" - ) + what = "floods in this scope · last 2 h" if self._scope else _ACTIVITY_ASIDE heading.append(f" · {what}", style="muted") # Buckets seeded from a previous session's stored history draw grey; only # what this session heard itself pulses green. diff --git a/tests/test_dashboard.py b/tests/test_dashboard.py index 9799712..2ee2aef 100644 --- a/tests/test_dashboard.py +++ b/tests/test_dashboard.py @@ -89,6 +89,24 @@ def test_dashboard_renders_all_three_sections() -> None: assert "advert" in body and "Alice" in body # traffic class + the busiest node +def test_the_activity_aside_names_dot_columns_only_where_braille_has_dots() -> None: + """The handhelds draw braille solid, so the heading drops ``one minute per dot column``. + + There are no dots there to count, and on 53 columns the words cost the heading its + line. The desktop keeps them; both keep what the chart counts. + """ + from meshterm.platforms import PICOCALC, REGULAR, set_platform + + def heading(width: int) -> str: + body = _plain(_screen(histogram=[1] * ACTIVITY_BUCKETS).render_body(width)) + return next(line for line in body.splitlines() if "Activity" in line) + + set_platform(PICOCALC) + assert heading(53).strip() == "Activity · every packet heard" + set_platform(REGULAR) + assert heading(72).strip() == "Activity · every packet heard · one minute per dot column" + + def test_dashboard_activity_chart_reads_newest_right_with_mirrored_scale() -> None: """'now' anchors the right edge and the scale marks mirror on both gutters.