[morethanwords/tweb/master](https://github.com/morethanwords/tweb/tree/master) • [882c48a](https://github.com/morethanwords/tweb/commit/882c48a2eb986aa863aefafe7acf76599f9cbe78) • _1 files, +10/-0_
Fix stale forum avatar unread badge

[morethanwords/tweb/master](https://github.com/morethanwords/tweb/tree/master) • [e934b90](https://github.com/morethanwords/tweb/commit/e934b9039d1af2db82a7226f5073a510886509c2) • _3 files, +4/-5_
Remove ripple from archive and community rows

[morethanwords/tweb/master](https://github.com/morethanwords/tweb/tree/master) • [8f6b380](https://github.com/morethanwords/tweb/commit/8f6b3800c55daf66b61e80a54fa5a15712b5e2dc) • _9 files, +152/-61_
Show forum membership actions

[morethanwords/tweb/master](https://github.com/morethanwords/tweb/tree/master) • [119c827](https://github.com/morethanwords/tweb/commit/119c82769ab8b65b115925e0b52bb2858e317831) • _3 files, +65/-83_
Align chat actions plate with translation layout

[morethanwords/tweb/master](https://github.com/morethanwords/tweb/tree/master) • [1cb8bb8](https://github.com/morethanwords/tweb/commit/1cb8bb86387d58d34c3ad3d606d95e6db227a16f) • _9 files, +513/-203_
Use thread separators instead of topic chips

[morethanwords/tweb/master](https://github.com/morethanwords/tweb/tree/master) • [1d0e373](https://github.com/morethanwords/tweb/commit/1d0e373370ae7c77f08762ee571114716ed93ea2) • _11 files, +218/-64_
Pinned message plate: thread-scoped everywhere, no flicker

Opening a forum topic flashed the plate with the channel-wide pin: the initial
hint came from `fullPeer.pinned_msg_id` while the plate's own list is fetched
with `threadId`, so a topic with no pins revealed the plate and hid it again
one task later (and shifted `--pinned-floating-height` with it).

topbar: seed the hint only when there is no threadId; key the staged setup by
  peer + thread (on mobile one chat instance is reused across peer changes, so
  peerId alone kept the previous topic's plate); pass threadId into the pinned
  tab and its title counter; drop the eagerly created throwaway plate
pinnedMessage: clear pinnedMid/pinnedIndex when the list resolves to empty, so
  no phantom hint is saved into ChatSavedPosition and re-flashed next open

Pinning while sitting at the end of the chat kept the previous pin with a
bumped counter: the `peer_pinned_messages` anchor was unconditional. Anchor
only while the user is actually walking the pin list (locked /
waitForScrollBottom) and not already at the end of the history.

Rest of the review of the plate:
- forum: unpin-all / hide are thread-scoped too (top_msg_id, thread-keyed
  hiddenPinnedMessages, thread-filtered local pFlags.pinned sweep), and both
  pin events carry threadId so a change in one topic no longer resets the
  plate of every other open topic
- chat: isPinnedMessagesNeeded() dropped the stale `|| isForum`, which put a
  plate inside a forum's own pinned-messages tab (and scheduled, and search)
- getPinnedMessage remembers an empty list; testMid mirrors setCorrectIndex's
  no-pins guard, so a jump-to-message in a chat without pins stops refetching
- _setPinnedMessage takes a render seq so an older run can't commit over a
  newer pin; destroy() cancels the debounce, throttle and leaving-button
  timers; the stale dataset.mid is cleared when nothing is pinned
- getCurrentIndexPromise is reset before the trailing testMid/setCorrectIndex
  so a fetch they start isn't orphaned
- followPinnedMessage falls back to mids[0] when pinnedMaxMid isn't known yet,
  instead of wrapping onto the oldest pin
- setCorrectIndex returns for static (Discussion) plates instead of doing an
  elementFromPoint reflow on every throttled scroll

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

[#webk](?q=%23webk)