Files
HellionChat/HellionChat
JonKazama-Hellion 6bb020547d feat(tabs): groundwork for the tab editor
The two halves that can be settled without a window, before the window
exists.

Concurrency first, because the editor is the first thing that ever
writes SelectedChannels after load. All three channel-filter fields are
read without a lock from the pending-message thread, the filter worker
and the draw thread, and mutating a live Dictionary while Matches walks
it is the standard way to get a wrong answer on somebody else's stack.
ReplaceChannelFilter builds the replacements and swaps the references,
so a reader sees the old set or the new one and never half of either.

It deliberately stops short of making the three writes one atomic step.
A reader can catch the new dictionary with the old ExtraChat flag for a
single message, which the editor's closing clear-and-refilter
reconsiders anyway. Doing better would mean one reference for all three,
and all three are serialized fields whose shape the config file already
has.

Then the index maths, which is where temp tabs make this more than list
arithmetic. They live in the same collection, they are not editable --
their name is a conversation partner and deleting one would be deleting
a conversation -- and a move has to step over them rather than swap with
them, or moving a tab down and back up would not return it to where it
started. Reversible in the editable order, which is the order the user
sees; the sidebar draws temp tabs under their own headers regardless of
where they sit in the list.

Twelve facts, and one of them started out asserting the wrong property:
that the whole list is restored by a move and its reverse. It is not,
and it does not need to be.

The last editable tab cannot be deleted. The message list has no empty
state, so a window with nothing to draw is not a state to offer.
2026-08-18 23:39:43 +02:00
..