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.
Regression from f362c16106: moving the key event filter from the
InputField to its raw QTextEdit made the Escape branch consume the key
before InputField::keyPressEventInner could fire cancelled(), so
sections like scheduled messages no longer went back on Escape with a
focused field. Keep the Cmd+Up/Down handling on the raw text edit and
suppress the propagated Escape in a separate filter on the field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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>
On selection change the top bar derives its active block and menu from the live article selection instead of the previously edited node, so a multi-cell table rectangle always lights the table button and its menu offers Unite cells.