refactor(tui): extract Activity readout and show local time

Move activity data assembly out of tui.py into activity_readout, behind
readout(conn, selection, now). Dashboard and fenris-monitor enable now show
local time with a timezone label, inspected points keep a secondary UTC line,
and the legacy UTC-relabelled day and hour branches are gone. Time formatting
(including freshness_age_human) lives in timefmt. Hour offsets now render as
+05:30 to match day labels.
This commit is contained in:
xavierk
2026-10-05 20:21:22 +05:30
parent ef61ececc1
commit 79ebb10dea
20 changed files with 1297 additions and 834 deletions
+35 -6
View File
@@ -20,6 +20,7 @@ NOW = datetime(2026, 9, 19, 12, tzinfo=timezone.utc)
@pytest.fixture
def dashboard(tmp_path, monkeypatch):
monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path / "prefs"))
monkeypatch.setenv("TZ", "UTC")
class Clock(datetime):
@classmethod
@@ -124,6 +125,19 @@ async def test_mouse_inspection_matches_time_axis(dashboard):
assert "09:00 → 09:03 UTC" in text
@pytest.mark.asyncio
async def test_live_readout_shows_local_time_with_secondary_utc_line(dashboard, monkeypatch):
monkeypatch.setenv("TZ", "Asia/Kolkata")
app = dashboard
async with app.run_test(size=(100, 36)) as pilot:
await pilot.pause()
await pilot.press("left")
text = str(app.query_one("#live-readout").render())
assert "17:24 → 17:27 Asia/Kolkata +05:30" in text
assert text.splitlines()[-1] == "11:54 → 11:57 UTC"
assert "local time" in str(app.query_one("#live-legend").render())
@pytest.mark.asyncio
async def test_theme_control_persists_choice_and_quit_never_pauses(dashboard, monkeypatch):
calls = []
@@ -144,14 +158,27 @@ async def test_unallocated_volume_survives_day_with_missing_coverage(dashboard,
await pilot.click("#view-history")
graph = dashboard.query_one("#usage-history")
graph.set_data([{
"day": "2026-09-18", "total_bytes": 2_000_000_000,
"unallocated_bytes": 2_000_000_000, "is_gap": True,
"is_partial": True,
"day": "2026-09-18", "local_label": "2026-09-18",
"timezone_label": "UTC +00:00", "identity": None,
"total_bytes": None, "total_written": None, "total_read": None,
"shared_bytes_written": 2_000_000_000, "shared_bytes_read": 0,
"unallocated_bytes_written": 2_000_000_000,
"unallocated_bytes_read": 0, "activity_state": "incomplete",
"is_gap": True, "is_partial": True,
}])
readout = str(dashboard.query_one("#bar-readout").render())
assert "W 2.000 GB unallocated" in readout
assert "R unavailable" in readout and "gap" in readout
assert "unallocated W 2.000 GB" in readout
assert "W unavailable · R unavailable" in readout
if size[0] >= 80:
graph.set_data([{
"day": "2026-09-18", "local_label": "2026-09-18",
"timezone_label": "UTC +00:00", "identity": None,
"total_bytes": 2_000_000_000, "total_written": 2_000_000_000,
"total_read": None, "shared_bytes_written": 2_000_000_000,
"shared_bytes_read": 0, "unallocated_bytes_written": 0,
"unallocated_bytes_read": 0, "activity_state": "incomplete",
"is_gap": False, "is_partial": True,
}])
plot = str(dashboard.query_one("#bar-render").render())
assert any(0x2801 <= ord(c) <= 0x28ff for c in plot)
graph.measure = "read"
@@ -167,7 +194,9 @@ async def test_small_terminal_hour_readout_does_not_invent_zero(dashboard, state
await pilot.click("#view-day")
graph = dashboard.query_one("#usage-history")
graph.set_hour_data([{
"hour": "2026-09-18T12:00:00+00:00", "local_label": "12",
"hour": "2026-09-18T12:00:00+00:00", "local_label": "12:00",
"timezone_label": "UTC +00:00",
"utc_label": "2026-09-18 12:00 UTC",
"is_gap": state == "gap", "is_future": state == "future",
}])
graph._hourly_selected = 0