Message paths: hold the fan's shape still across the selection
The dialog ranked layers by selection (priority 3 for the picked path, 2 for the rest), so every ↑↓ re-elected the spine and re-laid the whole graph out. Rank by first-heard order instead and move `emphasis`, the way the node detail's Routes tab already does — the geometry is fixed by evidence, only the white lane moves. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
18b1e034fd
commit
8fdd7572bd
2 files changed
+30
-2
No files matched your search
@@ -278,15 +278,22 @@ class MessagePathsScreen(Screen):
|
||||
(:func:`~meshterm.ui.widgets.route_graph_style`): endpoints named, relays their
|
||||
own map marker where the type is known, each labelled by its first hash byte in
|
||||
the node's own hue.
|
||||
|
||||
Layout rank is fixed by first-heard order (the first path heard is always the spine),
|
||||
exactly as the node detail's Routes tab fixes it by evidence order, so the fan's
|
||||
geometry holds still as ↑↓ walk the arrivals — only the emphasis (which lane draws
|
||||
white and on top) follows the pick.
|
||||
"""
|
||||
selected = self._arrivals[self._index].hops
|
||||
paths = self._paths()
|
||||
layers = [
|
||||
PathLayer(
|
||||
hops=path,
|
||||
color=_EDGE_SELECTED if path == selected else _EDGE_UNUSED,
|
||||
priority=3 if path == selected else 2,
|
||||
priority=len(paths) - i,
|
||||
emphasis=1 if path == selected else 0,
|
||||
)
|
||||
for path in self._paths()
|
||||
for i, path in enumerate(paths)
|
||||
]
|
||||
glyph_of, label_of, label_rgb_of = route_graph_style(
|
||||
resolve=self._resolve, self_name=self._self_name, source=self._source,
|
||||
|
||||
@@ -96,6 +96,27 @@ def test_paths_screen_draws_selected_path_white_over_gray() -> None:
|
||||
assert "38;2;255;255;255" in raw2 and "38;2;110;110;110" in raw2
|
||||
|
||||
|
||||
def test_paths_screen_graph_geometry_holds_still_across_the_selection() -> None:
|
||||
"""↑↓ repaint the fan's colours, never its shape — the Routes tab's rule.
|
||||
|
||||
Layout rank is first-heard order, so only ``emphasis`` follows the pick; the drawn
|
||||
glyphs/lanes are byte-identical from every selection.
|
||||
"""
|
||||
now = utcnow()
|
||||
arrivals = [
|
||||
Arrival(when=now, hops=("3d63",), snr=4.0),
|
||||
Arrival(when=now + timedelta(seconds=2), hops=("a1b2", "77aa"), snr=-2.0),
|
||||
Arrival(when=now + timedelta(seconds=4), hops=("a1b2", "5c5c", "77aa"), snr=1.0),
|
||||
]
|
||||
screen = _screen(arrivals)
|
||||
shapes = []
|
||||
for _ in range(len(arrivals)):
|
||||
shapes.append(_plain(screen._graph_lines(76)))
|
||||
screen.handle("down")
|
||||
assert len(set(shapes)) == 1, "the graph's shape moved when the selection did"
|
||||
assert shapes[0].count("\n") > 1 # a genuine multi-lane fan, not one flat line
|
||||
|
||||
|
||||
def test_paths_screen_marks_a_repeater_relay_with_its_triangle() -> None:
|
||||
"""A relay whose type resolves to a repeater draws ▲, not the generic dot."""
|
||||
screen = _screen(_arrivals(), type_of=lambda h: 2 if h == "3d63" else None)
|
||||
|
||||
Reference in new issue
Block a user