Factor the floating cloud bubble's painting and scroll-mount wiring into shared helpers so the bubble content can be mounted standalone over any scrollable surface.
ChatFilters::applyRemove() emptied the filter in the list and only then
detached its chats. Unpinning a chat re-caches its siblings' pinned
indices, which runs Session::refreshChatListEntry(); seeing the filter
still listed but emptied, it re-entered removeFromChatList() ->
setChatPinned() -> PinnedList::setPinned() on the same pinned list while
its re-cache loop iterated with a cached size, reading past the end of
the vector. This aborted on closing the Folders editor after removing
two or more folders that had pinned chats.
Detach the filter from the list before applyChange() tears down its
chats, so the re-entrant refresh no longer touches it. Also harden the
setPinned() re-cache loop to re-check the container size each iteration
as defense in depth.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Home/End jumped to the first/last chat until InnerWidget's key handling
was rewritten from a switch into an if/else chain (in 'Extract chats list
accessibility, fix build'), which carried over only Up/Down and Page
Up/Down and dropped the Home/End cases.
Re-add them, skipping by the actual total row count (which selectSkip()
clamps) instead of the previous 1<<20 constant, so it lands on the first
or last row in both the default list and the filtered/search results.
In screen reader mode, focusing the dialogs search field no longer opens
the suggestions panel or shows the cancel-search button. Search engages
only when the user types, stays engaged after clearing the query, and
disengages only on explicit Escape or the cancel-search button. Tab and
Backspace on an empty query no longer exit search in this mode.
Non-screen-reader behavior is unchanged.