forum: fix reply_to_top_id for replies inside a forum

resolveChannelReply applied discussion-thread logic (reply_to_top_id =
the replied-to message's own id) to forum replies. Replying to a General
message produced reply_to_top_id = <that id>, a topic no client can
resolve: the reply vanished from every topic view and reply-jump on
strict clients said "message doesn't exist".

Forum replies now inherit the target's topic via domain.ForumReplyTopicID
(target's topic, or its own id if it's a topic-create, else General), and
General (topic 1) is accepted as a valid virtual topic everywhere, so
sends carrying top_msg_id: 1 are no longer rejected. Non-forum discussion
threads are unchanged.
This commit is contained in:
Astra 2026-09-09 11:15:56 +01:00
parent f0bf315bf3
commit c7a77c23c8
4 changed files with 213 additions and 37 deletions

View file

@ -735,6 +735,23 @@ type ChannelMessage struct {
Deleted bool
}
// ForumReplyTopicID resolves the topic a reply to target belongs to inside a
// forum. Every forum message lives in exactly one topic, and a reply inherits
// the target's topic - never the target's own id. Using target.ID is
// discussion-thread logic (comment threads on a broadcast post) and does not
// apply to forums: it manufactures a topic reference that no channel_forum_topics
// row backs, which strict clients cannot place. A target with no recorded topic
// is in General.
func ForumReplyTopicID(target ChannelMessage) int {
if target.Action != nil && target.Action.Type == ChannelActionTopicCreate {
return target.ID // the target itself is a topic root
}
if target.ReplyTo != nil && target.ReplyTo.TopMessageID > 0 {
return target.ReplyTo.TopMessageID
}
return ForumGeneralTopicID
}
// ProjectChannelHistoryClearMessage returns the owner-local service-message
// projection for one channel history boundary. Identity fields from the shared
// source are retained when available, while all user payload, media, reply,