feat: Implement forum topics support#985
Conversation
fbec9a8 to
8bb1443
Compare
ce54e24 to
6e18a51
Compare
|
I tested this and found a bug where topic names and message previews would sometimes show the wrong content, especially in big active chats. For a split second the correct names would show, then they change to different topics. Looks like it was a race condition with RecyclerView recycling. Here's the fix for ForumTopicView.java:
Tested it and the issue is gone now |
|
And also, another bug: tapping on a Replies notification would open the @replies chat but show it as empty with just the "This chat helps you keep track of replies..." message, even though there were actual replies The issue was in MainActivity.openMessagesController() - when the forum topics support was added, the code assumed all messageThreadId values were forum topic IDs and always created MessageTopicForum objects. But Replies use MessageTopicThread instead, so the app couldn't find the thread and showed the empty state. Here's the fix for MainActivity.java: In the openMessagesController() method, replace: With: |
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
areFileContentsIdentical memory-mapped both files via FileChannel.map; the MappedByteBuffer stays mapped until GC, so the follow-up truncate-write of the same file failed on Windows with a user-mapped section open error whenever generated sources actually changed. Files.mismatch compares without mapping. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… hunks) Feature-overlapping files were reset to upstream and will be re-adapted via the compiler in the next commit, to avoid pulling feature code into the core. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Re-applied the upgrade's genuine upstream adaptations that landed in feature- adjacent rejected hunks, with zero feature code: - assert-hash renames (assertMessageContent/Update/InputMessageContent) - InputMessagePhoto/InputPhoto, InputMessageReplyToMessage, Message ctor changes - toDraftInputMessageText helper (DraftMessageContentText/RichMessage) - removed InternalLinkType/SettingsSection cases for types absent in the new TdApi (Stars/premium deep-links route to the unsupported tooltip; they belong to the premium-billing feature) - dropped UpdatePendingTextMessage; de-duplicated StakeDice cases - pinned vkryl/core to the origin/main SHA (core must not carry the feature-era bump) core/tdlib now compiles clean (compileLatestX64DebugJavaWithJavac green). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ps remain Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…lib as flat .so-as-regular-blobs snapshot LFS push of the custom TDLib build was unreliable in this environment (GitHub GH008 server-side LFS enforcement over the full unshallowed history). The .so binaries (94 MB total, largest 25 MB) are now stored as regular Git blobs in a flattened single-commit snapshot (japananimetime/tdlib@tgx/tdlib-flat).
6e18a51 to
6e87998
Compare
The bundled (fork) TDLib emits update constructors that TdApi defines but Tdlib.processUpdate() had no case for, so they fell through to the default branch and threw via Td.unsupported(). Several of these (UpdateTextCompositionStyles, UpdateWebBrowserSettings) are pushed automatically right after init, so the app crashed to the "Aw, Snap!" recovery screen on every launch (all builds, all users). Handle all eight currently-unhandled updates as ignored no-ops (no UI consumes them yet): UpdateTextCompositionStyles, UpdateWebBrowserSettings, UpdateChatJoinResult, UpdateChatUnreadPollVoteCount, UpdateMessageContainsUnreadPollVotes, UpdatePendingMessage, UpdateNewOauthRequest, UpdateManagedBot, UpdateNewGuestQuery. Found exhaustively by diffing TdApi's Update* classes against processUpdate's cases. Device-verified: app now boots to the chat list. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit c2759de)
Net feature diff onto core/tdlib; ForumTopicView recovered from main (net-diff version used old API), TGReactions reverted to core (paid-reaction contamination), messageThreadId->forumTopicId (MessageTopicForum field rename), topic-id send threading preserved. Stale TdApi hunks dropped. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…Android#813][TGX-Android#814] Two topic-scoping regressions in MessagesController, both reverted during the branch reconstruction while their supporting infrastructure stayed live: - getDraftMessage() dropped the forumTopic.draftMessage branch, so a topic-scoped controller (forumTopic != null, messageThread == null) showed the chat-level draft and per-topic drafts were invisible. Restore the topic-aware precedence; return null when a MessageTopicForum controller's ForumTopic is not yet backfilled so the chat draft is not wrongly applied. [TGX-Android#813] - reactions long-press unconditionally sent ReadAllChatReactions(chatId), marking the whole forum read instead of the open topic. Scope to ReadAllForumTopicReactions when getMessageTopicId() is a MessageTopicForum. [TGX-Android#814] Found + adversarially verified by the autonomous audit-loop (divergent-vs-backup) against backup/main-pre-split-20260613. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit 4bcefcd)
…n rebind [TGX-Android#821][TGX-Android#825] - mention badge long-press unconditionally sent ReadAllChatMentions(chatId), marking the whole chat read inside a forum topic. Scope to ReadAllForumTopicMentions when getMessageTopicId() is a MessageTopicForum, mirroring the reactions handler. [TGX-Android#821] - pendingMessageEffectId (a one-shot per-message effect) was never reset when a reused controller rebinds to a different chat, so an effect chosen but not sent in chat A stamped the first message in chat B. Reset it in the openChat setup path alongside discardAttachedFiles. [TGX-Android#825] Found + verified by the autonomous audit-loop (divergent-vs-backup / correctness). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit 175c865)
…ler [#826] The posted runnable mutated the topics list and called adapter.notifyItemChanged with no isDestroyed()/null re-check on the UI thread, unlike every other forum-topic listener callback in this controller (all hardened during the reconstruction). After destroy it poked a torn-down adapter/RecyclerView. Add the same `if (isDestroyed() || topics == null) return;` guard inside the lambda. Found + verified by the autonomous audit-loop (correctness). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit 97fd37a)
] Pinned-topic order could not be changed (SetPinnedForumTopics was never sent). Add an ItemTouchHelper drag-reorder confined to the pinned prefix and gated on canManageTopics() (same check as pin/unpin): onMove reorders the shared topics list (mirrored into allTopics) with notifyItemMoved; on drop, the pinned ids are collected in visual order and sent via SetPinnedForumTopics(chatId, int[]), reloading on TDLib error to restore authoritative order. Drag-only (no swipe), drops confined to the pinned region. Parity-coverage audit. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit 6b5dfb5)
…ages Tapping a chat in the list attaches a scroll-anchor highlight whenever the chat has unread messages. The forum-routing in TdlibUi.openChat treats any highlight payload as "open the unified message list instead of the topic list", so a forum with unread messages rendered as a flat chat while a fully-read forum correctly showed its topic list. Don't attach the flat-chat anchor highlight for forum chats: forums that genuinely open as a unified chat (view-as-messages mode) still get their scroll anchor recomputed inside TdlibUi.openChat, so nothing is lost. Device-verified. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit dcf6e1a)
5774f7d to
f5eec46
Compare
Adds complete forum topics functionality:
🤖 Generated with Claude Code
The guide below provides the flow for creating a perfect pull request to the Telegram X Repository. Before submitting your PR, ensure that it complies with the following principles.
Perfect PRs must be:
'main'branch.When fixing issues, make sure that your PR is:
When adding features, expect:
Other contributions:
PR types not mentioned above can be considered as well, provided they are rational. For example, optimizations of existing features or the app build time (for this, before/after timing is mandatory). For code refactoring, the code should be clearly improved/simplified/more convenient and is expected to be free of any edge-case bugs.
Good luck and thanks for the contribution!