From 83e2aa80ae3bceea41768fe5b4eb50c2d6210f2c Mon Sep 17 00:00:00 2001 From: Jean-Pierre Martineau Date: Sat, 12 Sep 2026 02:20:56 -0400 Subject: [PATCH] The trophy case fills the frame whichever way in A bare SelectScreen floats by default, and the browser was full-frame from the menu only because nothing sat under it; opened from a trace, over the still-pushed trace screen, the same page came up as a content-sized box. It is a place, not a question, and declares so like the contact list does. Co-Authored-By: Claude Fable 5.1 --- docs/survey-navigation.md | 4 ++++ meshterm/ui/records_screen.py | 5 +++++ tests/test_records_screen.py | 30 ++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/docs/survey-navigation.md b/docs/survey-navigation.md index 540d9bb..64b51a9 100644 --- a/docs/survey-navigation.md +++ b/docs/survey-navigation.md @@ -100,6 +100,10 @@ so what shows around it is the page it was reached from: `TuiSession._floated` n the **root** (the main menu, popped while a tool runs but still declared for ^W), and the reconnect dialog draws over it too. A blank base survives only for a session with no root. +*Same day — the trophy case is a place.* A bare `SelectScreen` floats by default, and the +browser was full-frame from the menu only by the compositor's fallback; opened from a +trace it came up as a box. It declares `floating = False` now, like the contact list. + **I. An entry chain of prompts was not a stack.** Five flows asked two or more things in a row, and Esc on any of them abandoned the whole flow rather than stepping back one — a mistyped 32-hex channel key cost the name typed before it. `menus.run_steps` now runs a diff --git a/meshterm/ui/records_screen.py b/meshterm/ui/records_screen.py index a9ddce6..9916437 100644 --- a/meshterm/ui/records_screen.py +++ b/meshterm/ui/records_screen.py @@ -907,6 +907,11 @@ async def open_records(ctx: AppContext) -> dict: footer_hint="↑↓ move · Enter open · Esc back", hscroll=True, # a long walk slides under ←→ instead of dying at the fold ) + # A place, not a question: the trophy case is the tool's own page, so it fills the + # frame whichever way in — from the menu, where it is the only screen and would be + # drawn full-frame anyway, and from a trace, where it opens over the still-pushed + # trace screen and used to come up as a content-sized box. + browser.floating = False # The browser stays pushed for the whole visit, so every dialog that belongs *over* # the trophy case — the discipline picker, the delete confirms, a record's floating # story — already has it drawn full-frame behind them, and the cursor is still on the diff --git a/tests/test_records_screen.py b/tests/test_records_screen.py index 28658f1..fffb9e9 100644 --- a/tests/test_records_screen.py +++ b/tests/test_records_screen.py @@ -380,6 +380,36 @@ def _trophy_case(session, *, other_than=None): return None +async def test_the_trophy_case_fills_the_frame_over_a_trace_too(tui_ctx) -> None: + """The trophy case is a place, so it is full-frame whichever way in. + + From the menu it is the only screen and was drawn full-frame by the compositor's + fallback; opened from a trace — over the still-pushed trace screen — the same list + came up as a content-sized box, because a bare ``SelectScreen`` floats by default. + """ + from meshterm.ui.tui.screen import ScrollScreen + + ctx = tui_ctx + session = ctx.ui.session + trace = ScrollScreen("", title="Trace — Lakeside", floating=False) + session.push(trace) + + task = asyncio.ensure_future(open_records(ctx)) + try: + browser = await _step_until(lambda: _trophy_case(session)) + assert browser is not None, "the trophy case list never opened" + assert not browser.floating + assert session._base_screen() is browser, "the page fills the frame, not a box over it" + assert not session._has_float() + browser.handle("escape") + await task + assert session._base_screen() is trace, "and Esc lands back on the trace" + finally: + if not task.done(): + task.cancel() + session.pop(trace) + + async def test_delete_all_confirm_floats_over_the_browser(tui_ctx) -> None: """The trophy case stays drawn full-frame behind the "Delete all records" confirm.