mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-06 15:13:57 +02:00
Track inbox/outbox comments/replies read state.
This commit is contained in:
parent
e021e0beb3
commit
13ad590a51
10 changed files with 257 additions and 192 deletions
|
@ -1929,8 +1929,35 @@ void Updates::feedUpdate(const MTPUpdate &update) {
|
||||||
case mtpc_updateReadChannelDiscussionInbox: {
|
case mtpc_updateReadChannelDiscussionInbox: {
|
||||||
const auto &d = update.c_updateReadChannelDiscussionInbox();
|
const auto &d = update.c_updateReadChannelDiscussionInbox();
|
||||||
const auto channelId = d.vchannel_id().v;
|
const auto channelId = d.vchannel_id().v;
|
||||||
if (const auto item = session().data().message(channelId, d.vtop_msg_id().v)) {
|
const auto msgId = d.vtop_msg_id().v;
|
||||||
item->setCommentsReadTill(d.vread_max_id().v);
|
const auto readTillId = d.vread_max_id().v;
|
||||||
|
const auto item = session().data().message(channelId, msgId);
|
||||||
|
if (item) {
|
||||||
|
item->setRepliesInboxReadTill(readTillId);
|
||||||
|
if (const auto post = item->lookupDiscussionPostOriginal()) {
|
||||||
|
post->setRepliesInboxReadTill(readTillId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (const auto broadcastId = d.vbroadcast_id()) {
|
||||||
|
if (const auto post = session().data().message(
|
||||||
|
broadcastId->v,
|
||||||
|
d.vbroadcast_post()->v)) {
|
||||||
|
post->setRepliesInboxReadTill(readTillId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case mtpc_updateReadChannelDiscussionOutbox: {
|
||||||
|
const auto &d = update.c_updateReadChannelDiscussionOutbox();
|
||||||
|
const auto channelId = d.vchannel_id().v;
|
||||||
|
const auto msgId = d.vtop_msg_id().v;
|
||||||
|
const auto readTillId = d.vread_max_id().v;
|
||||||
|
const auto item = session().data().message(channelId, msgId);
|
||||||
|
if (item) {
|
||||||
|
item->setRepliesOutboxReadTill(readTillId);
|
||||||
|
if (const auto post = item->lookupDiscussionPostOriginal()) {
|
||||||
|
post->setRepliesOutboxReadTill(readTillId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|
|
@ -238,9 +238,7 @@ bool RepliesList::buildFromData(not_null<Viewer*> viewer) {
|
||||||
if (viewer->around != ShowAtUnreadMsgId) {
|
if (viewer->around != ShowAtUnreadMsgId) {
|
||||||
return viewer->around;
|
return viewer->around;
|
||||||
} else if (const auto item = lookupRoot()) {
|
} else if (const auto item = lookupRoot()) {
|
||||||
if (const auto original = item->lookupDiscussionPostOriginal()) {
|
return item->computeRepliesInboxReadTillFull();
|
||||||
return original->computeCommentsReadTillFull();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return viewer->around;
|
return viewer->around;
|
||||||
}();
|
}();
|
||||||
|
@ -565,11 +563,16 @@ bool RepliesList::processMessagesIsEmpty(const MTPmessages_Messages &result) {
|
||||||
_fullCount = checkedCount;
|
_fullCount = checkedCount;
|
||||||
|
|
||||||
if (const auto item = lookupRoot()) {
|
if (const auto item = lookupRoot()) {
|
||||||
|
if (_skippedAfter == 0) {
|
||||||
|
item->setRepliesMaxId(_list.front());
|
||||||
|
} else {
|
||||||
|
item->setRepliesPossibleMaxId(maxId);
|
||||||
|
}
|
||||||
if (const auto original = item->lookupDiscussionPostOriginal()) {
|
if (const auto original = item->lookupDiscussionPostOriginal()) {
|
||||||
if (_skippedAfter == 0) {
|
if (_skippedAfter == 0) {
|
||||||
original->setCommentsMaxId(_list.front());
|
original->setRepliesMaxId(_list.front());
|
||||||
} else {
|
} else {
|
||||||
original->setCommentsPossibleMaxId(maxId);
|
original->setRepliesPossibleMaxId(maxId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,26 +198,36 @@ public:
|
||||||
[[nodiscard]] virtual bool externalReply() const {
|
[[nodiscard]] virtual bool externalReply() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] virtual MsgId repliesInboxReadTill() const {
|
||||||
|
return MsgId(0);
|
||||||
|
}
|
||||||
|
virtual void setRepliesInboxReadTill(MsgId readTillId) {
|
||||||
|
}
|
||||||
|
[[nodiscard]] virtual MsgId computeRepliesInboxReadTillFull() const {
|
||||||
|
return MsgId(0);
|
||||||
|
}
|
||||||
|
[[nodiscard]] virtual MsgId repliesOutboxReadTill() const {
|
||||||
|
return MsgId(0);
|
||||||
|
}
|
||||||
|
virtual void setRepliesOutboxReadTill(MsgId readTillId) {
|
||||||
|
}
|
||||||
|
[[nodiscard]] virtual MsgId computeRepliesOutboxReadTillFull() const {
|
||||||
|
return MsgId(0);
|
||||||
|
}
|
||||||
|
virtual void setRepliesMaxId(MsgId maxId) {
|
||||||
|
}
|
||||||
|
virtual void setRepliesPossibleMaxId(MsgId possibleMaxId) {
|
||||||
|
}
|
||||||
|
[[nodiscard]] virtual bool areRepliesUnread() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] virtual FullMsgId commentsItemId() const {
|
[[nodiscard]] virtual FullMsgId commentsItemId() const {
|
||||||
return FullMsgId();
|
return FullMsgId();
|
||||||
}
|
}
|
||||||
virtual void setCommentsItemId(FullMsgId id) {
|
virtual void setCommentsItemId(FullMsgId id) {
|
||||||
}
|
}
|
||||||
[[nodiscard]] virtual MsgId commentsReadTill() const {
|
|
||||||
return MsgId(0);
|
|
||||||
}
|
|
||||||
virtual void setCommentsReadTill(MsgId readTillId) {
|
|
||||||
}
|
|
||||||
virtual void setCommentsMaxId(MsgId maxId) {
|
|
||||||
}
|
|
||||||
virtual void setCommentsPossibleMaxId(MsgId possibleMaxId) {
|
|
||||||
}
|
|
||||||
[[nodiscard]] virtual MsgId computeCommentsReadTillFull() const {
|
|
||||||
return MsgId(0);
|
|
||||||
}
|
|
||||||
[[nodiscard]] virtual bool areCommentsUnread() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] virtual bool needCheck() const;
|
[[nodiscard]] virtual bool needCheck() const;
|
||||||
|
|
||||||
|
|
|
@ -45,10 +45,11 @@ struct HistoryMessageViews : public RuntimeComponent<HistoryMessageViews, Histor
|
||||||
Part views;
|
Part views;
|
||||||
Part replies;
|
Part replies;
|
||||||
Part repliesSmall;
|
Part repliesSmall;
|
||||||
ChannelId commentsChannelId = 0;
|
MsgId repliesInboxReadTillId = 0;
|
||||||
|
MsgId repliesOutboxReadTillId = 0;
|
||||||
|
MsgId repliesMaxId = 0;
|
||||||
|
ChannelId commentsMegagroupId = 0;
|
||||||
MsgId commentsRootId = 0;
|
MsgId commentsRootId = 0;
|
||||||
MsgId commentsReadTillId = 0;
|
|
||||||
MsgId commentsMaxId = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HistoryMessageSigned : public RuntimeComponent<HistoryMessageSigned, HistoryItem> {
|
struct HistoryMessageSigned : public RuntimeComponent<HistoryMessageSigned, HistoryItem> {
|
||||||
|
|
|
@ -772,7 +772,7 @@ bool HistoryMessage::checkCommentsLinkedChat(ChannelId id) const {
|
||||||
|
|
||||||
int HistoryMessage::repliesCount() const {
|
int HistoryMessage::repliesCount() const {
|
||||||
if (const auto views = Get<HistoryMessageViews>()) {
|
if (const auto views = Get<HistoryMessageViews>()) {
|
||||||
if (!checkCommentsLinkedChat(views->commentsChannelId)) {
|
if (!checkCommentsLinkedChat(views->commentsMegagroupId)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return std::max(views->replies.count, 0);
|
return std::max(views->replies.count, 0);
|
||||||
|
@ -782,8 +782,8 @@ int HistoryMessage::repliesCount() const {
|
||||||
|
|
||||||
bool HistoryMessage::repliesAreComments() const {
|
bool HistoryMessage::repliesAreComments() const {
|
||||||
if (const auto views = Get<HistoryMessageViews>()) {
|
if (const auto views = Get<HistoryMessageViews>()) {
|
||||||
return (views->commentsChannelId != 0)
|
return (views->commentsMegagroupId != 0)
|
||||||
&& checkCommentsLinkedChat(views->commentsChannelId);
|
&& checkCommentsLinkedChat(views->commentsMegagroupId);
|
||||||
}
|
}
|
||||||
return HistoryItem::repliesAreComments();
|
return HistoryItem::repliesAreComments();
|
||||||
}
|
}
|
||||||
|
@ -797,94 +797,139 @@ bool HistoryMessage::externalReply() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MsgId HistoryMessage::repliesInboxReadTill() const {
|
||||||
|
if (const auto views = Get<HistoryMessageViews>()) {
|
||||||
|
return views->repliesInboxReadTillId;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryMessage::setRepliesInboxReadTill(MsgId readTillId) {
|
||||||
|
if (const auto views = Get<HistoryMessageViews>()) {
|
||||||
|
const auto newReadTillId = std::max(readTillId, 1);
|
||||||
|
if (newReadTillId > views->repliesInboxReadTillId) {
|
||||||
|
const auto wasUnread = repliesAreComments() && areRepliesUnread();
|
||||||
|
views->repliesInboxReadTillId = newReadTillId;
|
||||||
|
if (wasUnread && !areRepliesUnread()) {
|
||||||
|
history()->owner().requestItemRepaint(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MsgId HistoryMessage::computeRepliesInboxReadTillFull() const {
|
||||||
|
const auto views = Get<HistoryMessageViews>();
|
||||||
|
if (!views) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const auto local = views->repliesInboxReadTillId;
|
||||||
|
const auto group = views->commentsMegagroupId
|
||||||
|
? history()->owner().historyLoaded(
|
||||||
|
peerFromChannel(views->commentsMegagroupId))
|
||||||
|
: history().get();
|
||||||
|
return group ? std::max(local, group->inboxReadTillId()) : local;
|
||||||
|
}
|
||||||
|
|
||||||
|
MsgId HistoryMessage::repliesOutboxReadTill() const {
|
||||||
|
if (const auto views = Get<HistoryMessageViews>()) {
|
||||||
|
return views->repliesOutboxReadTillId;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryMessage::setRepliesOutboxReadTill(MsgId readTillId) {
|
||||||
|
if (const auto views = Get<HistoryMessageViews>()) {
|
||||||
|
const auto newReadTillId = std::max(readTillId, 1);
|
||||||
|
if (newReadTillId > views->repliesOutboxReadTillId) {
|
||||||
|
views->repliesOutboxReadTillId = newReadTillId;
|
||||||
|
if (!repliesAreComments()) {
|
||||||
|
history()->session().changes().historyUpdated(
|
||||||
|
history(),
|
||||||
|
Data::HistoryUpdate::Flag::OutboxRead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MsgId HistoryMessage::computeRepliesOutboxReadTillFull() const {
|
||||||
|
const auto views = Get<HistoryMessageViews>();
|
||||||
|
if (!views) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const auto local = views->repliesOutboxReadTillId;
|
||||||
|
const auto group = views->commentsMegagroupId
|
||||||
|
? history()->owner().historyLoaded(
|
||||||
|
peerFromChannel(views->commentsMegagroupId))
|
||||||
|
: history().get();
|
||||||
|
return group ? std::max(local, group->outboxReadTillId()) : local;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryMessage::setRepliesMaxId(MsgId maxId) {
|
||||||
|
if (const auto views = Get<HistoryMessageViews>()) {
|
||||||
|
if (views->repliesMaxId != maxId) {
|
||||||
|
const auto comments = repliesAreComments();
|
||||||
|
const auto wasUnread = comments && areRepliesUnread();
|
||||||
|
views->repliesMaxId = maxId;
|
||||||
|
if (comments && wasUnread != areRepliesUnread()) {
|
||||||
|
history()->owner().requestItemRepaint(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryMessage::setRepliesPossibleMaxId(MsgId possibleMaxId) {
|
||||||
|
if (const auto views = Get<HistoryMessageViews>()) {
|
||||||
|
if (views->repliesMaxId < possibleMaxId) {
|
||||||
|
const auto comments = repliesAreComments();
|
||||||
|
const auto wasUnread = comments && areRepliesUnread();
|
||||||
|
views->repliesMaxId = possibleMaxId;
|
||||||
|
if (comments && !wasUnread && areRepliesUnread()) {
|
||||||
|
history()->owner().requestItemRepaint(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HistoryMessage::areRepliesUnread() const {
|
||||||
|
const auto views = Get<HistoryMessageViews>();
|
||||||
|
if (!views) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto local = views->repliesInboxReadTillId;
|
||||||
|
if (views->repliesInboxReadTillId < 2 || views->repliesMaxId <= local) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto group = views->commentsMegagroupId
|
||||||
|
? history()->owner().historyLoaded(
|
||||||
|
peerFromChannel(views->commentsMegagroupId))
|
||||||
|
: history().get();
|
||||||
|
return !group || (views->repliesMaxId > group->inboxReadTillId());
|
||||||
|
}
|
||||||
|
|
||||||
FullMsgId HistoryMessage::commentsItemId() const {
|
FullMsgId HistoryMessage::commentsItemId() const {
|
||||||
if (const auto views = Get<HistoryMessageViews>()) {
|
if (const auto views = Get<HistoryMessageViews>()) {
|
||||||
return FullMsgId(views->commentsChannelId, views->commentsRootId);
|
return FullMsgId(views->commentsMegagroupId, views->commentsRootId);
|
||||||
}
|
}
|
||||||
return FullMsgId();
|
return FullMsgId();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryMessage::setCommentsItemId(FullMsgId id) {
|
void HistoryMessage::setCommentsItemId(FullMsgId id) {
|
||||||
if (const auto views = Get<HistoryMessageViews>()) {
|
if (id.channel == _history->channelId()) {
|
||||||
if (views->commentsChannelId == id.channel) {
|
if (id.msg != this->id) {
|
||||||
views->commentsRootId = id.msg;
|
if (const auto reply = Get<HistoryMessageReply>()) {
|
||||||
}
|
reply->replyToMsgTop = id.msg;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MsgId HistoryMessage::commentsReadTill() const {
|
|
||||||
if (const auto views = Get<HistoryMessageViews>()) {
|
|
||||||
return views->commentsReadTillId;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistoryMessage::setCommentsReadTill(MsgId readTillId) {
|
|
||||||
if (const auto views = Get<HistoryMessageViews>()) {
|
|
||||||
const auto newReadTillId = std::max(readTillId, 1);
|
|
||||||
if (newReadTillId > views->commentsReadTillId) {
|
|
||||||
const auto wasUnread = areCommentsUnread();
|
|
||||||
views->commentsReadTillId = newReadTillId;
|
|
||||||
if (wasUnread && !areCommentsUnread()) {
|
|
||||||
history()->owner().requestItemRepaint(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return;
|
||||||
}
|
} else if (const auto views = Get<HistoryMessageViews>()) {
|
||||||
|
if (views->commentsMegagroupId != id.channel) {
|
||||||
void HistoryMessage::setCommentsMaxId(MsgId maxId) {
|
views->commentsMegagroupId = id.channel;
|
||||||
if (const auto views = Get<HistoryMessageViews>()) {
|
history()->owner().requestItemResize(this);
|
||||||
if (views->commentsMaxId != maxId) {
|
|
||||||
const auto wasUnread = areCommentsUnread();
|
|
||||||
views->commentsMaxId = maxId;
|
|
||||||
if (wasUnread != areCommentsUnread()) {
|
|
||||||
history()->owner().requestItemRepaint(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
views->commentsRootId = id.msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryMessage::setCommentsPossibleMaxId(MsgId possibleMaxId) {
|
|
||||||
if (const auto views = Get<HistoryMessageViews>()) {
|
|
||||||
if (views->commentsMaxId < possibleMaxId) {
|
|
||||||
const auto wasUnread = areCommentsUnread();
|
|
||||||
views->commentsMaxId = possibleMaxId;
|
|
||||||
if (!wasUnread && areCommentsUnread()) {
|
|
||||||
history()->owner().requestItemRepaint(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MsgId HistoryMessage::computeCommentsReadTillFull() const {
|
|
||||||
const auto local = commentsReadTill();
|
|
||||||
const auto views = Get<HistoryMessageViews>();
|
|
||||||
if (!views || !views->commentsChannelId) {
|
|
||||||
return local;
|
|
||||||
}
|
|
||||||
const auto group = history()->owner().historyLoaded(
|
|
||||||
peerFromChannel(views->commentsChannelId));
|
|
||||||
if (!group) {
|
|
||||||
return local;
|
|
||||||
}
|
|
||||||
return std::max(local, group->inboxReadTillId());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HistoryMessage::areCommentsUnread() const {
|
|
||||||
if (const auto views = Get<HistoryMessageViews>()) {
|
|
||||||
if (views->commentsReadTillId < 2
|
|
||||||
|| views->commentsMaxId <= views->commentsReadTillId) {
|
|
||||||
return false;
|
|
||||||
} else if (!views->commentsChannelId) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const auto group = history()->owner().historyLoaded(
|
|
||||||
peerFromChannel(views->commentsChannelId));
|
|
||||||
return !group || (views->commentsMaxId > group->inboxReadTillId());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HistoryMessage::updateDependencyItem() {
|
bool HistoryMessage::updateDependencyItem() {
|
||||||
if (const auto reply = Get<HistoryMessageReply>()) {
|
if (const auto reply = Get<HistoryMessageReply>()) {
|
||||||
const auto documentId = reply->replyToDocumentId;
|
const auto documentId = reply->replyToDocumentId;
|
||||||
|
@ -1555,29 +1600,31 @@ void HistoryMessage::setReplies(const MTPMessageReplies &data) {
|
||||||
}();
|
}();
|
||||||
const auto count = data.vreplies().v;
|
const auto count = data.vreplies().v;
|
||||||
const auto channelId = data.vchannel_id().value_or_empty();
|
const auto channelId = data.vchannel_id().value_or_empty();
|
||||||
const auto countChanged = (views->replies.count != count);
|
const auto readTillId = data.vread_max_id()
|
||||||
const auto channelChanged = (views->commentsChannelId != channelId);
|
? std::max(
|
||||||
|
{ views->repliesInboxReadTillId, data.vread_max_id()->v, 1 })
|
||||||
|
: views->repliesInboxReadTillId;
|
||||||
|
const auto maxId = data.vmax_id().value_or(views->repliesMaxId);
|
||||||
|
const auto countsChanged = (views->replies.count != count)
|
||||||
|
|| (views->repliesInboxReadTillId != readTillId)
|
||||||
|
|| (views->repliesMaxId != maxId);
|
||||||
|
const auto megagroupChanged = (views->commentsMegagroupId != channelId);
|
||||||
const auto recentChanged = (views->recentRepliers != repliers);
|
const auto recentChanged = (views->recentRepliers != repliers);
|
||||||
if (!countChanged && !channelChanged && !recentChanged) {
|
if (!countsChanged && !megagroupChanged && !recentChanged) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
views->replies.count = count;
|
views->replies.count = count;
|
||||||
if (recentChanged) {
|
if (recentChanged) {
|
||||||
views->recentRepliers = repliers;
|
views->recentRepliers = repliers;
|
||||||
}
|
}
|
||||||
views->commentsChannelId = channelId;
|
views->commentsMegagroupId = channelId;
|
||||||
const auto wasUnread = areCommentsUnread();
|
const auto wasUnread = channelId && areRepliesUnread();
|
||||||
if (const auto till = data.vread_max_id()) {
|
views->repliesInboxReadTillId = readTillId;
|
||||||
views->commentsReadTillId = std::max(
|
views->repliesMaxId = maxId;
|
||||||
{ views->commentsReadTillId, till->v, 1 });
|
if (channelId && wasUnread != areRepliesUnread()) {
|
||||||
}
|
|
||||||
if (const auto maxId = data.vmax_id()) {
|
|
||||||
views->commentsMaxId = maxId->v;
|
|
||||||
}
|
|
||||||
if (wasUnread != areCommentsUnread()) {
|
|
||||||
history()->owner().requestItemRepaint(this);
|
history()->owner().requestItemRepaint(this);
|
||||||
}
|
}
|
||||||
refreshRepliesText(views, channelChanged);
|
refreshRepliesText(views, megagroupChanged);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1585,7 +1632,7 @@ void HistoryMessage::refreshRepliesText(
|
||||||
not_null<HistoryMessageViews*> views,
|
not_null<HistoryMessageViews*> views,
|
||||||
bool forceResize) {
|
bool forceResize) {
|
||||||
const auto was = views->replies.textWidth;
|
const auto was = views->replies.textWidth;
|
||||||
if (views->commentsChannelId) {
|
if (views->commentsMegagroupId) {
|
||||||
views->replies.text = (views->replies.count > 0)
|
views->replies.text = (views->replies.count > 0)
|
||||||
? tr::lng_comments_open_count(
|
? tr::lng_comments_open_count(
|
||||||
tr::now,
|
tr::now,
|
||||||
|
@ -1621,7 +1668,7 @@ void HistoryMessage::changeRepliesCount(int delta, PeerId replier) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
views->replies.count = std::max(views->replies.count + delta, 0);
|
views->replies.count = std::max(views->replies.count + delta, 0);
|
||||||
if (replier && views->commentsChannelId) {
|
if (replier && views->commentsMegagroupId) {
|
||||||
if (delta < 0) {
|
if (delta < 0) {
|
||||||
views->recentRepliers.erase(
|
views->recentRepliers.erase(
|
||||||
ranges::remove(views->recentRepliers, replier),
|
ranges::remove(views->recentRepliers, replier),
|
||||||
|
@ -1691,7 +1738,7 @@ void HistoryMessage::changeReplyToTopCounter(
|
||||||
item->changeRepliesCount(delta, PeerId());
|
item->changeRepliesCount(delta, PeerId());
|
||||||
};
|
};
|
||||||
if (const auto views = top->Get<HistoryMessageViews>()) {
|
if (const auto views = top->Get<HistoryMessageViews>()) {
|
||||||
if (views->commentsChannelId) {
|
if (views->commentsMegagroupId) {
|
||||||
// This is a post in channel, we don't track its replies.
|
// This is a post in channel, we don't track its replies.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,14 +160,19 @@ public:
|
||||||
[[nodiscard]] int repliesCount() const override;
|
[[nodiscard]] int repliesCount() const override;
|
||||||
[[nodiscard]] bool repliesAreComments() const override;
|
[[nodiscard]] bool repliesAreComments() const override;
|
||||||
[[nodiscard]] bool externalReply() const override;
|
[[nodiscard]] bool externalReply() const override;
|
||||||
|
|
||||||
|
[[nodiscard]] MsgId repliesInboxReadTill() const override;
|
||||||
|
void setRepliesInboxReadTill(MsgId readTillId) override;
|
||||||
|
[[nodiscard]] MsgId computeRepliesInboxReadTillFull() const override;
|
||||||
|
[[nodiscard]] MsgId repliesOutboxReadTill() const override;
|
||||||
|
void setRepliesOutboxReadTill(MsgId readTillId) override;
|
||||||
|
[[nodiscard]] MsgId computeRepliesOutboxReadTillFull() const override;
|
||||||
|
void setRepliesMaxId(MsgId maxId) override;
|
||||||
|
void setRepliesPossibleMaxId(MsgId possibleMaxId) override;
|
||||||
|
[[nodiscard]] bool areRepliesUnread() const override;
|
||||||
|
|
||||||
[[nodiscard]] FullMsgId commentsItemId() const override;
|
[[nodiscard]] FullMsgId commentsItemId() const override;
|
||||||
void setCommentsItemId(FullMsgId id) override;
|
void setCommentsItemId(FullMsgId id) override;
|
||||||
[[nodiscard]] MsgId commentsReadTill() const override;
|
|
||||||
void setCommentsReadTill(MsgId readTillId) override;
|
|
||||||
void setCommentsMaxId(MsgId maxId) override;
|
|
||||||
void setCommentsPossibleMaxId(MsgId possibleMaxId) override;
|
|
||||||
[[nodiscard]] MsgId computeCommentsReadTillFull() const override;
|
|
||||||
[[nodiscard]] bool areCommentsUnread() const override;
|
|
||||||
bool updateDependencyItem() override;
|
bool updateDependencyItem() override;
|
||||||
[[nodiscard]] MsgId dependencyMsgId() const override {
|
[[nodiscard]] MsgId dependencyMsgId() const override {
|
||||||
return replyToId();
|
return replyToId();
|
||||||
|
|
|
@ -777,7 +777,7 @@ void Message::paintCommentsButton(
|
||||||
views ? views->replies.text : tr::lng_replies_view_original(tr::now),
|
views ? views->replies.text : tr::lng_replies_view_original(tr::now),
|
||||||
views ? views->replies.textWidth : -1);
|
views ? views->replies.textWidth : -1);
|
||||||
|
|
||||||
if (views && data()->areCommentsUnread()) {
|
if (views && data()->areRepliesUnread()) {
|
||||||
p.setPen(Qt::NoPen);
|
p.setPen(Qt::NoPen);
|
||||||
p.setBrush(outbg ? (selected ? st::msgFileOutBgSelected : st::msgFileOutBg) : (selected ? st::msgFileInBgSelected : st::msgFileInBg));
|
p.setBrush(outbg ? (selected ? st::msgFileOutBgSelected : st::msgFileOutBg) : (selected ? st::msgFileInBgSelected : st::msgFileInBg));
|
||||||
|
|
||||||
|
@ -1707,7 +1707,7 @@ void Message::drawInfo(
|
||||||
const auto iconTop = infoBottom + st::historyViewsTop;
|
const auto iconTop = infoBottom + st::historyViewsTop;
|
||||||
const auto textTop = infoBottom - st::msgDateFont->descent;
|
const auto textTop = infoBottom - st::msgDateFont->descent;
|
||||||
if (views->replies.count > 0
|
if (views->replies.count > 0
|
||||||
&& !views->commentsChannelId
|
&& !views->commentsMegagroupId
|
||||||
&& context() != Context::Replies) {
|
&& context() != Context::Replies) {
|
||||||
auto icon = [&] {
|
auto icon = [&] {
|
||||||
if (item->id > 0) {
|
if (item->id > 0) {
|
||||||
|
@ -1826,7 +1826,7 @@ int Message::infoWidth() const {
|
||||||
+ st::historyViewsWidth;
|
+ st::historyViewsWidth;
|
||||||
}
|
}
|
||||||
if (views->replies.count > 0
|
if (views->replies.count > 0
|
||||||
&& !views->commentsChannelId
|
&& !views->commentsMegagroupId
|
||||||
&& context() != Context::Replies) {
|
&& context() != Context::Replies) {
|
||||||
result += st::historyViewsSpace
|
result += st::historyViewsSpace
|
||||||
+ views->replies.textWidth
|
+ views->replies.textWidth
|
||||||
|
@ -1877,7 +1877,7 @@ int Message::timeLeft() const {
|
||||||
result += st::historyViewsSpace + views->views.textWidth + st::historyViewsWidth;
|
result += st::historyViewsSpace + views->views.textWidth + st::historyViewsWidth;
|
||||||
}
|
}
|
||||||
if (views->replies.count > 0
|
if (views->replies.count > 0
|
||||||
&& !views->commentsChannelId
|
&& !views->commentsMegagroupId
|
||||||
&& context() != Context::Replies) {
|
&& context() != Context::Replies) {
|
||||||
result += st::historyViewsSpace + views->replies.textWidth + st::historyViewsWidth;
|
result += st::historyViewsSpace + views->replies.textWidth + st::historyViewsWidth;
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,13 +92,11 @@ RepliesMemento::RepliesMemento(
|
||||||
TimeId(0),
|
TimeId(0),
|
||||||
FullMsgId(commentsItem->history()->channelId(), commentId)
|
FullMsgId(commentsItem->history()->channelId(), commentId)
|
||||||
});
|
});
|
||||||
} else if (const auto original = commentsItem->lookupDiscussionPostOriginal()) {
|
} else if (commentsItem->computeRepliesInboxReadTillFull() == MsgId(1)) {
|
||||||
if (original->computeCommentsReadTillFull() == MsgId(1)) {
|
_list.setAroundPosition(Data::MinMessagePosition);
|
||||||
_list.setAroundPosition(Data::MinMessagePosition);
|
_list.setScrollTopState(ListMemento::ScrollTopState{
|
||||||
_list.setScrollTopState(ListMemento::ScrollTopState{
|
Data::MinMessagePosition
|
||||||
Data::MinMessagePosition
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +126,6 @@ RepliesWidget::RepliesWidget(
|
||||||
, _history(history)
|
, _history(history)
|
||||||
, _rootId(rootId)
|
, _rootId(rootId)
|
||||||
, _root(lookupRoot())
|
, _root(lookupRoot())
|
||||||
, _commentsRoot(lookupCommentsRoot())
|
|
||||||
, _areComments(computeAreComments())
|
, _areComments(computeAreComments())
|
||||||
, _topBar(this, controller)
|
, _topBar(this, controller)
|
||||||
, _topBarShadow(this)
|
, _topBarShadow(this)
|
||||||
|
@ -209,9 +206,6 @@ RepliesWidget::RepliesWidget(
|
||||||
_root = nullptr;
|
_root = nullptr;
|
||||||
updatePinnedVisibility();
|
updatePinnedVisibility();
|
||||||
}
|
}
|
||||||
if (update.item == _commentsRoot) {
|
|
||||||
_commentsRoot = nullptr;
|
|
||||||
}
|
|
||||||
while (update.item == _replyReturn) {
|
while (update.item == _replyReturn) {
|
||||||
calculateNextReplyReturn();
|
calculateNextReplyReturn();
|
||||||
}
|
}
|
||||||
|
@ -228,7 +222,7 @@ RepliesWidget::~RepliesWidget() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RepliesWidget::sendReadTillRequest() {
|
void RepliesWidget::sendReadTillRequest() {
|
||||||
if (!_commentsRoot) {
|
if (!_root) {
|
||||||
_readRequestPending = true;
|
_readRequestPending = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -239,16 +233,15 @@ void RepliesWidget::sendReadTillRequest() {
|
||||||
const auto api = &_history->session().api();
|
const auto api = &_history->session().api();
|
||||||
api->request(base::take(_readRequestId)).cancel();
|
api->request(base::take(_readRequestId)).cancel();
|
||||||
_readRequestId = api->request(MTPmessages_ReadDiscussion(
|
_readRequestId = api->request(MTPmessages_ReadDiscussion(
|
||||||
_commentsRoot->history()->peer->input,
|
_root->history()->peer->input,
|
||||||
MTP_int(_commentsRoot->id),
|
MTP_int(_root->id),
|
||||||
MTP_int(_commentsRoot->computeCommentsReadTillFull())
|
MTP_int(_root->computeRepliesInboxReadTillFull())
|
||||||
)).done([=](const MTPBool &) {
|
)).done([=](const MTPBool &) {
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RepliesWidget::setupRoot() {
|
void RepliesWidget::setupRoot() {
|
||||||
if (_root) {
|
if (_root) {
|
||||||
setupCommentsRoot();
|
|
||||||
refreshRootView();
|
refreshRootView();
|
||||||
} else {
|
} else {
|
||||||
const auto channel = _history->peer->asChannel();
|
const auto channel = _history->peer->asChannel();
|
||||||
|
@ -256,7 +249,9 @@ void RepliesWidget::setupRoot() {
|
||||||
_root = lookupRoot();
|
_root = lookupRoot();
|
||||||
if (_root) {
|
if (_root) {
|
||||||
_areComments = computeAreComments();
|
_areComments = computeAreComments();
|
||||||
setupCommentsRoot();
|
if (_readRequestPending) {
|
||||||
|
sendReadTillRequest();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
updatePinnedVisibility();
|
updatePinnedVisibility();
|
||||||
refreshRootView();
|
refreshRootView();
|
||||||
|
@ -348,34 +343,6 @@ void RepliesWidget::setupRootView() {
|
||||||
}, _rootView->lifetime());
|
}, _rootView->lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
void RepliesWidget::setupCommentsRoot() {
|
|
||||||
Expects(_root != nullptr);
|
|
||||||
|
|
||||||
const auto postChannel = _root->discussionPostOriginalSender();
|
|
||||||
if (!postChannel) {
|
|
||||||
return;
|
|
||||||
} else if (_commentsRoot) {
|
|
||||||
if (_readRequestTimer.isActive() || _readRequestPending) {
|
|
||||||
sendReadTillRequest();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const auto forwarded = _root->Get<HistoryMessageForwarded>();
|
|
||||||
const auto messageId = forwarded->savedFromMsgId;
|
|
||||||
const auto done = crl::guard(this, [=](ChannelData*, MsgId) {
|
|
||||||
_commentsRoot = lookupCommentsRoot();
|
|
||||||
if (_commentsRoot) {
|
|
||||||
if (_readRequestTimer.isActive() || _readRequestPending) {
|
|
||||||
sendReadTillRequest();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
_history->session().api().requestMessageData(
|
|
||||||
postChannel,
|
|
||||||
messageId,
|
|
||||||
done);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RepliesWidget::refreshRootView() {
|
void RepliesWidget::refreshRootView() {
|
||||||
const auto sender = (_root && _root->discussionPostOriginalSender())
|
const auto sender = (_root && _root->discussionPostOriginalSender())
|
||||||
? _root->discussionPostOriginalSender()
|
? _root->discussionPostOriginalSender()
|
||||||
|
@ -408,12 +375,6 @@ HistoryItem *RepliesWidget::lookupRoot() const {
|
||||||
return _history->owner().message(_history->channelId(), _rootId);
|
return _history->owner().message(_history->channelId(), _rootId);
|
||||||
}
|
}
|
||||||
|
|
||||||
HistoryItem *RepliesWidget::lookupCommentsRoot() const {
|
|
||||||
return _root
|
|
||||||
? _root->lookupDiscussionPostOriginal()
|
|
||||||
: nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RepliesWidget::computeAreComments() const {
|
bool RepliesWidget::computeAreComments() const {
|
||||||
return _root && _root->isDiscussionPost();
|
return _root && _root->isDiscussionPost();
|
||||||
}
|
}
|
||||||
|
@ -1550,14 +1511,17 @@ void RepliesWidget::listSelectionChanged(SelectedItems &&items) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RepliesWidget::readTill(not_null<HistoryItem*> item) {
|
void RepliesWidget::readTill(not_null<HistoryItem*> item) {
|
||||||
if (!_commentsRoot) {
|
if (!_root) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto was = _commentsRoot->computeCommentsReadTillFull();
|
const auto was = _root->computeRepliesInboxReadTillFull();
|
||||||
const auto now = item->id;
|
const auto now = item->id;
|
||||||
const auto fast = item->out();
|
const auto fast = item->out();
|
||||||
if (was < now) {
|
if (was < now) {
|
||||||
_commentsRoot->setCommentsReadTill(now);
|
_root->setRepliesInboxReadTill(now);
|
||||||
|
if (const auto post = _root->lookupDiscussionPostOriginal()) {
|
||||||
|
post->setRepliesInboxReadTill(now);
|
||||||
|
}
|
||||||
if (!_readRequestTimer.isActive()) {
|
if (!_readRequestTimer.isActive()) {
|
||||||
_readRequestTimer.callOnce(fast ? 0 : kReadRequestTimeout);
|
_readRequestTimer.callOnce(fast ? 0 : kReadRequestTimeout);
|
||||||
} else if (fast && _readRequestTimer.remainingTime() > 0) {
|
} else if (fast && _readRequestTimer.remainingTime() > 0) {
|
||||||
|
@ -1578,10 +1542,10 @@ void RepliesWidget::listVisibleItemsChanged(HistoryItemsList &&items) {
|
||||||
|
|
||||||
MessagesBarData RepliesWidget::listMessagesBar(
|
MessagesBarData RepliesWidget::listMessagesBar(
|
||||||
const std::vector<not_null<Element*>> &elements) {
|
const std::vector<not_null<Element*>> &elements) {
|
||||||
if (!_commentsRoot || elements.empty()) {
|
if (!_root || elements.empty()) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const auto till = _commentsRoot->computeCommentsReadTillFull();
|
const auto till = _root->computeRepliesInboxReadTillFull();
|
||||||
if (till < 2) {
|
if (till < 2) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -1606,7 +1570,6 @@ MessagesBarData RepliesWidget::listMessagesBar(
|
||||||
}
|
}
|
||||||
|
|
||||||
void RepliesWidget::listContentRefreshed() {
|
void RepliesWidget::listContentRefreshed() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ClickHandlerPtr RepliesWidget::listDateLink(not_null<Element*> view) {
|
ClickHandlerPtr RepliesWidget::listDateLink(not_null<Element*> view) {
|
||||||
|
|
|
@ -155,7 +155,6 @@ private:
|
||||||
|
|
||||||
void setupRoot();
|
void setupRoot();
|
||||||
void setupRootView();
|
void setupRootView();
|
||||||
void setupCommentsRoot();
|
|
||||||
void refreshRootView();
|
void refreshRootView();
|
||||||
void setupDragArea();
|
void setupDragArea();
|
||||||
void sendReadTillRequest();
|
void sendReadTillRequest();
|
||||||
|
@ -184,7 +183,6 @@ private:
|
||||||
[[nodiscard]] SendMenu::Type sendMenuType() const;
|
[[nodiscard]] SendMenu::Type sendMenuType() const;
|
||||||
[[nodiscard]] MsgId replyToId() const;
|
[[nodiscard]] MsgId replyToId() const;
|
||||||
[[nodiscard]] HistoryItem *lookupRoot() const;
|
[[nodiscard]] HistoryItem *lookupRoot() const;
|
||||||
[[nodiscard]] HistoryItem *lookupCommentsRoot() const;
|
|
||||||
[[nodiscard]] bool computeAreComments() const;
|
[[nodiscard]] bool computeAreComments() const;
|
||||||
|
|
||||||
void pushReplyReturn(not_null<HistoryItem*> item);
|
void pushReplyReturn(not_null<HistoryItem*> item);
|
||||||
|
@ -235,7 +233,6 @@ private:
|
||||||
const not_null<History*> _history;
|
const not_null<History*> _history;
|
||||||
const MsgId _rootId = 0;
|
const MsgId _rootId = 0;
|
||||||
HistoryItem *_root = nullptr;
|
HistoryItem *_root = nullptr;
|
||||||
HistoryItem *_commentsRoot = nullptr;
|
|
||||||
std::shared_ptr<Data::RepliesList> _replies;
|
std::shared_ptr<Data::RepliesList> _replies;
|
||||||
rpl::variable<bool> _areComments = false;
|
rpl::variable<bool> _areComments = false;
|
||||||
QPointer<ListWidget> _inner;
|
QPointer<ListWidget> _inner;
|
||||||
|
|
|
@ -145,14 +145,26 @@ void SessionNavigation::showRepliesForMessage(
|
||||||
item = group->items.front();
|
item = group->items.front();
|
||||||
}
|
}
|
||||||
if (item) {
|
if (item) {
|
||||||
|
if (const auto maxId = data.vmax_id()) {
|
||||||
|
item->setRepliesMaxId(maxId->v);
|
||||||
|
}
|
||||||
|
if (const auto readTill = data.vread_inbox_max_id()) {
|
||||||
|
item->setRepliesInboxReadTill(readTill->v);
|
||||||
|
}
|
||||||
|
if (const auto readTill = data.vread_outbox_max_id()) {
|
||||||
|
item->setRepliesOutboxReadTill(readTill->v);
|
||||||
|
}
|
||||||
const auto post = _session->data().message(channelId, rootId);
|
const auto post = _session->data().message(channelId, rootId);
|
||||||
if (post) {
|
if (post) {
|
||||||
post->setCommentsItemId(item->fullId());
|
post->setCommentsItemId(item->fullId());
|
||||||
if (const auto maxId = data.vmax_id()) {
|
if (const auto maxId = data.vmax_id()) {
|
||||||
post->setCommentsMaxId(maxId->v);
|
post->setRepliesMaxId(maxId->v);
|
||||||
}
|
}
|
||||||
if (const auto readTill = data.vread_inbox_max_id()) {
|
if (const auto readTill = data.vread_inbox_max_id()) {
|
||||||
post->setCommentsReadTill(readTill->v);
|
post->setRepliesInboxReadTill(readTill->v);
|
||||||
|
}
|
||||||
|
if (const auto readTill = data.vread_outbox_max_id()) {
|
||||||
|
post->setRepliesOutboxReadTill(readTill->v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
showSection(
|
showSection(
|
||||||
|
|
Loading…
Add table
Reference in a new issue