Support unread reactions in monoforums.

This commit is contained in:
John Preston 2025-05-30 21:10:18 +04:00
parent 6068678fa1
commit ffe6786ad1
11 changed files with 61 additions and 22 deletions

View file

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_peer.h"
#include "data/data_channel.h"
#include "data/data_forum_topic.h"
#include "data/data_saved_sublist.h"
#include "data/data_session.h"
#include "main/main_session.h"
#include "history/history.h"
@ -31,7 +32,9 @@ UnreadThings::UnreadThings(not_null<ApiWrap*> api) : _api(api) {
bool UnreadThings::trackMentions(Data::Thread *thread) const {
const auto peer = thread ? thread->peer().get() : nullptr;
return peer && (peer->isChat() || peer->isMegagroup());
return peer
&& (peer->isChat() || peer->isMegagroup())
&& !peer->isMonoforum();
}
bool UnreadThings::trackReactions(Data::Thread *thread) const {
@ -93,7 +96,7 @@ void UnreadThings::cancelRequests(not_null<Data::Thread*> thread) {
void UnreadThings::requestMentions(
not_null<Data::Thread*> thread,
int loaded) {
if (_mentionsRequests.contains(thread)) {
if (_mentionsRequests.contains(thread) || thread->asSublist()) {
return;
}
const auto offsetId = std::max(
@ -138,13 +141,15 @@ void UnreadThings::requestReactions(
const auto maxId = 0;
const auto minId = 0;
const auto history = thread->owningHistory();
const auto sublist = thread->asSublist();
const auto topic = thread->asTopic();
using Flag = MTPmessages_GetUnreadReactions::Flag;
const auto requestId = _api->request(MTPmessages_GetUnreadReactions(
MTP_flags(topic ? Flag::f_top_msg_id : Flag()),
MTP_flags((topic ? Flag::f_top_msg_id : Flag())
| (sublist ? Flag::f_saved_peer_id : Flag())),
history->peer->input,
MTP_int(topic ? topic->rootId() : 0),
MTPInputPeer(), // saved_peer_id
(sublist ? sublist->sublistPeer()->input : MTPInputPeer()),
MTP_int(offsetId),
MTP_int(addOffset),
MTP_int(limit),

View file

@ -128,6 +128,12 @@ void SavedMessages::loadMore() {
_loadMore.call();
}
void SavedMessages::clearAllUnreadReactions() {
for (const auto &[peer, sublist] : _sublists) {
sublist->unreadReactions().clear();
}
}
void SavedMessages::sendLoadMore() {
if (_loadMoreRequestId || _chatsList.loaded()) {
return;

View file

@ -47,6 +47,7 @@ public:
void preloadSublists();
void loadMore();
void clearAllUnreadReactions();
void apply(const MTPDupdatePinnedSavedDialogs &update);
void apply(const MTPDupdateSavedDialogPinned &update);

View file

@ -725,6 +725,7 @@ void SavedSublist::applyMonoforumDialog(
data.vread_inbox_max_id().v,
data.vunread_count().v);
setOutboxReadTill(data.vread_outbox_max_id().v);
unreadReactions().setCount(data.vunread_reactions_count().v);
setUnreadMark(data.is_unread_mark());
applyMaybeLast(topItem);
}

View file

@ -836,11 +836,19 @@ void History::clearUnreadMentionsFor(MsgId topicRootId) {
}
}
void History::clearUnreadReactionsFor(MsgId topicRootId) {
void History::clearUnreadReactionsFor(
MsgId topicRootId,
Data::SavedSublist *sublist) {
const auto forum = peer->forum();
if (!topicRootId) {
const auto monoforum = peer->monoforum();
const auto sublistPeerId = sublist ? sublist->sublistPeer()->id : 0;
if ((!topicRootId && !sublist)
|| (!topicRootId && forum)
|| (!sublist && monoforum)) {
if (forum) {
forum->clearAllUnreadReactions();
} else if (monoforum) {
monoforum->clearAllUnreadReactions();
}
unreadReactions().clear();
return;
@ -848,6 +856,8 @@ void History::clearUnreadReactionsFor(MsgId topicRootId) {
if (const auto topic = forum->topicFor(topicRootId)) {
topic->unreadReactions().clear();
}
} else if (monoforum) {
sublist->unreadReactions().clear();
}
const auto &ids = unreadReactionsIds();
if (ids.empty()) {
@ -859,7 +869,8 @@ void History::clearUnreadReactionsFor(MsgId topicRootId) {
items.reserve(ids.size());
for (const auto &id : ids) {
if (const auto item = owner->message(peerId, id)) {
if (item->topicRootId() == topicRootId) {
if ((topicRootId && item->topicRootId() == topicRootId)
|| (sublist && item->sublistPeerId() == sublistPeerId)) {
items.emplace(id);
}
}

View file

@ -284,7 +284,9 @@ public:
void clearLastKeyboard();
void clearUnreadMentionsFor(MsgId topicRootId);
void clearUnreadReactionsFor(MsgId topicRootId);
void clearUnreadReactionsFor(
MsgId topicRootId,
Data::SavedSublist *sublist);
Data::Draft *draft(Data::DraftKey key) const;
void setDraft(Data::DraftKey key, std::unique_ptr<Data::Draft> &&draft);

View file

@ -1476,6 +1476,9 @@ void HistoryItem::markReactionsRead() {
if (const auto topic = this->topic()) {
topic->updateChatListEntry();
topic->unreadReactions().erase(id);
} else if (const auto sublist = this->savedSublist()) {
sublist->updateChatListEntry();
sublist->unreadReactions().erase(id);
}
}
@ -2195,6 +2198,8 @@ void HistoryItem::destroyHistoryEntry() {
history()->unreadReactions().erase(id);
if (const auto topic = this->topic()) {
topic->unreadReactions().erase(id);
} else if (const auto sublist = this->savedSublist()) {
sublist->unreadReactions().erase(id);
}
}
if (isRegular() && _history->peer->isMegagroup()) {

View file

@ -2198,7 +2198,7 @@ void ChatWidget::cornerButtonsShowAtPosition(
Data::Thread *ChatWidget::cornerButtonsThread() {
return _sublist
? nullptr
? static_cast<Data::Thread*>(_sublist)
: _topic
? static_cast<Data::Thread*>(_topic)
: _history;
@ -2233,7 +2233,9 @@ bool ChatWidget::cornerButtonsUnreadMayBeShown() {
}
bool ChatWidget::cornerButtonsHas(CornerButtonType type) {
return _topic || (type == CornerButtonType::Down);
return _topic
|| (_sublist && type == CornerButtonType::Reactions)
|| (type == CornerButtonType::Down);
}
void ChatWidget::showAtStart() {

View file

@ -45,6 +45,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_forum.h"
#include "data/data_forum_topic.h"
#include "data/data_message_reactions.h"
#include "data/data_saved_sublist.h"
#include "data/data_session.h"
#include "main/main_session.h"
#include "apiwrap.h"
@ -924,14 +925,16 @@ void SetupUnreadReactionsMenu(
return;
}
const auto topic = thread->asTopic();
const auto sublist = thread->asSublist();
const auto peer = thread->peer();
const auto rootId = topic ? topic->rootId() : 0;
using Flag = MTPmessages_ReadReactions::Flag;
peer->session().api().request(MTPmessages_ReadReactions(
MTP_flags(rootId ? Flag::f_top_msg_id : Flag(0)),
MTP_flags((rootId ? Flag::f_top_msg_id : Flag(0))
| (sublist ? Flag::f_saved_peer_id : Flag(0))),
peer->input,
MTP_int(rootId),
MTPInputPeer() // saved_peer_id
sublist ? sublist->sublistPeer()->input : MTPInputPeer()
)).done([=](const MTPmessages_AffectedHistory &result) {
const auto offset = peer->session().api().applyAffectedHistory(
peer,
@ -940,7 +943,9 @@ void SetupUnreadReactionsMenu(
resend(weakThread, done, resend);
} else {
done();
peer->owner().history(peer)->clearUnreadReactionsFor(rootId);
peer->owner().history(peer)->clearUnreadReactionsFor(
rootId,
sublist);
}
}).fail(done).send();
};

View file

@ -1167,6 +1167,9 @@ Window::SessionController *Manager::openNotificationMessage(
&& item->isRegular()
&& (item->out() || (item->mentionsMe() && !history->peer->isUser()));
const auto topic = item ? item->topic() : nullptr;
const auto sublist = (item && item->history()->amMonoforumAdmin())
? item->savedSublist()
: nullptr;
const auto guard = gsl::finally([&] {
if (topic) {
@ -1223,13 +1226,9 @@ Window::SessionController *Manager::openNotificationMessage(
if (window) {
window->widget()->showFromTray();
if (topic) {
using namespace HistoryView;
window->showSection(
std::make_shared<ChatMemento>(ChatViewId{
.history = history,
.repliesRootId = topic->rootId(),
}, itemId),
SectionShow::Way::Forward);
window->showTopic(topic, itemId, SectionShow::Way::Forward);
} else if (sublist) {
window->showSublist(sublist, itemId, SectionShow::Way::Forward);
} else {
window->showPeerHistory(
history->peer->id,

View file

@ -3090,12 +3090,14 @@ void UnpinAllMessages(
const auto sendRequest = [=](auto self) -> void {
const auto history = strong->owningHistory();
const auto topicRootId = strong->topicRootId();
const auto sublist = strong->asSublist();
using Flag = MTPmessages_UnpinAllMessages::Flag;
api->request(MTPmessages_UnpinAllMessages(
MTP_flags(topicRootId ? Flag::f_top_msg_id : Flag()),
MTP_flags((topicRootId ? Flag::f_top_msg_id : Flag())
| (sublist ? Flag::f_saved_peer_id : Flag())),
history->peer->input,
MTP_int(topicRootId.bare),
MTPInputPeer() // saved_peer_id
sublist ? sublist->sublistPeer()->input : MTPInputPeer()
)).done([=](const MTPmessages_AffectedHistory &result) {
const auto peer = history->peer;
const auto offset = api->applyAffectedHistory(peer, result);