The mention chips of a selected chat message go white with its text

In a channel, a DM, or a room, the selected message's text is white, and
now its mention chips follow: the label turns white and the fill stays, so
the chips still tell one node from the next. Arrow mode whitens the label
the same way. A mention that no key can place keeps its grey, as on every
selected row.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
Jean-Pierre MartineauandClaude Haiku 5.5 committed 2026-10-19 23:48:59 -04:00
1 parent 59273a6b29
commit 7264a71104
4 files changed
+68 -3

No files matched your search

+4 -1
View File
@@ -592,7 +592,10 @@ as a grouped list does. Filling a page in is editing its `.md`; no Python follow
what a route graph's one-byte labels are matched by — so `pathline` stamps its own extent
(`PATH_INK`, a style that draws nothing) and the fold skips what lies inside it. That is
what makes the arrow form say what the chip form always said, its fills having never been
in the fold's vocabulary. Reverse-video chips — a dialog's committing button,
in the fold's vocabulary. The one exception is a chat's **selected message**: its mention
chips go white with its text (JP, 2026-10-19) — the label only, the fill kept, keyed hues
only (`widgets.picked_hop`: `white_ink` on a chip, `cursor` in arrow mode). A mention is
a name in prose, not a hop of a route. Reverse-video chips — a dialog's committing button,
a running action's Abort, the arrow-mode composer slot, the editor cursor — are the
`selected` fill, a **grey** block (`muted`'s grey; light grey slot 7 on the VT, the one
grey a reverse can put behind text there, and the same fill the F-key lane uses). A chip
+8 -1
View File
@@ -51,6 +51,7 @@ from .widgets import (
hop_chip,
mention_hop,
mention_mark,
picked_hop,
self_chip,
)
@@ -910,6 +911,9 @@ class ChatScreen(Screen):
whose chip closes on the point). The chip has no ``@``, because the chip already
says that the name is a mention (JP, 2026-10-13). Arrow mode has no chip, so there a
mention keeps its ``@`` (refer to :func:`~meshterm.ui.widgets.mention_hop`).
On the selected message, the label of each chip is white, as the text around it is
(refer to :func:`~meshterm.ui.widgets.picked_hop`, JP, 2026-10-19).
"""
base = "cursor" if selected else None
text = Text()
@@ -917,7 +921,10 @@ class ChatScreen(Screen):
for match in MENTION.finditer(body):
if match.start() > pos:
text.append(body[pos : match.start()], style=base)
text.append_text(hop_chip(self._mention_hop(match.group(1)), role=DESTINATION))
hop = self._mention_hop(match.group(1))
if selected:
hop = picked_hop(hop) # the chips turn white with the text around them
text.append_text(hop_chip(hop, role=DESTINATION))
pos = match.end()
if pos < len(body):
text.append(body[pos:], style=base)
+22 -1
View File
@@ -5,7 +5,7 @@ from __future__ import annotations
import math
from collections.abc import Callable, Sequence
from dataclasses import dataclass, field
from dataclasses import dataclass, field, replace
from datetime import datetime
from itertools import pairwise
from typing import TYPE_CHECKING
@@ -789,6 +789,27 @@ def mention_hop(name: str, key: str | None, *, you: bool = False) -> PathHop:
return PathHop(label, key=key or None, white_ink=you and bool(key), quiet=True)
def picked_hop(hop: PathHop) -> PathHop:
"""``hop`` on the selected message of a chat: its label in the white of the selection.
The text of the selected message is white (``cursor``), and its chips follow it (JP,
2026-10-19). A chip keeps its fill, so it still tells one node from the next, and only
its label turns white: the white label of our own chip
(:attr:`~meshterm.ui.pathline.PathHop.white_ink`). Arrow mode has no fill, so there the
label takes the ``cursor`` white, as each other name on a selected row does.
The rule is the rule of the white fold of a selected row (refer to
:func:`~meshterm.ui.tui.render._whiten_identities`): only the hue of a key turns white.
A node that no key can place keeps its grey, because the selection must not claim to
know that node. A hop that already has a white label stays as it is.
"""
if not hop.key or hop.white_ink:
return hop
if powerline_enabled():
return replace(hop, white_ink=True)
return replace(hop, style="cursor")
def mention_chip(name: str, key: str | None, *, you: bool = False) -> Text:
"""A mention in a message: the chip of the node that it names, which opens on the notch.
+34
View File
@@ -3254,6 +3254,40 @@ def test_a_locked_author_has_the_padlock_on_its_sender_chip(
assert "\U0001f512" not in shown and "Alice" in shown
@pytest.mark.parametrize("chips", [True, False])
def test_the_chips_of_the_selected_message_turn_white_with_its_text(
powerline, # noqa: ANN001
chips: bool,
) -> None:
"""On the selected message, a mention chip has a white label, as the text around it does.
JP, 2026-10-19. A chip keeps its fill, so it still tells one node from the next. In
arrow mode, the label takes the ``cursor`` white. A node that no key can place keeps its
grey, as on each selected row: the selection must not claim to know that node.
"""
powerline(chips)
keys = {"alice": "a1" * 32, "bob": "b2" * 32}
body = "hi @[Bob] and @[Zed]"
screen = ChatScreen(
Conversation(label="#public", is_channel=True, channel_idx=0),
[ChatMessage(text=f"Alice: {body}", is_channel=True, channel_idx=0)],
send=None,
names={},
session=_StubSession(),
key_of=lambda name: keys.get(name.casefold()),
)
def styles(label: str, *, selected: bool) -> str:
text = screen._render_mentions(body, selected=selected)
at = text.plain.index(label)
return " ".join(str(s.style) for s in text.spans if s.start <= at < s.end)
white = "#ffffff" if chips else "cursor"
assert white in styles("Bob", selected=True)
assert white not in styles("Bob", selected=False)
assert white not in styles("Zed", selected=True)
def test_the_lock_atom_never_pushes_another_key_out_of_the_hint(tmp_path: Path) -> None:
"""With a link and a location, the hint has no room for ^K, so the atom stays out.