diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 873fc58b3a..4f8cef0a22 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -2978,17 +2978,27 @@ void ApiWrap::resolveJumpToDate( Fn, MsgId)> callback) { if (const auto peer = chat.peer()) { const auto topic = chat.topic(); - const auto rootId = topic ? topic->rootId() : 0; - resolveJumpToHistoryDate(peer, rootId, date, std::move(callback)); + const auto sublist = chat.sublist(); + const auto rootId = topic ? topic->rootId() : MsgId(); + const auto monoforumPeerId = sublist + ? sublist->sublistPeer()->id + : PeerId(); + resolveJumpToHistoryDate( + peer, + rootId, + monoforumPeerId, + date, + std::move(callback)); } } template void ApiWrap::requestMessageAfterDate( - not_null peer, - MsgId topicRootId, - const QDate &date, - Callback &&callback) { + not_null peer, + MsgId topicRootId, + PeerId monoforumPeerId, + const QDate &date, + Callback &&callback) { // API returns a message with date <= offset_date. // So we request a message with offset_date = desired_date - 1 and add_offset = -1. // This should give us the first message with date >= desired_date. @@ -3011,7 +3021,7 @@ void ApiWrap::requestMessageAfterDate( return &messages.vmessages().v; }; const auto list = result.match([&]( - const MTPDmessages_messages &data) { + const MTPDmessages_messages &data) { return handleMessages(data); }, [&](const MTPDmessages_messagesSlice &data) { return handleMessages(data); @@ -3054,6 +3064,18 @@ void ApiWrap::requestMessageAfterDate( MTP_int(maxId), MTP_int(minId), MTP_long(historyHash))); + } else if (monoforumPeerId) { + send(MTPmessages_GetSavedHistory( + MTP_flags(MTPmessages_GetSavedHistory::Flag::f_parent_peer), + peer->input, + session().data().peer(monoforumPeerId)->input, + MTP_int(offsetId), + MTP_int(offsetDate), + MTP_int(addOffset), + MTP_int(limit), + MTP_int(maxId), + MTP_int(minId), + MTP_long(historyHash))); } else { send(MTPmessages_GetHistory( peer->input, @@ -3070,28 +3092,41 @@ void ApiWrap::requestMessageAfterDate( void ApiWrap::resolveJumpToHistoryDate( not_null peer, MsgId topicRootId, + PeerId monoforumPeerId, const QDate &date, Fn, MsgId)> callback) { if (const auto channel = peer->migrateTo()) { return resolveJumpToHistoryDate( channel, topicRootId, + monoforumPeerId, date, std::move(callback)); } const auto jumpToDateInPeer = [=] { - requestMessageAfterDate(peer, topicRootId, date, [=](MsgId itemId) { - callback(peer, itemId); - }); + requestMessageAfterDate( + peer, + topicRootId, + monoforumPeerId, + date, + [=](MsgId itemId) { callback(peer, itemId); }); }; - if (const auto chat = topicRootId ? nullptr : peer->migrateFrom()) { - requestMessageAfterDate(chat, 0, date, [=](MsgId itemId) { - if (itemId) { - callback(chat, itemId); - } else { - jumpToDateInPeer(); - } - }); + const auto migrated = (topicRootId || monoforumPeerId) + ? nullptr + : peer->migrateFrom(); + if (migrated) { + requestMessageAfterDate( + migrated, + MsgId(), + PeerId(), + date, + [=](MsgId itemId) { + if (itemId) { + callback(migrated, itemId); + } else { + jumpToDateInPeer(); + } + }); } else { jumpToDateInPeer(); } @@ -3140,12 +3175,14 @@ void ApiWrap::requestHistory( void ApiWrap::requestSharedMedia( not_null peer, MsgId topicRootId, + PeerId monoforumPeerId, SharedMediaType type, MsgId messageId, SliceType slice) { const auto key = SharedMediaRequest{ peer, topicRootId, + monoforumPeerId, type, messageId, slice, @@ -3157,6 +3194,7 @@ void ApiWrap::requestSharedMedia( const auto prepared = Api::PrepareSearchRequest( peer, topicRootId, + monoforumPeerId, type, QString(), messageId, @@ -3179,7 +3217,12 @@ void ApiWrap::requestSharedMedia( messageId, slice, result); - sharedMediaDone(peer, topicRootId, type, std::move(parsed)); + sharedMediaDone( + peer, + topicRootId, + monoforumPeerId, + type, + std::move(parsed)); finish(); }).fail([=] { _sharedMediaRequests.remove(key); @@ -3192,16 +3235,19 @@ void ApiWrap::requestSharedMedia( void ApiWrap::sharedMediaDone( not_null peer, MsgId topicRootId, + PeerId monoforumPeerId, SharedMediaType type, Api::SearchResult &&parsed) { const auto topic = peer->forumTopicFor(topicRootId); - if (topicRootId && !topic) { + const auto sublist = peer->monoforumSublistFor(monoforumPeerId); + if ((topicRootId && !topic) || (monoforumPeerId && !sublist)) { return; } const auto hasMessages = !parsed.messageIds.empty(); _session->storage().add(Storage::SharedMediaAddSlice( peer->id, topicRootId, + monoforumPeerId, type, std::move(parsed.messageIds), parsed.noSkipRange, @@ -3212,6 +3258,9 @@ void ApiWrap::sharedMediaDone( if (topic) { topic->setHasPinnedMessages(true); } + if (sublist) { + sublist->setHasPinnedMessages(true); + } } } @@ -3245,16 +3294,12 @@ void ApiWrap::sendAction(const SendAction &action) { && !action.options.shortcutId && !action.replaceMediaOf) { const auto topicRootId = action.replyTo.topicRootId; - const auto monoforumPeerId = action.replyTo.monoforumPeerId; const auto topic = topicRootId ? action.history->peer->forumTopicFor(topicRootId) : nullptr; - const auto monoforum = monoforumPeerId - ? action.history->peer->monoforum() - : nullptr; - const auto sublist = monoforum - ? monoforum->sublistLoaded( - action.history->owner().peer(monoforumPeerId)) + const auto monoforumPeerId = action.replyTo.monoforumPeerId; + const auto sublist = monoforumPeerId + ? action.history->peer->monoforumSublistFor(monoforumPeerId) : nullptr; if (topic) { topic->readTillEnd(); diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index a4835adbae..cb6ed34c2d 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -289,6 +289,7 @@ public: void requestSharedMedia( not_null peer, MsgId topicRootId, + PeerId monoforumPeerId, Storage::SharedMediaType type, MsgId messageId, SliceType slice); @@ -505,18 +506,21 @@ private: void resolveJumpToHistoryDate( not_null peer, MsgId topicRootId, + PeerId monoforumPeerId, const QDate &date, Fn, MsgId)> callback); template void requestMessageAfterDate( not_null peer, MsgId topicRootId, + PeerId monoforumPeerId, const QDate &date, Callback &&callback); void sharedMediaDone( not_null peer, MsgId topicRootId, + PeerId monoforumPeerId, SharedMediaType type, Api::SearchResult &&parsed); void globalMediaDone( @@ -665,6 +669,7 @@ private: struct SharedMediaRequest { not_null peer; MsgId topicRootId = 0; + PeerId monoforumPeerId = 0; SharedMediaType mediaType = {}; MsgId aroundId = 0; SliceType sliceType = {}; diff --git a/Telegram/SourceFiles/boxes/pin_messages_box.cpp b/Telegram/SourceFiles/boxes/pin_messages_box.cpp index 163e9dedc6..07d041a7d1 100644 --- a/Telegram/SourceFiles/boxes/pin_messages_box.cpp +++ b/Telegram/SourceFiles/boxes/pin_messages_box.cpp @@ -24,10 +24,15 @@ namespace { [[nodiscard]] bool IsOldForPin( MsgId id, not_null peer, - MsgId topicRootId) { + MsgId topicRootId, + PeerId monoforumPeerId) { const auto normal = peer->migrateToOrMe(); const auto migrated = normal->migrateFrom(); - const auto top = Data::ResolveTopPinnedId(normal, topicRootId, migrated); + const auto top = Data::ResolveTopPinnedId( + normal, + topicRootId, + monoforumPeerId, + migrated); if (!top) { return false; } else if (peer == migrated) { @@ -53,7 +58,14 @@ void PinMessageBox( const auto peer = item->history()->peer; const auto msgId = item->id; const auto topicRootId = item->topic() ? item->topicRootId() : MsgId(); - const auto pinningOld = IsOldForPin(msgId, peer, topicRootId); + const auto monoforumPeerId = item->history()->peer->amMonoforumAdmin() + ? item->sublistPeerId() + : PeerId(); + const auto pinningOld = IsOldForPin( + msgId, + peer, + topicRootId, + monoforumPeerId); const auto state = box->lifetime().make_state(); const auto api = box->lifetime().make_state( &peer->session().mtp()); diff --git a/Telegram/SourceFiles/core/local_url_handlers.cpp b/Telegram/SourceFiles/core/local_url_handlers.cpp index 832276e05f..64e33b14ca 100644 --- a/Telegram/SourceFiles/core/local_url_handlers.cpp +++ b/Telegram/SourceFiles/core/local_url_handlers.cpp @@ -847,6 +847,7 @@ bool OpenMediaTimestamp( document, context, context ? context->topicRootId() : MsgId(0), + context ? context->sublistPeerId() : PeerId(0), false, time)); } else if (document->isSong() || document->isVoiceMessage()) { diff --git a/Telegram/SourceFiles/data/data_document_resolver.cpp b/Telegram/SourceFiles/data/data_document_resolver.cpp index 4c901daa24..13b30f0bd2 100644 --- a/Telegram/SourceFiles/data/data_document_resolver.cpp +++ b/Telegram/SourceFiles/data/data_document_resolver.cpp @@ -187,7 +187,8 @@ void ResolveDocument( Window::SessionController *controller, not_null document, HistoryItem *item, - MsgId topicRootId) { + MsgId topicRootId, + PeerId monoforumPeerId) { if (document->isNull()) { return; } @@ -202,7 +203,7 @@ void ResolveDocument( controller->openDocument( document, true, - { msgId, topicRootId }); + { msgId, topicRootId, monoforumPeerId }); } }; diff --git a/Telegram/SourceFiles/data/data_document_resolver.h b/Telegram/SourceFiles/data/data_document_resolver.h index 4988297aaa..de9327312f 100644 --- a/Telegram/SourceFiles/data/data_document_resolver.h +++ b/Telegram/SourceFiles/data/data_document_resolver.h @@ -31,6 +31,7 @@ void ResolveDocument( Window::SessionController *controller, not_null document, HistoryItem *item, - MsgId topicRootId); + MsgId topicRootId, + PeerId monoforumPeerId); } // namespace Data diff --git a/Telegram/SourceFiles/data/data_forum.cpp b/Telegram/SourceFiles/data/data_forum.cpp index 921cd0ca15..ffc92a9847 100644 --- a/Telegram/SourceFiles/data/data_forum.cpp +++ b/Telegram/SourceFiles/data/data_forum.cpp @@ -72,7 +72,10 @@ Forum::~Forum() { auto &changes = session().changes(); const auto peerId = _history->peer->id; for (const auto &[rootId, topic] : _topics) { - storage.unload(Storage::SharedMediaUnloadThread(peerId, rootId)); + storage.unload(Storage::SharedMediaUnloadThread( + peerId, + rootId, + PeerId())); _history->setForwardDraft(rootId, PeerId(), {}); const auto raw = topic.get(); @@ -198,7 +201,8 @@ void Forum::applyTopicDeleted(MsgId rootId) { _history->destroyMessagesByTopic(rootId); session().storage().unload(Storage::SharedMediaUnloadThread( _history->peer->id, - rootId)); + rootId, + PeerId())); _history->setForwardDraft(rootId, PeerId(), {}); } diff --git a/Telegram/SourceFiles/data/data_history_messages.cpp b/Telegram/SourceFiles/data/data_history_messages.cpp index 5d5dffa30b..6711059297 100644 --- a/Telegram/SourceFiles/data/data_history_messages.cpp +++ b/Telegram/SourceFiles/data/data_history_messages.cpp @@ -152,6 +152,7 @@ rpl::producer HistoryMergedViewer( auto createSimpleViewer = [=]( PeerId peerId, MsgId topicRootId, + PeerId monoforumPeerId, SparseIdsSlice::Key simpleKey, int limitBefore, int limitAfter) { @@ -161,11 +162,10 @@ rpl::producer HistoryMergedViewer( return HistoryViewer(chosen, simpleKey, limitBefore, limitAfter); }; const auto peerId = history->peer->id; - const auto topicRootId = MsgId(); const auto migratedPeerId = migrateFrom ? migrateFrom->id : PeerId(0); using Key = SparseIdsMergedSlice::Key; return SparseIdsMergedSlice::CreateViewer( - Key(peerId, topicRootId, migratedPeerId, universalAroundId), + Key(peerId, MsgId(), PeerId(), migratedPeerId, universalAroundId), limitBefore, limitAfter, std::move(createSimpleViewer)); diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index 7af00bad92..8f639faf0f 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -1474,6 +1474,16 @@ Data::SavedMessages *PeerData::monoforum() const { return nullptr; } +Data::SavedSublist *PeerData::monoforumSublistFor( + PeerId sublistPeerId) const { + if (!sublistPeerId) { + return nullptr; + } else if (const auto monoforum = this->monoforum()) { + return monoforum->sublistLoaded(owner().peer(sublistPeerId)); + } + return nullptr; +} + bool PeerData::allowsForwarding() const { if (isUser()) { return true; @@ -1807,12 +1817,14 @@ void SetTopPinnedMessageId( session.settings().setHiddenPinnedMessageId( peer->id, MsgId(0), // topicRootId + PeerId(0), // monoforumPeerId 0); session.saveSettingsDelayed(); } session.storage().add(Storage::SharedMediaAddExisting( peer->id, MsgId(0), // topicRootId + PeerId(0), // monoforumPeerId Storage::SharedMediaType::Pinned, messageId, { messageId, ServerMaxMsgId })); @@ -1822,22 +1834,25 @@ void SetTopPinnedMessageId( FullMsgId ResolveTopPinnedId( not_null peer, MsgId topicRootId, + PeerId monoforumPeerId, PeerData *migrated) { const auto slice = peer->session().storage().snapshot( Storage::SharedMediaQuery( Storage::SharedMediaKey( peer->id, topicRootId, + monoforumPeerId, Storage::SharedMediaType::Pinned, ServerMaxMsgId - 1), 1, 1)); - const auto old = (!topicRootId && migrated) + const auto old = (!topicRootId && !monoforumPeerId && migrated) ? migrated->session().storage().snapshot( Storage::SharedMediaQuery( Storage::SharedMediaKey( migrated->id, MsgId(0), // topicRootId + PeerId(0), // monoforumPeerId Storage::SharedMediaType::Pinned, ServerMaxMsgId - 1), 1, @@ -1859,22 +1874,25 @@ FullMsgId ResolveTopPinnedId( FullMsgId ResolveMinPinnedId( not_null peer, MsgId topicRootId, + PeerId monoforumPeerId, PeerData *migrated) { const auto slice = peer->session().storage().snapshot( Storage::SharedMediaQuery( Storage::SharedMediaKey( peer->id, topicRootId, + monoforumPeerId, Storage::SharedMediaType::Pinned, 1), 1, 1)); - const auto old = (!topicRootId && migrated) + const auto old = (!topicRootId && !monoforumPeerId && migrated) ? migrated->session().storage().snapshot( Storage::SharedMediaQuery( Storage::SharedMediaKey( migrated->id, MsgId(0), // topicRootId + PeerId(0), // monoforumPeerId Storage::SharedMediaType::Pinned, 1), 1, diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h index 8de2297985..104e8ba10b 100644 --- a/Telegram/SourceFiles/data/data_peer.h +++ b/Telegram/SourceFiles/data/data_peer.h @@ -38,6 +38,7 @@ class ForumTopic; class Session; class GroupCall; class SavedMessages; +class SavedSublist; struct ReactionId; class WallPaper; @@ -260,6 +261,8 @@ public: [[nodiscard]] Data::ForumTopic *forumTopicFor(MsgId rootId) const; [[nodiscard]] Data::SavedMessages *monoforum() const; + [[nodiscard]] Data::SavedSublist *monoforumSublistFor( + PeerId sublistPeerId) const; [[nodiscard]] Data::PeerNotifySettings ¬ify() { return _notify; @@ -616,10 +619,12 @@ void SetTopPinnedMessageId( [[nodiscard]] FullMsgId ResolveTopPinnedId( not_null peer, MsgId topicRootId, + PeerId monoforumPeerId, PeerData *migrated = nullptr); [[nodiscard]] FullMsgId ResolveMinPinnedId( not_null peer, MsgId topicRootId, + PeerId monoforumPeerId, PeerData *migrated = nullptr); } // namespace Data diff --git a/Telegram/SourceFiles/data/data_saved_messages.cpp b/Telegram/SourceFiles/data/data_saved_messages.cpp index ae5d4e3218..ab3ac5f4eb 100644 --- a/Telegram/SourceFiles/data/data_saved_messages.cpp +++ b/Telegram/SourceFiles/data/data_saved_messages.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/application.h" #include "data/data_changes.h" #include "data/data_channel.h" +#include "data/data_histories.h" #include "data/data_user.h" #include "data/data_saved_sublist.h" #include "data/data_session.h" @@ -18,6 +19,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_item.h" #include "history/history_unread_things.h" #include "main/main_session.h" +#include "storage/storage_facade.h" +#include "storage/storage_shared_media.h" #include "window/notifications_manager.h" namespace Data { @@ -29,6 +32,7 @@ constexpr auto kListPerPage = 100; constexpr auto kListFirstPerPage = 20; constexpr auto kLoadedSublistsMinCount = 20; constexpr auto kShowSublistNamesCount = 5; +constexpr auto kStalePerRequest = 100; } // namespace @@ -50,16 +54,36 @@ SavedMessages::SavedMessages( } } -SavedMessages::~SavedMessages() { +void SavedMessages::clear() { + for (const auto &request : base::take(_sublistRequests)) { + if (request.second.id != _staleRequestId) { + owner().histories().cancelRequest(request.second.id); + } + } + if (const auto requestId = base::take(_staleRequestId)) { + session().api().request(requestId).cancel(); + } + + auto &storage = session().storage(); auto &changes = session().changes(); if (_owningHistory) { - for (const auto &[peer, sublist] : _sublists) { + for (const auto &[peer, sublist] : base::take(_sublists)) { + storage.unload(Storage::SharedMediaUnloadThread( + _owningHistory->peer->id, + MsgId(), + peer->id)); _owningHistory->setForwardDraft(MsgId(), peer->id, {}); const auto raw = sublist.get(); + changes.sublistRemoved(raw); changes.entryRemoved(raw); } } + _owningHistory = nullptr; +} + +SavedMessages::~SavedMessages() { + clear(); } bool SavedMessages::supported() const { @@ -108,6 +132,90 @@ SavedSublist *SavedMessages::sublistLoaded(not_null peer) { return (i != end(_sublists)) ? i->second.get() : nullptr; } +void SavedMessages::requestSomeStale() { + if (_staleRequestId + || (!_offset.id && _loadMoreRequestId) + || _stalePeers.empty() + || !_parentChat) { + return; + } + const auto type = Histories::RequestType::History; + auto peers = std::vector>(); + auto peerIds = QVector(); + peers.reserve(std::min(int(_stalePeers.size()), kStalePerRequest)); + peerIds.reserve(std::min(int(_stalePeers.size()), kStalePerRequest)); + for (auto i = begin(_stalePeers); i != end(_stalePeers);) { + const auto peer = *i; + i = _stalePeers.erase(i); + + peers.push_back(peer); + peerIds.push_back(peer->input); + if (peerIds.size() == kStalePerRequest) { + break; + } + } + if (peerIds.empty()) { + return; + } + const auto call = [=] { + for (const auto &peer : peers) { + finishSublistRequest(peer); + } + }; + auto &histories = owner().histories(); + _staleRequestId = histories.sendRequest(_owningHistory, type, [=]( + Fn finish) { + using Flag = MTPmessages_GetSavedDialogsByID::Flag; + return session().api().request( + MTPmessages_GetSavedDialogsByID( + MTP_flags(Flag::f_parent_peer), + _parentChat->input, + MTP_vector(peerIds)) + ).done([=](const MTPmessages_SavedDialogs &result) { + _staleRequestId = 0; + applyReceivedSublists(result); + call(); + finish(); + }).fail([=] { + _staleRequestId = 0; + call(); + finish(); + }).send(); + }); + for (const auto &peer : peers) { + _sublistRequests[peer].id = _staleRequestId; + } +} + +void SavedMessages::finishSublistRequest(not_null peer) { + if (const auto request = _sublistRequests.take(peer)) { + for (const auto &callback : request->callbacks) { + callback(); + } + } +} + +void SavedMessages::requestSublist( + not_null peer, + Fn done) { + if (!_parentChat) { + return; + } + auto &request = _sublistRequests[peer]; + if (done) { + request.callbacks.push_back(std::move(done)); + } + if (!request.id + && _stalePeers.emplace(peer).second + && (_stalePeers.size() == 1)) { + crl::on_main(&session(), [peer = _parentChat] { + if (const auto monoforum = peer->monoforum()) { + monoforum->requestSomeStale(); + } + }); + } +} + rpl::producer<> SavedMessages::chatsListChanges() const { return _chatsListChanges.events(); } @@ -146,18 +254,28 @@ void SavedMessages::sendLoadMore() { MTP_flags(Flag::f_exclude_pinned | (_parentChat ? Flag::f_parent_peer : Flag(0))), _parentChat ? _parentChat->input : MTPInputPeer(), - MTP_int(_offsetDate), - MTP_int(_offsetId), - _offsetPeer ? _offsetPeer->input : MTP_inputPeerEmpty(), - MTP_int(_offsetId ? kListPerPage : kListFirstPerPage), + MTP_int(_offset.date), + MTP_int(_offset.id), + _offset.peer ? _offset.peer->input : MTP_inputPeerEmpty(), + MTP_int(_offset.id ? kListPerPage : kListFirstPerPage), MTP_long(0)) // hash ).done([=](const MTPmessages_SavedDialogs &result) { - apply(result, false); + const auto applied = applyReceivedSublists(result); + if (applied.allLoaded || _offset == applied.offset) { + _chatsList.setLoaded(); + } else if (_offset.date > 0 && applied.offset.date > _offset.date) { + LOG(("API Error: Bad order in messages.savedDialogs.")); + _chatsList.setLoaded(); + } else { + _offset = applied.offset; + } + _loadMoreRequestId = 0; _chatsListChanges.fire({}); if (_chatsList.loaded()) { _chatsListLoadedEvents.fire({}); } reorderLastSublists(); + requestSomeStale(); }).fail([=](const MTP::Error &error) { if (error.type() == u"SAVED_DIALOGS_UNSUPPORTED"_q) { markUnsupported(); @@ -174,7 +292,9 @@ void SavedMessages::loadPinned() { _pinnedRequestId = _owner->session().api().request( MTPmessages_GetPinnedSavedDialogs() ).done([=](const MTPmessages_SavedDialogs &result) { - apply(result, true); + _pinnedRequestId = 0; + _pinnedLoaded = true; + applyReceivedSublists(result, true); _chatsListChanges.fire({}); }).fail([=](const MTP::Error &error) { if (error.type() == u"SAVED_DIALOGS_UNSUPPORTED"_q) { @@ -186,11 +306,11 @@ void SavedMessages::loadPinned() { }).send(); } -void SavedMessages::apply( - const MTPmessages_SavedDialogs &result, +SavedMessages::ApplyResult SavedMessages::applyReceivedSublists( + const MTPmessages_SavedDialogs &dialogs, bool pinned) { auto list = (const QVector*)nullptr; - result.match([](const MTPDmessages_savedDialogsNotModified &) { + dialogs.match([](const MTPDmessages_savedDialogsNotModified &) { LOG(("API Error: messages.savedDialogsNotModified.")); }, [&](const auto &data) { _owner->processUsers(data.vusers()); @@ -200,22 +320,11 @@ void SavedMessages::apply( NewMessageType::Existing); list = &data.vdialogs().v; }); - if (pinned) { - _pinnedRequestId = 0; - _pinnedLoaded = true; - } else { - _loadMoreRequestId = 0; - } if (!list) { - if (!pinned) { - _chatsList.setLoaded(); - } - return; + return { .allLoaded = true }; } auto lastValid = false; - auto offsetDate = TimeId(); - auto offsetId = MsgId(); - auto offsetPeer = (PeerData*)nullptr; + auto result = ApplyResult(); const auto parentPeerId = _parentChat ? _parentChat->id : _owner->session().userPeerId(); @@ -224,9 +333,9 @@ void SavedMessages::apply( const auto peer = _owner->peer(peerFromMTP(data.vpeer())); const auto topId = MsgId(data.vtop_message().v); if (const auto item = _owner->message(parentPeerId, topId)) { - offsetPeer = peer; - offsetDate = item->date(); - offsetId = topId; + result.offset.peer = peer; + result.offset.date = item->date(); + result.offset.id = topId; lastValid = true; const auto entry = sublist(peer); const auto entryPinned = pinned || data.is_pinned(); @@ -239,9 +348,9 @@ void SavedMessages::apply( const auto peer = _owner->peer(peerFromMTP(data.vpeer())); const auto topId = MsgId(data.vtop_message().v); if (const auto item = _owner->message(parentPeerId, topId)) { - offsetPeer = peer; - offsetDate = item->date(); - offsetId = topId; + result.offset.peer = peer; + result.offset.date = item->date(); + result.offset.id = topId; lastValid = true; sublist(peer)->applyMonoforumDialog(data, item); } else { @@ -252,20 +361,14 @@ void SavedMessages::apply( if (pinned) { } else if (!lastValid) { LOG(("API Error: Unknown message in the end of a slice.")); - _chatsList.setLoaded(); - } else if (result.type() == mtpc_messages_savedDialogs) { - _chatsList.setLoaded(); - } else if ((_offsetDate > 0 && offsetDate > _offsetDate) - || (offsetDate == _offsetDate - && offsetId == _offsetId - && offsetPeer == _offsetPeer)) { - LOG(("API Error: Bad order in messages.savedDialogs.")); - _chatsList.setLoaded(); - } else { - _offsetDate = offsetDate; - _offsetId = offsetId; - _offsetPeer = offsetPeer; + result.allLoaded = true; + } else if (dialogs.type() == mtpc_messages_savedDialogs) { + result.allLoaded = true; } + if (!_stalePeers.empty()) { + requestSomeStale(); + } + return result; } void SavedMessages::sendLoadMoreRequests() { @@ -324,7 +427,7 @@ void SavedMessages::applySublistDeleted(not_null sublistPeer) { return; } const auto raw = i->second.get(); - //Core::App().notifications().clearFromTopic(raw); // #TODO monoforum + Core::App().notifications().clearFromSublist(raw); owner().removeChatListEntry(raw); if (ranges::contains(_lastSublists, not_null(raw))) { @@ -342,9 +445,10 @@ void SavedMessages::applySublistDeleted(not_null sublistPeer) { const auto history = owningHistory(); history->destroyMessagesBySublist(sublistPeer); - //session().storage().unload(Storage::SharedMediaUnloadThread( - // _history->peer->id, - // rootId)); + session().storage().unload(Storage::SharedMediaUnloadThread( + _owningHistory->peer->id, + MsgId(), + sublistPeer->id)); history->setForwardDraft(MsgId(), sublistPeer->id, {}); } diff --git a/Telegram/SourceFiles/data/data_saved_messages.h b/Telegram/SourceFiles/data/data_saved_messages.h index 9b20b8920a..c7568326c5 100644 --- a/Telegram/SourceFiles/data/data_saved_messages.h +++ b/Telegram/SourceFiles/data/data_saved_messages.h @@ -18,6 +18,16 @@ namespace Data { class Session; class SavedSublist; +struct SavedMessagesOffsets { + TimeId date = 0; + MsgId id = 0; + PeerData *peer = nullptr; + + friend inline constexpr auto operator<=>( + SavedMessagesOffsets, + SavedMessagesOffsets) = default; +}; + class SavedMessages final { public: explicit SavedMessages( @@ -37,6 +47,7 @@ public: [[nodiscard]] not_null chatsList(); [[nodiscard]] not_null sublist(not_null peer); [[nodiscard]] SavedSublist *sublistLoaded(not_null peer); + void requestSublist(not_null peer, Fn done = nullptr); [[nodiscard]] rpl::producer<> chatsListChanges() const; [[nodiscard]] rpl::producer<> chatsListLoadedEvents() const; @@ -59,13 +70,31 @@ public: [[nodiscard]] auto recentSublists() const -> const std::vector> &; + void clear(); + [[nodiscard]] rpl::lifetime &lifetime(); private: + struct SublistRequest { + mtpRequestId id = 0; + std::vector> callbacks; + }; + struct ApplyResult { + SavedMessagesOffsets offset; + bool allLoaded = false; + }; + void loadPinned(); - void apply(const MTPmessages_SavedDialogs &result, bool pinned); + ApplyResult applyReceivedSublists( + const MTPmessages_SavedDialogs &result, + SavedMessagesOffsets &updateOffsets); + ApplyResult applyReceivedSublists( + const MTPmessages_SavedDialogs &result, + bool pinned = false); void reorderLastSublists(); + void requestSomeStale(); + void finishSublistRequest(not_null peer); void sendLoadMore(); void sendLoadMoreRequests(); @@ -80,13 +109,14 @@ private: base::flat_map< not_null, std::unique_ptr> _sublists; + base::flat_map, SublistRequest> _sublistRequests; + base::flat_set> _stalePeers; + mtpRequestId _staleRequestId = 0; mtpRequestId _loadMoreRequestId = 0; mtpRequestId _pinnedRequestId = 0; - TimeId _offsetDate = 0; - MsgId _offsetId = 0; - PeerData *_offsetPeer = nullptr; + SavedMessagesOffsets _offset; SingleQueuedInvokation _loadMore; bool _loadMoreScheduled = false; diff --git a/Telegram/SourceFiles/data/data_saved_sublist.cpp b/Telegram/SourceFiles/data/data_saved_sublist.cpp index 50f75e051b..ce0a3f4147 100644 --- a/Telegram/SourceFiles/data/data_saved_sublist.cpp +++ b/Telegram/SourceFiles/data/data_saved_sublist.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_saved_sublist.h" #include "apiwrap.h" +#include "core/application.h" #include "data/data_changes.h" #include "data/data_channel.h" #include "data/data_drafts.h" @@ -22,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_item.h" #include "history/history_unread_things.h" #include "main/main_session.h" +#include "window/notifications_manager.h" namespace Data { namespace { @@ -221,7 +223,7 @@ void SavedSublist::applyItemRemoved(MsgId id) { void SavedSublist::requestChatListMessage() { if (!chatListMessageKnown()) { - //forum()->requestTopic(_rootId); // #TODO monoforum + parent()->requestSublist(sublistPeer()); } } @@ -648,7 +650,7 @@ void SavedSublist::readTill( _readRequestTimer.callOnce(0); } } - // Core::App().notifications().clearIncomingFromSublist(this); // #TODO monoforum + Core::App().notifications().clearIncomingFromSublist(this); } void SavedSublist::sendReadTillRequest() { diff --git a/Telegram/SourceFiles/data/data_search_controller.cpp b/Telegram/SourceFiles/data/data_search_controller.cpp index 4a2418eb9d..6b43192805 100644 --- a/Telegram/SourceFiles/data/data_search_controller.cpp +++ b/Telegram/SourceFiles/data/data_search_controller.cpp @@ -132,6 +132,7 @@ GlobalMediaResult ParseGlobalMediaResult( std::optional PrepareSearchRequest( not_null peer, MsgId topicRootId, + PeerId monoforumPeerId, Storage::SharedMediaType type, const QString &query, MsgId messageId, @@ -168,11 +169,14 @@ std::optional PrepareSearchRequest( int64(0x3FFFFFFF))); using Flag = MTPmessages_Search::Flag; return MTPmessages_Search( - MTP_flags(topicRootId ? Flag::f_top_msg_id : Flag(0)), + MTP_flags((topicRootId ? Flag::f_top_msg_id : Flag(0)) + | (monoforumPeerId ? Flag::f_saved_peer_id : Flag(0))), peer->input, MTP_string(query), MTP_inputPeerEmpty(), - MTPInputPeer(), // saved_peer_id + (monoforumPeerId + ? peer->owner().peer(monoforumPeerId)->input + : MTPInputPeer()), MTPVector(), // saved_reaction MTP_int(topicRootId), filter, @@ -369,12 +373,14 @@ rpl::producer SearchController::idsSlice( auto createSimpleViewer = [=]( PeerId peerId, MsgId topicRootId, + PeerId monoforumPeerId, SparseIdsSlice::Key simpleKey, int limitBefore, int limitAfter) { return simpleIdsSlice( peerId, topicRootId, + monoforumPeerId, simpleKey, query, limitBefore, @@ -384,6 +390,7 @@ rpl::producer SearchController::idsSlice( SparseIdsMergedSlice::Key( query.peerId, query.topicRootId, + query.monoforumPeerId, query.migratedPeerId, aroundId), limitBefore, @@ -394,6 +401,7 @@ rpl::producer SearchController::idsSlice( rpl::producer SearchController::simpleIdsSlice( PeerId peerId, MsgId topicRootId, + PeerId monoforumPeerId, MsgId aroundId, const Query &query, int limitBefore, @@ -402,8 +410,12 @@ rpl::producer SearchController::simpleIdsSlice( Expects(IsServerMsgId(aroundId) || (aroundId == 0)); Expects((aroundId != 0) || (limitBefore == 0 && limitAfter == 0)); - Expects((query.peerId == peerId && query.topicRootId == topicRootId) - || (query.migratedPeerId == peerId && MsgId(0) == topicRootId)); + Expects((query.peerId == peerId + && query.topicRootId == topicRootId + && query.monoforumPeerId == monoforumPeerId) + || (query.migratedPeerId == peerId + && MsgId(0) == topicRootId + && PeerId(0) == monoforumPeerId)); auto it = _cache.find(query); if (it == _cache.end()) { @@ -437,7 +449,9 @@ rpl::producer SearchController::simpleIdsSlice( _session->data().itemRemoved( ) | rpl::filter([=](not_null item) { return (item->history()->peer->id == peerId) - && (!topicRootId || item->topicRootId() == topicRootId); + && (!topicRootId || item->topicRootId() == topicRootId) + && (!monoforumPeerId + || item->sublistPeerId() == monoforumPeerId); }) | rpl::filter([=](not_null item) { return builder->removeOne(item->id); }) | rpl::start_with_next(pushNextSnapshot, lifetime); @@ -510,6 +524,7 @@ void SearchController::requestMore( auto prepared = PrepareSearchRequest( listData->peer, query.topicRootId, + query.monoforumPeerId, query.type, query.query, key.aroundId, diff --git a/Telegram/SourceFiles/data/data_search_controller.h b/Telegram/SourceFiles/data/data_search_controller.h index c73fb7b390..e7fb3f8e9f 100644 --- a/Telegram/SourceFiles/data/data_search_controller.h +++ b/Telegram/SourceFiles/data/data_search_controller.h @@ -61,6 +61,7 @@ struct GlobalMediaResult { [[nodiscard]] std::optional PrepareSearchRequest( not_null peer, MsgId topicRootId, + PeerId monoforumPeerId, Storage::SharedMediaType type, const QString &query, MsgId messageId, @@ -92,6 +93,7 @@ public: PeerId peerId = 0; MsgId topicRootId = 0; + PeerId monoforumPeerId = 0; PeerId migratedPeerId = 0; MediaType type = MediaType::kCount; QString query; @@ -151,6 +153,7 @@ private: rpl::producer simpleIdsSlice( PeerId peerId, MsgId topicRootId, + PeerId monoforumPeerId, MsgId aroundId, const Query &query, int limitBefore, diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index f9a3127f56..292dffc405 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -404,6 +404,7 @@ void Session::clear() { channel->setFlags(channel->flags() & ~(ChannelDataFlag::Forum | ChannelDataFlag::MonoforumAdmin)); } + _savedMessages->clear(); _sendActionManager->clear(); diff --git a/Telegram/SourceFiles/data/data_shared_media.cpp b/Telegram/SourceFiles/data/data_shared_media.cpp index 6834190bf7..5e0c3735d2 100644 --- a/Telegram/SourceFiles/data/data_shared_media.cpp +++ b/Telegram/SourceFiles/data/data_shared_media.cpp @@ -110,11 +110,13 @@ rpl::producer SharedMediaViewer( auto requestMediaAround = [ peer = session->data().peer(key.peerId), topicRootId = key.topicRootId, + monoforumPeerId = key.monoforumPeerId, type = key.type ](const SparseIdsSliceBuilder::AroundData &data) { peer->session().api().requestSharedMedia( peer, topicRootId, + monoforumPeerId, type, data.aroundId, data.direction); @@ -131,6 +133,7 @@ rpl::producer SharedMediaViewer( ) | rpl::filter([=](const SliceUpdate &update) { return (update.peerId == key.peerId) && (update.topicRootId == key.topicRootId) + && (update.monoforumPeerId == key.monoforumPeerId) && (update.type == key.type); }) | rpl::filter([=](const SliceUpdate &update) { return builder->applyUpdate(update.data); @@ -151,6 +154,8 @@ rpl::producer SharedMediaViewer( return (update.peerId == key.peerId) && (!update.topicRootId || update.topicRootId == key.topicRootId) + && (!update.monoforumPeerId + || update.monoforumPeerId == key.monoforumPeerId) && update.types.test(key.type); }) | rpl::filter([=] { return builder->removeAll(); @@ -236,6 +241,7 @@ rpl::producer SharedMediaMergedViewer( auto createSimpleViewer = [=]( PeerId peerId, MsgId topicRootId, + PeerId monoforumPeerId, SparseIdsSlice::Key simpleKey, int limitBefore, int limitAfter) { @@ -244,6 +250,7 @@ rpl::producer SharedMediaMergedViewer( Storage::SharedMediaKey( peerId, topicRootId, + monoforumPeerId, key.type, simpleKey), limitBefore, diff --git a/Telegram/SourceFiles/data/data_shared_media.h b/Telegram/SourceFiles/data/data_shared_media.h index d9d2d8c63f..8f53b4026c 100644 --- a/Telegram/SourceFiles/data/data_shared_media.h +++ b/Telegram/SourceFiles/data/data_shared_media.h @@ -74,11 +74,13 @@ public: Key( PeerId peerId, MsgId topicRootId, + PeerId monoforumPeerId, PeerId migratedPeerId, Type type, UniversalMsgId universalId) : peerId(peerId) , topicRootId(topicRootId) + , monoforumPeerId(monoforumPeerId) , migratedPeerId(migratedPeerId) , type(type) , universalId(universalId) { @@ -91,6 +93,7 @@ public: PeerId peerId = 0; MsgId topicRootId = 0; + PeerId monoforumPeerId = 0; PeerId migratedPeerId = 0; Type type = Type::kCount; UniversalMsgId universalId; @@ -120,6 +123,7 @@ public: return { key.peerId, key.topicRootId, + key.monoforumPeerId, key.migratedPeerId, v::is(key.universalId) ? v::get(key.universalId) @@ -130,6 +134,7 @@ public: return { key.peerId, key.topicRootId, + key.monoforumPeerId, key.migratedPeerId, ServerMaxMsgId - 1 }; diff --git a/Telegram/SourceFiles/data/data_sparse_ids.cpp b/Telegram/SourceFiles/data/data_sparse_ids.cpp index b48881ca3a..787c0148a3 100644 --- a/Telegram/SourceFiles/data/data_sparse_ids.cpp +++ b/Telegram/SourceFiles/data/data_sparse_ids.cpp @@ -377,7 +377,10 @@ rpl::producer SparseIdsMergedSlice::CreateViewer( int limitBefore, int limitAfter, Fn simpleViewer) { - Expects(!key.topicRootId || !key.migratedPeerId); + Expects(!key.topicRootId + || (!key.monoforumPeerId && !key.migratedPeerId)); + Expects(!key.monoforumPeerId + || (!key.topicRootId && !key.migratedPeerId)); Expects(IsServerMsgId(key.universalId) || (key.universalId == 0) || (IsServerMsgId(ServerMaxMsgId + key.universalId) && key.migratedPeerId != 0)); @@ -388,6 +391,7 @@ rpl::producer SparseIdsMergedSlice::CreateViewer( auto partViewer = simpleViewer( key.peerId, key.topicRootId, + key.monoforumPeerId, SparseIdsMergedSlice::PartKey(key), limitBefore, limitAfter @@ -405,6 +409,7 @@ rpl::producer SparseIdsMergedSlice::CreateViewer( auto migratedViewer = simpleViewer( key.migratedPeerId, MsgId(0), // topicRootId + PeerId(0), // monoforumPeerId SparseIdsMergedSlice::MigratedKey(key), limitBefore, limitAfter); diff --git a/Telegram/SourceFiles/data/data_sparse_ids.h b/Telegram/SourceFiles/data/data_sparse_ids.h index 6b762e2dbe..3328ee5a40 100644 --- a/Telegram/SourceFiles/data/data_sparse_ids.h +++ b/Telegram/SourceFiles/data/data_sparse_ids.h @@ -33,11 +33,13 @@ public: Key( PeerId peerId, MsgId topicRootId, + PeerId monoforumPeerId, PeerId migratedPeerId, UniversalMsgId universalId) : peerId(peerId) , topicRootId(topicRootId) - , migratedPeerId(topicRootId ? 0 : migratedPeerId) + , monoforumPeerId(monoforumPeerId) + , migratedPeerId((topicRootId || monoforumPeerId) ? 0 : migratedPeerId) , universalId(universalId) { } @@ -47,6 +49,7 @@ public: PeerId peerId = 0; MsgId topicRootId = 0; + PeerId monoforumPeerId = 0; PeerId migratedPeerId = 0; UniversalMsgId universalId = 0; }; @@ -72,6 +75,7 @@ public: using SimpleViewerFunction = rpl::producer( PeerId peerId, MsgId topicRootId, + PeerId monoforumPeerId, SparseIdsSlice::Key simpleKey, int limitBefore, int limitAfter); diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 344bebd455..6eb211320a 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -1909,7 +1909,7 @@ RowDescriptor InnerWidget::computeChatPreviewRow() const { auto result = computeChosenRow(); if (const auto peer = result.key.peer()) { const auto topicId = _pressedTopicJump - ? _pressedTopicJumpRootId + ? _pressedTopicJumpRootId // #TODO monoforums : 0; if (const auto topic = peer->forumTopicFor(topicId)) { return { topic, FullMsgId() }; diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index bee130f501..8061df17fb 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -651,8 +651,38 @@ void History::destroyMessagesBySublist(not_null sublistPeer) { } } -void History::unpinMessagesFor(MsgId topicRootId) { - if (!topicRootId) { +void History::unpinMessagesFor(MsgId topicRootId, PeerId monoforumPeerId) { + if (topicRootId) { + session().storage().remove( + Storage::SharedMediaRemoveAll( + peer->id, + topicRootId, + Storage::SharedMediaType::Pinned)); + if (const auto topic = peer->forumTopicFor(topicRootId)) { + topic->setHasPinnedMessages(false); + } + for (const auto &item : _items) { + if (item->isPinned() && item->topicRootId() == topicRootId) { + item->setIsPinned(false); + } + } + } else if (monoforumPeerId) { + session().storage().remove( + Storage::SharedMediaRemoveAll( + peer->id, + monoforumPeerId, + Storage::SharedMediaType::Pinned)); + if (const auto sublist = peer->monoforumSublistFor( + monoforumPeerId)) { + sublist->setHasPinnedMessages(false); + } + for (const auto &item : _items) { + if (item->isPinned() + && item->sublistPeerId() == monoforumPeerId) { + item->setIsPinned(false); + } + } + } else { session().storage().remove( Storage::SharedMediaRemoveAll( peer->id, @@ -668,20 +698,6 @@ void History::unpinMessagesFor(MsgId topicRootId) { item->setIsPinned(false); } } - } else { - session().storage().remove( - Storage::SharedMediaRemoveAll( - peer->id, - topicRootId, - Storage::SharedMediaType::Pinned)); - if (const auto topic = peer->forumTopicFor(topicRootId)) { - topic->setHasPinnedMessages(false); - } - for (const auto &item : _items) { - if (item->isPinned() && item->topicRootId() == topicRootId) { - item->setIsPinned(false); - } - } } } @@ -898,6 +914,7 @@ not_null History::addNewToBack( storage.add(Storage::SharedMediaAddExisting( peer->id, MsgId(0), // topicRootId + PeerId(0), // monoforumPeerId types, item->id, { from, till })); @@ -909,6 +926,7 @@ not_null History::addNewToBack( storage.add(Storage::SharedMediaAddExisting( peer->id, topic->rootId(), + PeerId(), // monoforumPeerId types, item->id, { item->id, item->id})); @@ -916,6 +934,18 @@ not_null History::addNewToBack( topic->setHasPinnedMessages(true); } } + if (const auto sublist = item->savedSublist()) { + storage.add(Storage::SharedMediaAddExisting( + peer->id, + MsgId(), // topicRootId + item->sublistPeerId(), + types, + item->id, + { item->id, item->id })); + if (pinned) { + sublist->setHasPinnedMessages(true); + } + } } } if (item->from()->id) { @@ -1182,7 +1212,8 @@ void History::applyServiceChanges( if (id && item) { session().storage().add(Storage::SharedMediaAddSlice( peer->id, - MsgId(0), + MsgId(0), // topicRootId + PeerId(0), // monoforumPeerId Storage::SharedMediaType::Pinned, { id }, { id, ServerMaxMsgId })); @@ -1191,11 +1222,22 @@ void History::applyServiceChanges( session().storage().add(Storage::SharedMediaAddSlice( peer->id, topic->rootId(), + PeerId(), // monoforumPeerId Storage::SharedMediaType::Pinned, { id }, { id, ServerMaxMsgId })); topic->setHasPinnedMessages(true); } + if (const auto sublist = item->savedSublist()) { + session().storage().add(Storage::SharedMediaAddSlice( + peer->id, + MsgId(), // topicRootId + item->sublistPeerId(), + Storage::SharedMediaType::Pinned, + { id }, + { id, ServerMaxMsgId })); + sublist->setHasPinnedMessages(true); + } } }, [&](const MTPDmessageReplyStoryHeader &data) { LOG(("API Error: story reply in messageActionPinMessage.")); @@ -1470,6 +1512,7 @@ void History::addEdgesToSharedMedia() { session().storage().add(Storage::SharedMediaAddSlice( peer->id, MsgId(0), // topicRootId + PeerId(0), // monoforumPeerId type, {}, { from, till })); @@ -1683,6 +1726,7 @@ void History::addToSharedMedia( session().storage().add(Storage::SharedMediaAddSlice( peer->id, MsgId(0), // topicRootId + PeerId(0), // monoforumPeerId type, std::move(medias[i]), { from, till })); @@ -3162,11 +3206,9 @@ void History::forceFullResize() { Data::Thread *History::threadFor(MsgId topicRootId, PeerId monoforumPeerId) { return topicRootId ? peer->forumTopicFor(topicRootId) - : !monoforumPeerId - ? static_cast(this) - : peer->monoforum() - ? peer->monoforum()->sublistLoaded(owner().peer(monoforumPeerId)) - : nullptr; + : monoforumPeerId + ? peer->monoforumSublistFor(monoforumPeerId) + : static_cast(this); } const Data::Thread *History::threadFor( diff --git a/Telegram/SourceFiles/history/history.h b/Telegram/SourceFiles/history/history.h index 2bddc0eef0..cd6e707372 100644 --- a/Telegram/SourceFiles/history/history.h +++ b/Telegram/SourceFiles/history/history.h @@ -141,7 +141,7 @@ public: void destroyMessagesByTopic(MsgId topicRootId); void destroyMessagesBySublist(not_null sublistPeer); - void unpinMessagesFor(MsgId topicRootId); + void unpinMessagesFor(MsgId topicRootId, PeerId monoforumPeerId); not_null addNewMessage( MsgId id, diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 231a8d7a09..3daa1a5500 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -1513,6 +1513,7 @@ void HistoryItem::setIsPinned(bool pinned) { storage.add(Storage::SharedMediaAddExisting( _history->peer->id, MsgId(0), // topicRootId + PeerId(0), // monoforumPeerId Storage::SharedMediaType::Pinned, id, { id, id })); @@ -1521,11 +1522,22 @@ void HistoryItem::setIsPinned(bool pinned) { storage.add(Storage::SharedMediaAddExisting( _history->peer->id, topic->rootId(), + PeerId(), // monoforumPeerId Storage::SharedMediaType::Pinned, id, { id, id })); topic->setHasPinnedMessages(true); } + if (const auto sublist = this->savedSublist()) { + storage.add(Storage::SharedMediaAddExisting( + _history->peer->id, + MsgId(0), // topicRootId + sublistPeerId(), + Storage::SharedMediaType::Pinned, + id, + { id, id })); + sublist->setHasPinnedMessages(true); + } } else { _flags &= ~MessageFlag::Pinned; if (_flags & MessageFlag::StoryItem) { @@ -2238,6 +2250,7 @@ void HistoryItem::addToSharedMediaIndex() { _history->session().storage().add(Storage::SharedMediaAddNew( _history->peer->id, topicRootId(), + sublistPeerId(), types, id)); if (types.test(Storage::SharedMediaType::Pinned)) { @@ -2245,6 +2258,9 @@ void HistoryItem::addToSharedMediaIndex() { if (const auto topic = this->topic()) { topic->setHasPinnedMessages(true); } + if (const auto sublist = this->savedSublist()) { + sublist->setHasPinnedMessages(true); + } } } } diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 13119ca1cc..7d41300c38 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -6038,7 +6038,7 @@ bool HistoryWidget::showSendingFilesError( return true; } -MsgId HistoryWidget::resolveReplyToTopicRootId() { +MsgId HistoryWidget::resolveReplyToTopicRootId() { // #TODO monoforums Expects(_peer != nullptr); const auto replyToInfo = replyTo(); @@ -7601,6 +7601,7 @@ void HistoryWidget::updatePinnedViewer() { _minPinnedId = Data::ResolveMinPinnedId( _peer, MsgId(0), // topicRootId + PeerId(0), // monoforumPeerId _migrated ? _migrated->peer.get() : nullptr); } if (_pinnedClickedId @@ -7680,6 +7681,7 @@ void HistoryWidget::checkPinnedBarState() { const auto currentPinnedId = Data::ResolveTopPinnedId( _peer, MsgId(0), // topicRootId + PeerId(0), // monoforumPeerId _migrated ? _migrated->peer.get() : nullptr); const auto universalPinnedId = !currentPinnedId ? int32(0) @@ -7713,6 +7715,7 @@ void HistoryWidget::checkPinnedBarState() { auto pinnedRefreshed = Info::Profile::SharedMediaCountValue( _peer, MsgId(0), // topicRootId + PeerId(0), // monoforumPeerId nullptr, Storage::SharedMediaType::Pinned ) | rpl::distinct_until_changed( @@ -8593,6 +8596,7 @@ void HistoryWidget::hidePinnedMessage() { controller(), _peer, MsgId(0), // topicRootId + PeerId(0), // monoforumPeerId crl::guard(this, callback)); } } diff --git a/Telegram/SourceFiles/history/view/history_view_chat_section.cpp b/Telegram/SourceFiles/history/view/history_view_chat_section.cpp index 3d164d2946..39afe08693 100644 --- a/Telegram/SourceFiles/history/view/history_view_chat_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_chat_section.cpp @@ -151,7 +151,7 @@ void ChatMemento::setFromTopic(not_null topic) { } -Data::ForumTopic *ChatMemento::topicForRemoveRequests() const { +Data::ForumTopic *ChatMemento::topicForRemoveRequests() const {// #TODO monoforums return _id.repliesRootId ? _id.history->peer->forumTopicFor(_id.repliesRootId) : nullptr; @@ -233,6 +233,9 @@ ChatWidget::ChatWidget( , _topic(lookupTopic()) , _areComments(computeAreComments()) , _sublist(_id.sublist) +, _monoforumPeerId((_sublist && _sublist->parentChat()) + ? _sublist->sublistPeer()->id + : PeerId()) , _sendAction(_repliesRootId ? _history->owner().sendActionManager().repliesPainter( _history, @@ -772,7 +775,7 @@ void ChatWidget::setupComposeControls() { _composeControls->setHistory({ .history = _history.get(), .topicRootId = _topic ? _topic->rootId() : MsgId(), - .monoforumPeerId = _sublist ? _sublist->sublistPeer()->id : PeerId(), + .monoforumPeerId = _monoforumPeerId, .showSlowmodeError = [=] { return showSlowmodeError(); }, .sendActionFactory = [=] { return prepareSendAction({}); }, .slowmodeSecondsLeft = SlowmodeSecondsLeft(_peer), @@ -1781,20 +1784,17 @@ SendMenu::Details ChatWidget::sendMenuDetails() const { } FullReplyTo ChatWidget::replyTo() const { - const auto monoforumPeerId = (_sublist && _sublist->parentChat()) - ? _sublist->sublistPeer()->id - : PeerId(); if (auto custom = _composeControls->replyingToMessage()) { const auto item = custom.messageId ? session().data().message(custom.messageId) : nullptr; const auto sublistPeerId = item ? item->sublistPeerId() : PeerId(); if (!item - || !monoforumPeerId - || (sublistPeerId == monoforumPeerId)) { + || !_monoforumPeerId + || (sublistPeerId == _monoforumPeerId)) { // Never answer to a message in a wrong monoforum peer id. custom.topicRootId = _repliesRootId; - custom.monoforumPeerId = monoforumPeerId; + custom.monoforumPeerId = _monoforumPeerId; return custom; } } @@ -1803,7 +1803,7 @@ FullReplyTo ChatWidget::replyTo() const { ? FullMsgId(_peer->id, _repliesRootId) : FullMsgId()), .topicRootId = _repliesRootId, - .monoforumPeerId = monoforumPeerId, + .monoforumPeerId = _monoforumPeerId, }; } @@ -1850,7 +1850,10 @@ void ChatWidget::updatePinnedViewer() { _pinnedClickedId = FullMsgId(); } if (_pinnedClickedId && !_minPinnedId) { - _minPinnedId = Data::ResolveMinPinnedId(_peer, _repliesRootId); + _minPinnedId = Data::ResolveMinPinnedId( + _peer, + _repliesRootId, + _monoforumPeerId); } if (_pinnedClickedId && _minPinnedId && _minPinnedId >= _pinnedClickedId) { // After click on the last pinned message we should the top one. @@ -1955,6 +1958,7 @@ void ChatWidget::setupPinnedTracker() { Storage::SharedMediaKey( _topic->channel()->id, _repliesRootId, + _monoforumPeerId, Storage::SharedMediaType::Pinned, ServerMaxMsgId - 1), 1, @@ -1968,10 +1972,15 @@ void ChatWidget::setupPinnedTracker() { const auto peerId = _peer->id; const auto hiddenId = settings.hiddenPinnedMessageId( peerId, - _repliesRootId); + _repliesRootId, + _monoforumPeerId); const auto last = result.size() ? result[result.size() - 1] : 0; if (hiddenId && hiddenId != last) { - settings.setHiddenPinnedMessageId(peerId, _repliesRootId, 0); + settings.setHiddenPinnedMessageId( + peerId, + _repliesRootId, + _monoforumPeerId, + 0); _history->session().saveSettingsDelayed(); } } @@ -1987,10 +1996,12 @@ void ChatWidget::checkPinnedBarState() { ? MsgId(0) : _peer->session().settings().hiddenPinnedMessageId( _peer->id, - _repliesRootId); + _repliesRootId, + _monoforumPeerId); const auto currentPinnedId = Data::ResolveTopPinnedId( _peer, - _repliesRootId); + _repliesRootId, + _monoforumPeerId); const auto universalPinnedId = !currentPinnedId ? MsgId(0) : currentPinnedId.msg; @@ -2021,6 +2032,7 @@ void ChatWidget::checkPinnedBarState() { auto pinnedRefreshed = Info::Profile::SharedMediaCountValue( _peer, _repliesRootId, + _monoforumPeerId, nullptr, Storage::SharedMediaType::Pinned ) | rpl::distinct_until_changed( @@ -2187,6 +2199,7 @@ void ChatWidget::hidePinnedMessage() { controller(), _peer, _repliesRootId, + _monoforumPeerId, crl::guard(this, callback)); } } @@ -3193,7 +3206,9 @@ void ChatWidget::listShowPremiumToast(not_null document) { void ChatWidget::listOpenPhoto( not_null photo, FullMsgId context) { - controller()->openPhoto(photo, { context, _repliesRootId }); + controller()->openPhoto( + photo, + { context, _repliesRootId, _monoforumPeerId }); } void ChatWidget::listOpenDocument( @@ -3203,7 +3218,7 @@ void ChatWidget::listOpenDocument( controller()->openDocument( document, showInMediaView, - { context, _repliesRootId }); + { context, _repliesRootId, _monoforumPeerId }); } void ChatWidget::listPaintEmpty( diff --git a/Telegram/SourceFiles/history/view/history_view_chat_section.h b/Telegram/SourceFiles/history/view/history_view_chat_section.h index 52bc50f832..593553ce25 100644 --- a/Telegram/SourceFiles/history/view/history_view_chat_section.h +++ b/Telegram/SourceFiles/history/view/history_view_chat_section.h @@ -394,6 +394,7 @@ private: rpl::variable _areComments = false; Data::SavedSublist *_sublist = nullptr; + PeerId _monoforumPeerId; std::shared_ptr _sendAction; std::shared_ptr _theme; diff --git a/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp b/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp index b8c380c5c1..cf82e31e2b 100644 --- a/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_pinned_section.cpp @@ -195,6 +195,7 @@ void PinnedWidget::setupClearButton() { controller(), _history->peer, _thread->topicRootId(), + _thread->monoforumPeerId(), crl::guard(this, callback)); } else { Window::UnpinAllMessages(controller(), _thread); @@ -517,6 +518,7 @@ rpl::producer PinnedWidget::listSource( SparseIdsMergedSlice::Key( _history->peer->id, _thread->topicRootId(), + _thread->monoforumPeerId(), _migratedPeer ? _migratedPeer->id : 0, messageId), Storage::SharedMediaType::Pinned), diff --git a/Telegram/SourceFiles/history/view/history_view_pinned_tracker.cpp b/Telegram/SourceFiles/history/view/history_view_pinned_tracker.cpp index 24abaa03fe..fcc7226566 100644 --- a/Telegram/SourceFiles/history/view/history_view_pinned_tracker.cpp +++ b/Telegram/SourceFiles/history/view/history_view_pinned_tracker.cpp @@ -86,6 +86,7 @@ void PinnedTracker::refreshViewer() { SparseIdsMergedSlice::Key( peer->id, _thread->topicRootId(), + _thread->monoforumPeerId(), _migratedPeer ? _migratedPeer->id : 0, _viewerAroundId), Storage::SharedMediaType::Pinned), diff --git a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp index 3cb26ace66..9f7a8ac8be 100644 --- a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp @@ -751,7 +751,7 @@ void TopBarWidget::infoClicked() { _controller->showSection(std::make_shared(topic)); } else if (const auto sublist = key.sublist()) { _controller->showSection(std::make_shared( - sublist->owningHistory()->peer, + sublist, Info::Section(Storage::SharedMediaType::Photo))); } else if (key.peer()->savedSublistsInfo()) { _controller->showSection(std::make_shared( diff --git a/Telegram/SourceFiles/info/common_groups/info_common_groups_widget.cpp b/Telegram/SourceFiles/info/common_groups/info_common_groups_widget.cpp index f81019bb77..46ad5a394a 100644 --- a/Telegram/SourceFiles/info/common_groups/info_common_groups_widget.cpp +++ b/Telegram/SourceFiles/info/common_groups/info_common_groups_widget.cpp @@ -21,7 +21,7 @@ namespace Info { namespace CommonGroups { Memento::Memento(not_null user) -: ContentMemento(user, nullptr, PeerId()) { +: ContentMemento(user, nullptr, nullptr, PeerId()) { } Section Memento::section() const { diff --git a/Telegram/SourceFiles/info/info_content_widget.cpp b/Telegram/SourceFiles/info/info_content_widget.cpp index f392e132ed..efbfbdc14a 100644 --- a/Telegram/SourceFiles/info/info_content_widget.cpp +++ b/Telegram/SourceFiles/info/info_content_widget.cpp @@ -307,6 +307,7 @@ QRect ContentWidget::floatPlayerAvailableRect() const { void ContentWidget::fillTopBarMenu(const Ui::Menu::MenuCallback &addAction) { const auto peer = _controller->key().peer(); const auto topic = _controller->key().topic(); + const auto sublist = _controller->key().sublist(); if (!peer && !topic) { return; } @@ -316,6 +317,8 @@ void ContentWidget::fillTopBarMenu(const Ui::Menu::MenuCallback &addAction) { Dialogs::EntryState{ .key = (topic ? Dialogs::Key{ topic } + : sublist + ? Dialogs::Key{ sublist } : Dialogs::Key{ peer->owner().history(peer) }), .section = Dialogs::EntryState::Section::Profile, }, @@ -465,6 +468,8 @@ void ContentWidget::setupSwipeHandler(not_null widget) { Key ContentMemento::key() const { if (const auto topic = this->topic()) { return Key(topic); + } else if (const auto sublist = this->sublist()) { + return Key(sublist); } else if (const auto peer = this->peer()) { return Key(peer); } else if (const auto poll = this->poll()) { @@ -489,12 +494,14 @@ Key ContentMemento::key() const { ContentMemento::ContentMemento( not_null peer, Data::ForumTopic *topic, + Data::SavedSublist *sublist, PeerId migratedPeerId) : _peer(peer) -, _migratedPeerId((!topic && peer->migrateFrom()) +, _migratedPeerId((!topic && !sublist && peer->migrateFrom()) ? peer->migrateFrom()->id : 0) -, _topic(topic) { +, _topic(topic) +, _sublist(sublist) { if (_topic) { _peer->owner().itemIdChanged( ) | rpl::start_with_next([=](const Data::Session::IdChange &change) { diff --git a/Telegram/SourceFiles/info/info_content_widget.h b/Telegram/SourceFiles/info/info_content_widget.h index 359f46787a..29c376dfa4 100644 --- a/Telegram/SourceFiles/info/info_content_widget.h +++ b/Telegram/SourceFiles/info/info_content_widget.h @@ -210,6 +210,7 @@ public: ContentMemento( not_null peer, Data::ForumTopic *topic, + Data::SavedSublist *sublist, PeerId migratedPeerId); explicit ContentMemento(Settings::Tag settings); explicit ContentMemento(Downloads::Tag downloads); @@ -240,6 +241,9 @@ public: Data::ForumTopic *topic() const { return _topic; } + Data::SavedSublist *sublist() const { + return _sublist; + } UserData *settingsSelf() const { return _settingsSelf; } @@ -311,6 +315,7 @@ private: PeerData * const _peer = nullptr; const PeerId _migratedPeerId = 0; Data::ForumTopic *_topic = nullptr; + Data::SavedSublist *_sublist = nullptr; UserData * const _settingsSelf = nullptr; PeerData * const _storiesPeer = nullptr; Stories::Tab _storiesTab = {}; diff --git a/Telegram/SourceFiles/info/info_controller.cpp b/Telegram/SourceFiles/info/info_controller.cpp index b1ec130dc5..49054d63f1 100644 --- a/Telegram/SourceFiles/info/info_controller.cpp +++ b/Telegram/SourceFiles/info/info_controller.cpp @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/search_field_controller.h" #include "data/data_shared_media.h" +#include "history/history.h" #include "info/info_content_widget.h" #include "info/info_memento.h" #include "info/global_media/info_global_media_widget.h" @@ -20,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_chat.h" #include "data/data_forum_topic.h" #include "data/data_forum.h" +#include "data/data_saved_sublist.h" #include "data/data_session.h" #include "data/data_media_types.h" #include "data/data_download_manager.h" @@ -35,6 +37,9 @@ Key::Key(not_null peer) : _value(peer) { Key::Key(not_null topic) : _value(topic) { } +Key::Key(not_null sublist) : _value(sublist) { +} + Key::Key(Settings::Tag settings) : _value(settings) { } @@ -69,6 +74,8 @@ PeerData *Key::peer() const { return *peer; } else if (const auto topic = this->topic()) { return topic->channel(); + } else if (const auto sublist = this->sublist()) { + return sublist->owningHistory()->peer; } return nullptr; } @@ -81,6 +88,14 @@ Data::ForumTopic *Key::topic() const { return nullptr; } +Data::SavedSublist *Key::sublist() const { + if (const auto sublist = std::get_if>( + &_value)) { + return *sublist; + } + return nullptr; +} + UserData *Key::settingsSelf() const { if (const auto tag = std::get_if(&_value)) { return tag->self; @@ -195,6 +210,7 @@ rpl::producer AbstractController::mediaSource( SparseIdsMergedSlice::Key( peer()->id, topicId, + sublist() ? sublist()->sublistPeer()->id : PeerId(), migratedPeerId(), aroundId), section().mediaType()), @@ -487,6 +503,7 @@ rpl::producer Controller::mediaSource( SparseIdsMergedSlice::Key( query.peerId, query.topicRootId, + query.monoforumPeerId, query.migratedPeerId, aroundId), query.type), diff --git a/Telegram/SourceFiles/info/info_controller.h b/Telegram/SourceFiles/info/info_controller.h index c82a8b9f5a..5b29ac1ce6 100644 --- a/Telegram/SourceFiles/info/info_controller.h +++ b/Telegram/SourceFiles/info/info_controller.h @@ -18,6 +18,7 @@ struct WhoReadList; namespace Data { class ForumTopic; +class SavedSublist; } // namespace Data namespace Ui { @@ -94,6 +95,7 @@ class Key { public: explicit Key(not_null peer); explicit Key(not_null topic); + explicit Key(not_null sublist); Key(Settings::Tag settings); Key(Downloads::Tag downloads); Key(Stories::Tag stories); @@ -108,6 +110,7 @@ public: PeerData *peer() const; Data::ForumTopic *topic() const; + Data::SavedSublist *sublist() const; UserData *settingsSelf() const; bool isDownloads() const; bool isGlobalMedia() const; @@ -135,6 +138,7 @@ private: std::variant< not_null, not_null, + not_null, Settings::Tag, Downloads::Tag, Stories::Tag, @@ -225,6 +229,9 @@ public: [[nodiscard]] Data::ForumTopic *topic() const { return key().topic(); } + [[nodiscard]] Data::SavedSublist *sublist() const { + return key().sublist(); + } [[nodiscard]] UserData *settingsSelf() const { return key().settingsSelf(); } diff --git a/Telegram/SourceFiles/info/info_memento.cpp b/Telegram/SourceFiles/info/info_memento.cpp index 40f7733dd6..945bda8736 100644 --- a/Telegram/SourceFiles/info/info_memento.cpp +++ b/Telegram/SourceFiles/info/info_memento.cpp @@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_channel.h" #include "data/data_chat.h" #include "data/data_forum_topic.h" +#include "data/data_saved_sublist.h" #include "data/data_session.h" #include "main/main_session.h" @@ -48,6 +49,14 @@ Memento::Memento(not_null topic, Section section) : Memento(DefaultStack(topic, section)) { } +Memento::Memento(not_null sublist) +: Memento(sublist, Section::Type::Profile) { +} + +Memento::Memento(not_null sublist, Section section) +: Memento(DefaultStack(sublist, section)) { +} + Memento::Memento(Settings::Tag settings, Section section) : Memento(DefaultStack(settings, section)) { } @@ -66,9 +75,12 @@ Memento::Memento( Memento::Memento(std::vector> stack) : _stack(std::move(stack)) { auto topics = base::flat_set>(); + auto sublists = base::flat_set>(); for (auto &entry : _stack) { if (const auto topic = entry->topic()) { topics.emplace(topic); + } else if (const auto sublist = entry->sublist()) { + sublists.emplace(sublist); } } for (const auto &topic : topics) { @@ -86,6 +98,21 @@ Memento::Memento(std::vector> stack) } }, _lifetime); } + for (const auto &sublist : sublists) { + sublist->destroyed( + ) | rpl::start_with_next([=] { + for (auto i = begin(_stack); i != end(_stack);) { + if (i->get()->sublist() == sublist) { + i = _stack.erase(i); + } else { + ++i; + } + } + if (_stack.empty()) { + _removeRequests.fire({}); + } + }, _lifetime); + } } std::vector> Memento::DefaultStack( @@ -104,6 +131,14 @@ std::vector> Memento::DefaultStack( return result; } +std::vector> Memento::DefaultStack( + not_null sublist, + Section section) { + auto result = std::vector>(); + result.push_back(DefaultContent(sublist, section)); + return result; +} + std::vector> Memento::DefaultStack( Settings::Tag settings, Section section) { @@ -205,6 +240,20 @@ std::shared_ptr Memento::DefaultContent( Unexpected("Wrong section type in Info::Memento::DefaultContent()"); } +std::shared_ptr Memento::DefaultContent( + not_null sublist, + Section section) { + switch (section.type()) { + case Section::Type::Profile: + return std::make_shared(sublist); + case Section::Type::Media: + return std::make_shared( + sublist, + section.mediaType()); + } + Unexpected("Wrong section type in Info::Memento::DefaultContent()"); +} + object_ptr Memento::createWidget( QWidget *parent, not_null controller, diff --git a/Telegram/SourceFiles/info/info_memento.h b/Telegram/SourceFiles/info/info_memento.h index dc50f2f89c..fd0e5946aa 100644 --- a/Telegram/SourceFiles/info/info_memento.h +++ b/Telegram/SourceFiles/info/info_memento.h @@ -23,6 +23,7 @@ enum class SharedMediaType : signed char; namespace Data { class ForumTopic; +class SavedSublist; struct ReactionId; } // namespace Data @@ -49,6 +50,8 @@ public: Memento(not_null peer, Section section); explicit Memento(not_null topic); Memento(not_null topic, Section section); + explicit Memento(not_null sublist); + Memento(not_null sublist, Section section); Memento(Settings::Tag settings, Section section); Memento(not_null poll, FullMsgId contextId); Memento( @@ -94,6 +97,9 @@ private: static std::vector> DefaultStack( not_null topic, Section section); + static std::vector> DefaultStack( + not_null sublist, + Section section); static std::vector> DefaultStack( Settings::Tag settings, Section section); @@ -111,6 +117,9 @@ private: static std::shared_ptr DefaultContent( not_null topic, Section section); + static std::shared_ptr DefaultContent( + not_null sublist, + Section section); std::vector> _stack; rpl::event_stream<> _removeRequests; diff --git a/Telegram/SourceFiles/info/media/info_media_buttons.cpp b/Telegram/SourceFiles/info/media/info_media_buttons.cpp index 9d91702861..5a2b78e952 100644 --- a/Telegram/SourceFiles/info/media/info_media_buttons.cpp +++ b/Telegram/SourceFiles/info/media/info_media_buttons.cpp @@ -147,12 +147,18 @@ not_null AddButton( not_null navigation, not_null peer, MsgId topicRootId, + PeerId monoforumPeerId, PeerData *migrated, Type type, Ui::MultiSlideTracker &tracker) { auto result = AddCountedButton( parent, - Profile::SharedMediaCountValue(peer, topicRootId, migrated, type), + Profile::SharedMediaCountValue( + peer, + topicRootId, + monoforumPeerId, + migrated, + type), MediaText(type), tracker)->entity(); const auto separateId = SeparateId(peer, topicRootId, type); diff --git a/Telegram/SourceFiles/info/media/info_media_buttons.h b/Telegram/SourceFiles/info/media/info_media_buttons.h index e8927c0970..a8a24feb47 100644 --- a/Telegram/SourceFiles/info/media/info_media_buttons.h +++ b/Telegram/SourceFiles/info/media/info_media_buttons.h @@ -42,6 +42,7 @@ using Type = Storage::SharedMediaType; not_null navigation, not_null peer, MsgId topicRootId, + PeerId monoforumPeerId, PeerData *migrated, Type type, Ui::MultiSlideTracker &tracker); diff --git a/Telegram/SourceFiles/info/media/info_media_inner_widget.cpp b/Telegram/SourceFiles/info/media/info_media_inner_widget.cpp index 6f2bedac48..faccefcd74 100644 --- a/Telegram/SourceFiles/info/media/info_media_inner_widget.cpp +++ b/Telegram/SourceFiles/info/media/info_media_inner_widget.cpp @@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/info_controller.h" #include "data/data_forum_topic.h" #include "data/data_peer.h" +#include "data/data_saved_sublist.h" #include "ui/widgets/discrete_sliders.h" #include "ui/widgets/shadow.h" #include "ui/widgets/buttons.h" @@ -79,7 +80,11 @@ void InnerWidget::createTypeButtons() { auto tracker = Ui::MultiSlideTracker(); const auto peer = _controller->key().peer(); const auto topic = _controller->key().topic(); + const auto sublist = _controller->key().sublist(); const auto topicRootId = topic ? topic->rootId() : MsgId(); + const auto monoforumPeerId = sublist + ? sublist->sublistPeer()->id + : PeerId(); const auto migrated = _controller->migrated(); const auto addMediaButton = [&]( Type buttonType, @@ -92,6 +97,7 @@ void InnerWidget::createTypeButtons() { _controller, peer, topicRootId, + monoforumPeerId, migrated, buttonType, tracker); diff --git a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp index 681405968c..d4d99d138a 100644 --- a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp +++ b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp @@ -28,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_file_origin.h" #include "data/data_download_manager.h" #include "data/data_forum_topic.h" +#include "data/data_saved_sublist.h" #include "history/history_item.h" #include "history/history_item_helpers.h" #include "history/history.h" @@ -512,7 +513,7 @@ void ListWidget::openPhoto(not_null photo, FullMsgId id) { : Data::StoriesContext{ Data::StoriesContextSaved() }; _controller->parentController()->openPhoto( photo, - { id, topicRootId() }, + { id, topicRootId(), monoforumPeerId() }, _controller->storiesPeer() ? &context : nullptr); } @@ -527,7 +528,7 @@ void ListWidget::openDocument( _controller->parentController()->openDocument( document, showInMediaView, - { id, topicRootId() }, + { id, topicRootId(), monoforumPeerId() }, _controller->storiesPeer() ? &context : nullptr); } @@ -796,6 +797,11 @@ MsgId ListWidget::topicRootId() const { return topic ? topic->rootId() : MsgId(0); } +PeerId ListWidget::monoforumPeerId() const { + const auto sublist = _controller->key().sublist(); + return sublist ? sublist->sublistPeer()->id : PeerId(0); +} + QMargins ListWidget::padding() const { return st::infoMediaMargin; } diff --git a/Telegram/SourceFiles/info/media/info_media_list_widget.h b/Telegram/SourceFiles/info/media/info_media_list_widget.h index 5b486c1de7..4f4a78e966 100644 --- a/Telegram/SourceFiles/info/media/info_media_list_widget.h +++ b/Telegram/SourceFiles/info/media/info_media_list_widget.h @@ -158,6 +158,7 @@ private: void setupSelectRestriction(); [[nodiscard]] MsgId topicRootId() const; + [[nodiscard]] PeerId monoforumPeerId() const; QMargins padding() const; bool isItemLayout( diff --git a/Telegram/SourceFiles/info/media/info_media_provider.cpp b/Telegram/SourceFiles/info/media/info_media_provider.cpp index 62f7fdfc4a..88f47bc755 100644 --- a/Telegram/SourceFiles/info/media/info_media_provider.cpp +++ b/Telegram/SourceFiles/info/media/info_media_provider.cpp @@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_user.h" #include "data/data_peer_values.h" #include "data/data_document.h" +#include "data/data_saved_sublist.h" #include "styles/style_info.h" #include "styles/style_overview.h" @@ -40,7 +41,10 @@ Provider::Provider(not_null controller) , _peer(_controller->key().peer()) , _topicRootId(_controller->key().topic() ? _controller->key().topic()->rootId() - : 0) + : MsgId()) +, _monoforumPeerId(_controller->key().sublist() + ? _controller->key().sublist()->sublistPeer()->id + : PeerId()) , _migrated(_controller->migrated()) , _type(_controller->section().mediaType()) , _slice(sliceKey(_universalAroundId)) { @@ -331,13 +335,23 @@ SparseIdsMergedSlice::Key Provider::sliceKey( UniversalMsgId universalId) const { using Key = SparseIdsMergedSlice::Key; if (!_topicRootId && _migrated) { - return Key(_peer->id, _topicRootId, _migrated->id, universalId); + return Key( + _peer->id, + _topicRootId, + _monoforumPeerId, + _migrated->id, + universalId); } if (universalId < 0) { // Convert back to plain id for non-migrated histories. universalId = universalId + ServerMaxMsgId; } - return Key(_peer->id, _topicRootId, 0, universalId); + return Key( + _peer->id, + _topicRootId, + _monoforumPeerId, + PeerId(), + universalId); } void Provider::itemRemoved(not_null item) { diff --git a/Telegram/SourceFiles/info/media/info_media_provider.h b/Telegram/SourceFiles/info/media/info_media_provider.h index b544e2b8d7..ed09954e83 100644 --- a/Telegram/SourceFiles/info/media/info_media_provider.h +++ b/Telegram/SourceFiles/info/media/info_media_provider.h @@ -105,6 +105,7 @@ private: const not_null _peer; const MsgId _topicRootId = 0; + const PeerId _monoforumPeerId = 0; PeerData * const _migrated = nullptr; const Type _type = Type::Photo; diff --git a/Telegram/SourceFiles/info/media/info_media_widget.cpp b/Telegram/SourceFiles/info/media/info_media_widget.cpp index e01d44f533..58d9e8e95e 100644 --- a/Telegram/SourceFiles/info/media/info_media_widget.cpp +++ b/Telegram/SourceFiles/info/media/info_media_widget.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "info/media/info_media_widget.h" +#include "history/history.h" #include "info/media/info_media_inner_widget.h" #include "info/info_controller.h" #include "main/main_session.h" @@ -17,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_user.h" #include "data/data_channel.h" #include "data/data_forum_topic.h" +#include "data/data_saved_sublist.h" #include "lang/lang_keys.h" #include "styles/style_info.h" @@ -70,6 +72,7 @@ Memento::Memento(not_null controller) ? controller->storiesPeer() : controller->parentController()->session().user()), controller->topic(), + controller->sublist(), controller->migratedPeerId(), (controller->section().type() == Section::Type::Downloads ? Type::File @@ -79,23 +82,31 @@ Memento::Memento(not_null controller) } Memento::Memento(not_null peer, PeerId migratedPeerId, Type type) -: Memento(peer, nullptr, migratedPeerId, type) { +: Memento(peer, nullptr, nullptr, migratedPeerId, type) { } Memento::Memento(not_null topic, Type type) -: Memento(topic->channel(), topic, PeerId(), type) { +: Memento(topic->channel(), topic, nullptr, PeerId(), type) { +} + +Memento::Memento(not_null sublist, Type type) +: Memento(sublist->owningHistory()->peer, nullptr, sublist, PeerId(), type) { } Memento::Memento( not_null peer, Data::ForumTopic *topic, + Data::SavedSublist *sublist, PeerId migratedPeerId, Type type) -: ContentMemento(peer, topic, migratedPeerId) +: ContentMemento(peer, topic, sublist, migratedPeerId) , _type(type) { _searchState.query.type = type; _searchState.query.peerId = peer->id; - _searchState.query.topicRootId = topic ? topic->rootId() : 0; + _searchState.query.topicRootId = topic ? topic->rootId() : MsgId(); + _searchState.query.monoforumPeerId = sublist + ? sublist->sublistPeer()->id + : PeerId(); _searchState.query.migratedPeerId = migratedPeerId; if (migratedPeerId) { _searchState.migratedList = Storage::SparseIdsList(); diff --git a/Telegram/SourceFiles/info/media/info_media_widget.h b/Telegram/SourceFiles/info/media/info_media_widget.h index b7c53879b3..1a84139190 100644 --- a/Telegram/SourceFiles/info/media/info_media_widget.h +++ b/Telegram/SourceFiles/info/media/info_media_widget.h @@ -35,6 +35,7 @@ public: explicit Memento(not_null controller); Memento(not_null peer, PeerId migratedPeerId, Type type); Memento(not_null topic, Type type); + Memento(not_null sublist, Type type); using SearchState = Api::DelayedSearchController::SavedState; @@ -92,6 +93,7 @@ private: Memento( not_null peer, Data::ForumTopic *topic, + Data::SavedSublist *sublist, PeerId migratedPeerId, Type type); diff --git a/Telegram/SourceFiles/info/members/info_members_widget.cpp b/Telegram/SourceFiles/info/members/info_members_widget.cpp index 0a00a7344d..07609a430e 100644 --- a/Telegram/SourceFiles/info/members/info_members_widget.cpp +++ b/Telegram/SourceFiles/info/members/info_members_widget.cpp @@ -26,7 +26,7 @@ Memento::Memento(not_null controller) } Memento::Memento(not_null peer, PeerId migratedPeerId) -: ContentMemento(peer, nullptr, migratedPeerId) { +: ContentMemento(peer, nullptr, nullptr, migratedPeerId) { } Section Memento::section() const { diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp index 47981cdf73..86b7d7b527 100644 --- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp +++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp @@ -678,7 +678,7 @@ void InnerWidget::restoreState(not_null memento) { } Memento::Memento(not_null peer) -: ContentMemento(peer, nullptr, PeerId()) { +: ContentMemento(peer, nullptr, nullptr, PeerId()) { } Section Memento::section() const { diff --git a/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp b/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp index aa8b1862fe..5c9b86ce47 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp @@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_photo.h" #include "data/data_file_origin.h" #include "data/data_user.h" +#include "data/data_saved_sublist.h" #include "main/main_session.h" #include "apiwrap.h" #include "api/api_peer_photo.h" @@ -46,6 +47,7 @@ InnerWidget::InnerWidget( , _peer(_controller->key().peer()) , _migrated(_controller->migrated()) , _topic(_controller->key().topic()) +, _sublist(_controller->key().sublist()) , _content(setupContent(this, origin)) { _content->heightValue( ) | rpl::start_with_next([this](int height) { @@ -82,7 +84,7 @@ object_ptr InnerWidget::setupContent( AddDetails(result, _controller, _peer, _topic, origin); result->add(setupSharedMedia(result.data())); - if (_topic) { + if (_topic || _sublist) { return result; } { @@ -147,7 +149,8 @@ object_ptr InnerWidget::setupSharedMedia( content, _controller, _peer, - _topic ? _topic->rootId() : 0, + _topic ? _topic->rootId() : MsgId(), + _sublist ? _sublist->sublistPeer()->id : PeerId(), _migrated, type, tracker); diff --git a/Telegram/SourceFiles/info/profile/info_profile_inner_widget.h b/Telegram/SourceFiles/info/profile/info_profile_inner_widget.h index a1b257801b..65936bcae5 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_inner_widget.h +++ b/Telegram/SourceFiles/info/profile/info_profile_inner_widget.h @@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Data { class ForumTopic; +class SavedSublist; class PhotoMedia; } // namespace Data @@ -74,6 +75,7 @@ private: const not_null _peer; PeerData * const _migrated = nullptr; Data::ForumTopic * const _topic = nullptr; + Data::SavedSublist * const _sublist = nullptr; PeerData *_reactionGroup = nullptr; diff --git a/Telegram/SourceFiles/info/profile/info_profile_values.cpp b/Telegram/SourceFiles/info/profile/info_profile_values.cpp index 16e8b231f7..ac25b6c436 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_values.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_values.cpp @@ -543,6 +543,7 @@ rpl::producer KickedCountValue(not_null channel) { rpl::producer SharedMediaCountValue( not_null peer, MsgId topicRootId, + PeerId monoforumPeerId, PeerData *migrated, Storage::SharedMediaType type) { auto aroundId = 0; @@ -553,6 +554,7 @@ rpl::producer SharedMediaCountValue( SparseIdsMergedSlice::Key( peer->id, topicRootId, + monoforumPeerId, migrated ? migrated->id : 0, aroundId), type), diff --git a/Telegram/SourceFiles/info/profile/info_profile_values.h b/Telegram/SourceFiles/info/profile/info_profile_values.h index 52f0148bd4..16e9ed5d64 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_values.h +++ b/Telegram/SourceFiles/info/profile/info_profile_values.h @@ -113,6 +113,7 @@ struct LinkWithUrl { [[nodiscard]] rpl::producer SharedMediaCountValue( not_null peer, MsgId topicRootId, + PeerId monoforumPeerId, PeerData *migrated, Storage::SharedMediaType type); [[nodiscard]] rpl::producer CommonGroupsCountValue( diff --git a/Telegram/SourceFiles/info/profile/info_profile_widget.cpp b/Telegram/SourceFiles/info/profile/info_profile_widget.cpp index 6f62b98975..cf235c55df 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_widget.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_widget.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/profile/info_profile_widget.h" #include "dialogs/ui/dialogs_stories_content.h" +#include "history/history.h" #include "info/profile/info_profile_inner_widget.h" #include "info/profile/info_profile_members.h" #include "ui/widgets/scroll_area.h" @@ -15,6 +16,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_user.h" #include "lang/lang_keys.h" #include "info/info_controller.h" @@ -25,6 +27,7 @@ Memento::Memento(not_null controller) : Memento( controller->peer(), controller->topic(), + controller->sublist(), controller->migratedPeerId(), { v::null }) { } @@ -33,20 +36,25 @@ Memento::Memento( not_null peer, PeerId migratedPeerId, Origin origin) -: Memento(peer, nullptr, migratedPeerId, origin) { +: Memento(peer, nullptr, nullptr, migratedPeerId, origin) { } Memento::Memento( not_null peer, Data::ForumTopic *topic, + Data::SavedSublist *sublist, PeerId migratedPeerId, Origin origin) -: ContentMemento(peer, topic, migratedPeerId) +: ContentMemento(peer, topic, sublist, migratedPeerId) , _origin(origin) { } Memento::Memento(not_null topic) -: ContentMemento(topic->channel(), topic, 0) { +: ContentMemento(topic->channel(), topic, nullptr, 0) { +} + +Memento::Memento(not_null sublist) +: ContentMemento(sublist->owningHistory()->peer, nullptr, sublist, 0) { } Section Memento::section() const { diff --git a/Telegram/SourceFiles/info/profile/info_profile_widget.h b/Telegram/SourceFiles/info/profile/info_profile_widget.h index b6e4da66a9..6d1bfcefbf 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_widget.h +++ b/Telegram/SourceFiles/info/profile/info_profile_widget.h @@ -35,6 +35,7 @@ public: PeerId migratedPeerId, Origin origin = { v::null }); explicit Memento(not_null topic); + explicit Memento(not_null sublist); object_ptr createWidget( QWidget *parent, @@ -56,6 +57,7 @@ private: Memento( not_null peer, Data::ForumTopic *topic, + Data::SavedSublist *sublist, PeerId migratedPeerId, Origin origin); diff --git a/Telegram/SourceFiles/info/requests_list/info_requests_list_widget.cpp b/Telegram/SourceFiles/info/requests_list/info_requests_list_widget.cpp index 2fae27d580..b006dbbe28 100644 --- a/Telegram/SourceFiles/info/requests_list/info_requests_list_widget.cpp +++ b/Telegram/SourceFiles/info/requests_list/info_requests_list_widget.cpp @@ -188,7 +188,7 @@ std::shared_ptr InnerWidget::peerListUiShow() { } Memento::Memento(not_null peer) -: ContentMemento(peer, nullptr, PeerId()) { +: ContentMemento(peer, nullptr, nullptr, PeerId()) { } Section Memento::section() const { diff --git a/Telegram/SourceFiles/info/saved/info_saved_sublists_widget.cpp b/Telegram/SourceFiles/info/saved/info_saved_sublists_widget.cpp index 06143d2c13..298ef5f3e1 100644 --- a/Telegram/SourceFiles/info/saved/info_saved_sublists_widget.cpp +++ b/Telegram/SourceFiles/info/saved/info_saved_sublists_widget.cpp @@ -29,7 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Info::Saved { SublistsMemento::SublistsMemento(not_null session) -: ContentMemento(session->user(), nullptr, PeerId()) { +: ContentMemento(session->user(), nullptr, nullptr, PeerId()) { } Section SublistsMemento::section() const { @@ -113,6 +113,7 @@ void SublistsWidget::setupOtherTypes() { controller(), peer, MsgId(), // topicRootId + PeerId(), // monoforumPeerId nullptr, // migrated buttonType, tracker); diff --git a/Telegram/SourceFiles/info/similar_peers/info_similar_peers_widget.cpp b/Telegram/SourceFiles/info/similar_peers/info_similar_peers_widget.cpp index 3646b5b683..003166ff98 100644 --- a/Telegram/SourceFiles/info/similar_peers/info_similar_peers_widget.cpp +++ b/Telegram/SourceFiles/info/similar_peers/info_similar_peers_widget.cpp @@ -438,7 +438,7 @@ std::shared_ptr InnerWidget::peerListUiShow() { } Memento::Memento(not_null peer) -: ContentMemento(peer, nullptr, PeerId()) { +: ContentMemento(peer, nullptr, nullptr, PeerId()) { } Section Memento::section() const { diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp index 0b5c01cd39..b79c168013 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp @@ -347,9 +347,9 @@ bool Result::onChoose(Layout::ItemBase *layout) { Media::View::OpenRequest Result::openRequest() { using namespace Media::View; if (_document) { - return OpenRequest(nullptr, _document, nullptr, MsgId()); + return OpenRequest(nullptr, _document, nullptr, MsgId(), PeerId()); } else if (_photo) { - return OpenRequest(nullptr, _photo, nullptr, MsgId()); + return OpenRequest(nullptr, _photo, nullptr, MsgId(), PeerId()); } return {}; } diff --git a/Telegram/SourceFiles/iv/iv_instance.cpp b/Telegram/SourceFiles/iv/iv_instance.cpp index b4fbc4e844..09a7e2e383 100644 --- a/Telegram/SourceFiles/iv/iv_instance.cpp +++ b/Telegram/SourceFiles/iv/iv_instance.cpp @@ -894,6 +894,7 @@ void Instance::show( : nullptr; const auto item = (HistoryItem*)nullptr; const auto topicRootId = MsgId(0); + const auto monoforumPeerId = PeerId(0); if (event.context.startsWith("-photo")) { const auto id = event.context.mid(6).toULongLong(); const auto photo = _shownSession->data().photo(id); @@ -902,7 +903,8 @@ void Instance::show( controller, photo, item, - topicRootId + topicRootId, + monoforumPeerId }); } } else if (event.context.startsWith("-video")) { @@ -913,7 +915,8 @@ void Instance::show( controller, video, item, - topicRootId + topicRootId, + monoforumPeerId }); } } diff --git a/Telegram/SourceFiles/main/main_session_settings.cpp b/Telegram/SourceFiles/main/main_session_settings.cpp index 7d13cde46c..58b7578c1b 100644 --- a/Telegram/SourceFiles/main/main_session_settings.cpp +++ b/Telegram/SourceFiles/main/main_session_settings.cpp @@ -40,7 +40,7 @@ QByteArray SessionSettings::serialize() const { + sizeof(qint32) * 11 + (_mutePeriods.size() * sizeof(quint64)) + sizeof(qint32) * 2 - + _hiddenPinnedMessages.size() * (sizeof(quint64) * 3) + + _hiddenPinnedMessages.size() * (sizeof(quint64) * 4) + sizeof(qint32) + _groupEmojiSectionHidden.size() * sizeof(quint64) + sizeof(qint32) * 2; @@ -68,32 +68,33 @@ QByteArray SessionSettings::serialize() const { << qint32(_archiveInMainMenu.current() ? 1 : 0) << qint32(_skipArchiveInSearch.current() ? 1 : 0) << qint32(0) // old _mediaLastPlaybackPosition.size()); - << qint32(0) // very old _hiddenPinnedMessages.size()); + << qint32(0) // very very old _hiddenPinnedMessages.size()); << qint32(_dialogsFiltersEnabled ? 1 : 0) << qint32(_supportAllSilent ? 1 : 0) << qint32(_photoEditorHintShowsCount) - << qint32(0) // old _hiddenPinnedMessages.size()); + << qint32(0) // very old _hiddenPinnedMessages.size()); << qint32(_mutePeriods.size()); for (const auto &period : _mutePeriods) { stream << quint64(period); } stream << qint32(0) // old _skipPremiumStickersSet - << qint32(_hiddenPinnedMessages.size()); - for (const auto &[key, value] : _hiddenPinnedMessages) { - stream - << SerializePeerId(key.peerId) - << qint64(key.topicRootId.bare) - << qint64(value.bare); - } - stream + << qint32(0) // old _hiddenPinnedMessages.size()); << qint32(_groupEmojiSectionHidden.size()); for (const auto &peerId : _groupEmojiSectionHidden) { stream << SerializePeerId(peerId); } stream << qint32(_lastNonPremiumLimitDownload) - << qint32(_lastNonPremiumLimitUpload); + << qint32(_lastNonPremiumLimitUpload) + << qint32(_hiddenPinnedMessages.size()); + for (const auto &[key, value] : _hiddenPinnedMessages) { + stream + << SerializePeerId(key.peerId) + << qint64(key.topicRootId.bare) + << SerializePeerId(key.monoforumPeerId) + << qint64(value.bare); + } } Ensures(result.size() == size); @@ -401,6 +402,7 @@ void SessionSettings::addFromSerialized(const QByteArray &serialized) { auto count = qint32(0); stream >> count; if (stream.status() == QDataStream::Ok) { + // Legacy. for (auto i = 0; i != count; ++i) { auto keyPeerId = quint64(); auto keyTopicRootId = qint64(); @@ -438,6 +440,33 @@ void SessionSettings::addFromSerialized(const QByteArray &serialized) { >> lastNonPremiumLimitDownload >> lastNonPremiumLimitUpload; } + if (!stream.atEnd()) { + auto count = qint32(0); + stream >> count; + if (stream.status() == QDataStream::Ok) { + for (auto i = 0; i != count; ++i) { + auto keyPeerId = quint64(); + auto keyTopicRootId = qint64(); + auto keyMonoforumPeerId = quint64(); + auto value = qint64(); + stream + >> keyPeerId + >> keyTopicRootId + >> keyMonoforumPeerId + >> value; + if (stream.status() != QDataStream::Ok) { + LOG(("App Error: " + "Bad data for SessionSettings::addFromSerialized()")); + return; + } + hiddenPinnedMessages.emplace(ThreadId{ + DeserializePeerId(keyPeerId), + keyTopicRootId, + DeserializePeerId(keyMonoforumPeerId), + }, value); + } + } + } if (stream.status() != QDataStream::Ok) { LOG(("App Error: " "Bad data for SessionSettings::addFromSerialized()")); @@ -595,16 +624,22 @@ rpl::producer SessionSettings::skipArchiveInSearchChanges() const { MsgId SessionSettings::hiddenPinnedMessageId( PeerId peerId, - MsgId topicRootId) const { - const auto i = _hiddenPinnedMessages.find({ peerId, topicRootId }); + MsgId topicRootId, + PeerId monoforumPeerId) const { + const auto i = _hiddenPinnedMessages.find({ + peerId, + topicRootId, + monoforumPeerId, + }); return (i != end(_hiddenPinnedMessages)) ? i->second : 0; } void SessionSettings::setHiddenPinnedMessageId( PeerId peerId, MsgId topicRootId, + PeerId monoforumPeerId, MsgId msgId) { - const auto id = ThreadId{ peerId, topicRootId }; + const auto id = ThreadId{ peerId, topicRootId, monoforumPeerId }; if (msgId) { _hiddenPinnedMessages[id] = msgId; } else { diff --git a/Telegram/SourceFiles/main/main_session_settings.h b/Telegram/SourceFiles/main/main_session_settings.h index c171968e2c..b88244aaa3 100644 --- a/Telegram/SourceFiles/main/main_session_settings.h +++ b/Telegram/SourceFiles/main/main_session_settings.h @@ -110,10 +110,12 @@ public: [[nodiscard]] MsgId hiddenPinnedMessageId( PeerId peerId, - MsgId topicRootId = 0) const; + MsgId topicRootId = 0, + PeerId monoforumPeerId = 0) const; void setHiddenPinnedMessageId( PeerId peerId, MsgId topicRootId, + PeerId monoforumPeerId, MsgId msgId); [[nodiscard]] bool dialogsFiltersEnabled() const { @@ -149,6 +151,7 @@ private: struct ThreadId { PeerId peerId; MsgId topicRootId; + PeerId monoforumPeerId; friend inline constexpr auto operator<=>( ThreadId, diff --git a/Telegram/SourceFiles/media/player/media_player_instance.cpp b/Telegram/SourceFiles/media/player/media_player_instance.cpp index de1932b7aa..c73c34e5ef 100644 --- a/Telegram/SourceFiles/media/player/media_player_instance.cpp +++ b/Telegram/SourceFiles/media/player/media_player_instance.cpp @@ -85,6 +85,7 @@ struct Instance::ShuffleData { std::vector playedIds; History *history = nullptr; MsgId topicRootId = 0; + PeerId monoforumPeerId = 0; History *migrated = nullptr; bool scheduled = false; int indexInPlayedIds = 0; @@ -247,6 +248,7 @@ void Instance::setHistory( if (history) { data->history = history->migrateToOrMe(); data->topicRootId = 0; + data->monoforumPeerId = 0; data->migrated = data->history->migrateFrom(); setSession(data, &history->session()); } else { @@ -349,6 +351,7 @@ bool Instance::validPlaylist(not_null data) const { const auto inSameDomain = [](const Key &a, const Key &b) { return (a.peerId == b.peerId) && (a.topicRootId == b.topicRootId) + && (a.monoforumPeerId == b.monoforumPeerId) && (a.migratedPeerId == b.migratedPeerId); }; const auto countDistanceInData = [&](const Key &a, const Key &b) { @@ -422,6 +425,7 @@ auto Instance::playlistKey(not_null data) const (item->isScheduled() ? SparseIdsMergedSlice::kScheduledTopicId : data->topicRootId), + data->monoforumPeerId, data->migrated ? data->migrated->peer->id : 0, universalId); } @@ -479,6 +483,7 @@ auto Instance::playlistOtherKey(not_null data) const return SliceKey( data->history->peer->id, data->topicRootId, + data->monoforumPeerId, data->migrated ? data->migrated->peer->id : 0, (data->playlistSlice->skippedBefore() == 0 ? ServerMaxMsgId - 1 @@ -905,6 +910,7 @@ void Instance::validateShuffleData(not_null data) { && (key->topicRootId == SparseIdsMergedSlice::kScheduledTopicId); if (raw->history != data->history || raw->topicRootId != data->topicRootId + || raw->monoforumPeerId != data->monoforumPeerId || raw->migrated != data->migrated || raw->scheduled != scheduled) { raw->history = data->history; @@ -962,6 +968,7 @@ void Instance::validateShuffleData(not_null data) { SliceKey( raw->history->peer->id, raw->topicRootId, + raw->monoforumPeerId, raw->migrated ? raw->migrated->peer->id : 0, last), data->overview), diff --git a/Telegram/SourceFiles/media/player/media_player_instance.h b/Telegram/SourceFiles/media/player/media_player_instance.h index ebe7d3d4cb..baf0599869 100644 --- a/Telegram/SourceFiles/media/player/media_player_instance.h +++ b/Telegram/SourceFiles/media/player/media_player_instance.h @@ -194,6 +194,7 @@ private: rpl::event_stream<> playlistChanges; History *history = nullptr; MsgId topicRootId = 0; + PeerId monoforumPeerId = 0; History *migrated = nullptr; Main::Session *session = nullptr; bool isPlaying = false; diff --git a/Telegram/SourceFiles/media/view/media_view_open_common.h b/Telegram/SourceFiles/media/view/media_view_open_common.h index 76cfd7748a..f512ca45b3 100644 --- a/Telegram/SourceFiles/media/view/media_view_open_common.h +++ b/Telegram/SourceFiles/media/view/media_view_open_common.h @@ -30,11 +30,13 @@ public: Window::SessionController *controller, not_null photo, HistoryItem *item, - MsgId topicRootId) + MsgId topicRootId, + PeerId monoforumPeerId) : _controller(controller) , _photo(photo) , _item(item) - , _topicRootId(topicRootId) { + , _topicRootId(topicRootId) + , _monoforumPeerId(monoforumPeerId) { } OpenRequest( Window::SessionController *controller, @@ -50,12 +52,14 @@ public: not_null document, HistoryItem *item, MsgId topicRootId, + PeerId monoforumPeerId, bool continueStreaming = false, crl::time startTime = 0) : _controller(controller) , _document(document) , _item(item) , _topicRootId(topicRootId) + , _monoforumPeerId(monoforumPeerId) , _continueStreaming(continueStreaming) , _startTime(startTime) { } @@ -92,6 +96,9 @@ public: [[nodiscard]] MsgId topicRootId() const { return _topicRootId; } + [[nodiscard]] PeerId monoforumPeerId() const { + return _monoforumPeerId; + } [[nodiscard]] DocumentData *document() const { return _document; @@ -129,6 +136,7 @@ private: PeerData *_peer = nullptr; HistoryItem *_item = nullptr; MsgId _topicRootId = 0; + PeerId _monoforumPeerId = 0; std::optional _cloudTheme = std::nullopt; bool _continueStreaming = false; crl::time _startTime = 0; diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp index 1ea8c3f560..99f7bc2825 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp @@ -366,6 +366,7 @@ struct OverlayWidget::PipWrap { struct OverlayWidget::ItemContext { not_null item; MsgId topicRootId = 0; + PeerId monoforumPeerId = 0; }; struct OverlayWidget::StoriesContext { @@ -2675,7 +2676,8 @@ void OverlayWidget::handleDocumentClick() { findWindow(), _document, _message, - _topicRootId); + _topicRootId, + _monoforumPeerId); if (_document && _document->loading() && !_radial.animating()) { _radial.start(_documentMedia->progress()); } @@ -2921,13 +2923,22 @@ void OverlayWidget::showMediaOverview() { const auto topic = _topicRootId ? _history->peer->forumTopicFor(_topicRootId) : nullptr; + const auto sublist = _monoforumPeerId + ? _history->peer->monoforumSublistFor(_monoforumPeerId) + : nullptr; if (_topicRootId && !topic) { return; + } else if (_monoforumPeerId && !sublist) { + return; } window->showSection(_topicRootId ? std::make_shared( topic, Info::Section(*overviewType)) + : _monoforumPeerId + ? std::make_shared( + sublist, + Info::Section(*overviewType)) : std::make_shared( _history->peer, Info::Section(*overviewType))); @@ -3017,6 +3028,7 @@ auto OverlayWidget::sharedMediaKey() const -> std::optional { return SharedMediaKey{ _history->peer->id, MsgId(0), // topicRootId + PeerId(0), // monoforumPeerId _migrated ? _migrated->peer->id : 0, SharedMediaType::ChatPhoto, _photo @@ -3032,6 +3044,7 @@ auto OverlayWidget::sharedMediaKey() const -> std::optional { (isScheduled ? SparseIdsMergedSlice::kScheduledTopicId : _topicRootId), + (isScheduled ? PeerId() : _monoforumPeerId), _migrated ? _migrated->peer->id : 0, type, (_message->history() == _history @@ -4609,6 +4622,7 @@ void OverlayWidget::switchToPip() { const auto document = _document; const auto messageId = _message ? _message->fullId() : FullMsgId(); const auto topicRootId = _topicRootId; + const auto monoforumPeerId = _monoforumPeerId; const auto closeAndContinue = [=] { _showAsPip = false; show(OpenRequest( @@ -4616,6 +4630,7 @@ void OverlayWidget::switchToPip() { document, document->owner().message(messageId), topicRootId, + monoforumPeerId, true)); }; _showAsPip = true; @@ -5699,9 +5714,9 @@ OverlayWidget::Entity OverlayWidget::entityForCollage(int index) const { return { v::null, nullptr }; } if (const auto document = std::get_if(&items[index])) { - return { *document, _message, _topicRootId }; + return { *document, _message, _topicRootId, _monoforumPeerId }; } else if (const auto photo = std::get_if(&items[index])) { - return { *photo, _message, _topicRootId }; + return { *photo, _message, _topicRootId, _monoforumPeerId }; } return { v::null, nullptr }; } @@ -5712,12 +5727,12 @@ OverlayWidget::Entity OverlayWidget::entityForItemId(const FullMsgId &itemId) co if (const auto item = _session->data().message(itemId)) { if (const auto media = item->media()) { if (const auto photo = media->photo()) { - return { photo, item, _topicRootId }; + return { photo, item, _topicRootId, _monoforumPeerId }; } else if (const auto document = media->document()) { - return { document, item, _topicRootId }; + return { document, item, _topicRootId, _monoforumPeerId }; } } - return { v::null, item, _topicRootId }; + return { v::null, item, _topicRootId, _monoforumPeerId }; } return { v::null, nullptr }; } @@ -5744,6 +5759,9 @@ void OverlayWidget::setContext( _history = _message->history(); _peer = _history->peer; _topicRootId = _peer->isForum() ? item->topicRootId : MsgId(); + _monoforumPeerId = _peer->amMonoforumAdmin() + ? item->monoforumPeerId + : PeerId(); setStoriesPeer(nullptr); } else if (const auto peer = std::get_if>(&context)) { _peer = *peer; diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.h b/Telegram/SourceFiles/media/view/media_view_overlay_widget.h index fb8efce90e..8787be47e4 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.h +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.h @@ -170,6 +170,7 @@ private: not_null> data; HistoryItem *item = nullptr; MsgId topicRootId = 0; + PeerId monoforumPeerId = 0; }; enum class SavePhotoVideo { None, @@ -674,6 +675,7 @@ private: History *_migrated = nullptr; History *_history = nullptr; // if conversation photos or files overview MsgId _topicRootId = 0; + PeerId _monoforumPeerId = 0; PeerData *_peer = nullptr; UserData *_user = nullptr; // if user profile photos overview diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp index d49fecb814..8303e0d033 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp @@ -16,6 +16,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/sandbox.h" #include "core/core_settings.h" #include "data/data_forum_topic.h" +#include "data/data_saved_sublist.h" +#include "data/data_peer.h" #include "history/history.h" #include "history/history_item.h" #include "main/main_session.h" @@ -156,6 +158,7 @@ public: void clearAll(); void clearFromItem(not_null item); void clearFromTopic(not_null topic); + void clearFromSublist(not_null sublist); void clearFromHistory(not_null history); void clearFromSession(not_null session); void clearNotification(NotificationId id); @@ -367,6 +370,8 @@ Manager::Private::Private(not_null manager) .sessionId = dict.lookup_value("session").get_uint64(), .peerId = PeerId(dict.lookup_value("peer").get_uint64()), .topicRootId = dict.lookup_value("topic").get_int64(), + .monoforumPeerId = dict.lookup_value( + "monoforumpeer").get_uint64(), }, .msgId = dict.lookup_value("msgid").get_int64(), }; @@ -531,6 +536,7 @@ void Manager::Private::showNotification( .sessionId = peer->session().uniqueId(), .peerId = peer->id, .topicRootId = info.topicRootId, + .monoforumPeerId = info.monoforumPeerId, }; const auto notificationId = NotificationId{ .contextId = key, @@ -591,6 +597,10 @@ void Manager::Private::showNotification( GLib::Variant::new_string("topic"), GLib::Variant::new_variant( GLib::Variant::new_int64(info.topicRootId.bare))), + GLib::Variant::new_dict_entry( + GLib::Variant::new_string("monoforumpeer"), + GLib::Variant::new_variant( + GLib::Variant::new_uint64(info.monoforumPeerId.value))), GLib::Variant::new_dict_entry( GLib::Variant::new_string("msgid"), GLib::Variant::new_variant( @@ -809,6 +819,7 @@ void Manager::Private::clearFromItem(not_null item) { .sessionId = item->history()->session().uniqueId(), .peerId = item->history()->peer->id, .topicRootId = item->topicRootId(), + .monoforumPeerId = item->sublistPeerId(), }); if (i != _notifications.cend() && i->second.remove(item->id) @@ -825,6 +836,15 @@ void Manager::Private::clearFromTopic(not_null topic) { }); } +void Manager::Private::clearFromSublist( + not_null sublist) { + _notifications.remove(ContextId{ + .sessionId = sublist->session().uniqueId(), + .peerId = sublist->owningHistory()->peer->id, + .monoforumPeerId = sublist->sublistPeer()->id, + }); +} + void Manager::Private::clearFromHistory(not_null history) { const auto sessionId = history->session().uniqueId(); const auto peerId = history->peer->id; @@ -889,6 +909,10 @@ void Manager::doClearFromTopic(not_null topic) { _private->clearFromTopic(topic); } +void Manager::doClearFromSublist(not_null sublist) { + _private->clearFromSublist(sublist); +} + void Manager::doClearFromHistory(not_null history) { _private->clearFromHistory(history); } diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h index 8ab17f55b7..d2e740750f 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h @@ -24,6 +24,7 @@ protected: void doClearAllFast() override; void doClearFromItem(not_null item) override; void doClearFromTopic(not_null topic) override; + void doClearFromSublist(not_null sublist) override; void doClearFromHistory(not_null history) override; void doClearFromSession(not_null session) override; bool doSkipToast() const override; diff --git a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.h b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.h index 2ffc5d6cb6..6af0292384 100644 --- a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.h +++ b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.h @@ -25,6 +25,7 @@ protected: void doClearAllFast() override; void doClearFromItem(not_null item) override; void doClearFromTopic(not_null topic) override; + void doClearFromSublist(not_null sublist) override; void doClearFromHistory(not_null history) override; void doClearFromSession(not_null session) override; QString accountNameSeparator() override; diff --git a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm index 3be39ef841..7ab8462891 100644 --- a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm +++ b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm @@ -14,6 +14,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/platform/mac/base_utilities_mac.h" #include "base/random.h" #include "data/data_forum_topic.h" +#include "data/data_saved_sublist.h" +#include "data/data_peer.h" #include "history/history.h" #include "history/history_item.h" #include "ui/empty_userpic.h" @@ -131,6 +133,12 @@ using Manager = Platform::Notifications::Manager; return; } const auto notificationTopicRootId = [topicObject longLongValue]; + NSNumber *monoforumPeerObject = [notificationUserInfo objectForKey:@"monoforumpeer"]; + if (!monoforumPeerObject) { + LOG(("App Error: A notification with unknown monoforum peer was received")); + return; + } + const auto notificationMonoforumPeerId = [monoforumPeerObject unsignedLongLongValue]; NSNumber *msgObject = [notificationUserInfo objectForKey:@"msgid"]; const auto notificationMsgId = msgObject ? [msgObject longLongValue] : 0LL; @@ -140,6 +148,7 @@ using Manager = Platform::Notifications::Manager; .sessionId = notificationSessionId, .peerId = PeerId(notificationPeerId), .topicRootId = MsgId(notificationTopicRootId), + .monoforumPeerId = PeerId(notificationMonoforumPeerId), }, .msgId = notificationMsgId, }; @@ -210,6 +219,7 @@ public: void clearAll(); void clearFromItem(not_null item); void clearFromTopic(not_null topic); + void clearFromSublist(not_null sublist); void clearFromHistory(not_null history); void clearFromSession(not_null session); void updateDelegate(); @@ -237,6 +247,9 @@ private: struct ClearFromTopic { ContextId contextId; }; + struct ClearFromSublist { + ContextId contextId; + } struct ClearFromHistory { ContextId partialContextId; }; @@ -250,6 +263,7 @@ private: using ClearTask = std::variant< ClearFromItem, ClearFromTopic, + ClearFromSublist, ClearFromHistory, ClearFromSession, ClearAll, @@ -311,6 +325,8 @@ void Manager::Private::showNotification( @"peer", [NSNumber numberWithLongLong:info.topicRootId.bare], @"topic", + [NSNumber numberWithUnsignedLongLong:info.monoforumPeerId.value], + @"monoforumpeer", [NSNumber numberWithLongLong:info.itemId.bare], @"msgid", [NSNumber numberWithUnsignedLongLong:_managerId], @@ -351,6 +367,7 @@ void Manager::Private::clearingThreadLoop() { auto clearAll = false; auto clearFromItems = base::flat_set(); auto clearFromTopics = base::flat_set(); + auto clearFromSublists = base::flat_set(); auto clearFromHistories = base::flat_set(); auto clearFromSessions = base::flat_set(); { @@ -368,6 +385,8 @@ void Manager::Private::clearingThreadLoop() { clearFromItems.emplace(value.id); }, [&](const ClearFromTopic &value) { clearFromTopics.emplace(value.contextId); + }, [&](const ClearFromSublist &value) { + clearFromSublists.emplace(value.contextId); }, [&](const ClearFromHistory &value) { clearFromHistories.emplace(value.partialContextId); }, [&](const ClearFromSession &value) { @@ -395,21 +414,35 @@ void Manager::Private::clearingThreadLoop() { return true; } const auto notificationTopicRootId = [topicObject longLongValue]; + NSNumber *monoforumPeerObject = [notificationUserInfo objectForKey:@"monoforumpeer"]; + if (!monoforumPeerObject) { + return true; + } + const auto notificationMonoforumPeerId = [monoforumPeerObject unsignedLongLongValue]; NSNumber *msgObject = [notificationUserInfo objectForKey:@"msgid"]; const auto msgId = msgObject ? [msgObject longLongValue] : 0LL; const auto partialContextId = ContextId{ .sessionId = notificationSessionId, .peerId = PeerId(notificationPeerId), }; - const auto contextId = ContextId{ + const auto contextId = notificationTopicRootId + ? ContextId{ .sessionId = notificationSessionId, .peerId = PeerId(notificationPeerId), .topicRootId = MsgId(notificationTopicRootId), - }; + } + : notificationMonoforumPeerId + ? ContextId{ + .sessionId = notificationSessionId, + .peerId = PeerId(notificationPeerId), + .monoforumPeerId = PeerId(notificationMonoforumPeerId), + } + : partialContextId; const auto id = NotificationId{ contextId, MsgId(msgId) }; return clearFromSessions.contains(notificationSessionId) || clearFromHistories.contains(partialContextId) || clearFromTopics.contains(contextId) + || clearFromSublists.contains(contextId) || (msgId && clearFromItems.contains(id)); }; @@ -450,6 +483,7 @@ void Manager::Private::clearFromItem(not_null item) { .sessionId = item->history()->session().uniqueId(), .peerId = item->history()->peer->id, .topicRootId = item->topicRootId(), + .monoforumPeerId = item->sublistPeerId(), }, item->id }); } @@ -461,6 +495,15 @@ void Manager::Private::clearFromTopic(not_null topic) { } }); } +void Manager::Private::clearFromSublist( + not_null sublist) { + putClearTask(ClearFromSublist{ ContextId{ + .sessionId = sublist->session().uniqueId(), + .peerId = sublist->owningHistory()->peer->id, + .monoforumPeerId = sublist->sublistPeer()->id, + } }); +} + void Manager::Private::clearFromHistory(not_null history) { putClearTask(ClearFromHistory{ ContextId{ .sessionId = history->session().uniqueId(), @@ -511,6 +554,10 @@ void Manager::doClearFromTopic(not_null topic) { _private->clearFromTopic(topic); } +void Manager::doClearFromSublist(not_null sublist) { + _private->clearFromSublist(sublist); +} + void Manager::doClearFromHistory(not_null history) { _private->clearFromHistory(history); } diff --git a/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp b/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp index 9a4f028af4..d132ed4f32 100644 --- a/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp +++ b/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp @@ -20,6 +20,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "platform/win/windows_dlls.h" #include "platform/win/specific_win.h" #include "data/data_forum_topic.h" +#include "data/data_saved_sublist.h" +#include "data/data_peer.h" #include "history/history.h" #include "history/history_item.h" #include "core/application.h" @@ -433,6 +435,7 @@ public: void clearAll(); void clearFromItem(not_null item); void clearFromTopic(not_null topic); + void clearFromSublist(not_null sublist); void clearFromHistory(not_null history); void clearFromSession(not_null session); void beforeNotificationActivated(NotificationId id); @@ -508,6 +511,7 @@ void Manager::Private::clearFromItem(not_null item) { .sessionId = item->history()->session().uniqueId(), .peerId = item->history()->peer->id, .topicRootId = item->topicRootId(), + .monoforumPeerId = item->sublistPeerId(), }); if (i == _notifications.cend()) { return; @@ -544,6 +548,27 @@ void Manager::Private::clearFromTopic(not_null topic) { } } +void Manager::Private::clearFromSublist( + not_null sublist) { + if (!_notifier) { + return; + } + + const auto i = _notifications.find(ContextId{ + .sessionId = sublist->session().uniqueId(), + .peerId = sublist->owningHistory()->peer->id, + .monoforumPeerId = sublist->sublistPeer()->id, + }); + if (i != _notifications.cend()) { + const auto temp = base::take(i->second); + _notifications.erase(i); + + for (const auto &[msgId, notification] : temp) { + tryHide(notification); + } + } +} + void Manager::Private::clearFromHistory(not_null history) { if (!_notifier) { return; @@ -626,7 +651,9 @@ void Manager::Private::handleActivation(const ToastActivation &activation) { .contextId = ContextId{ .sessionId = parsed.value("session").toULongLong(), .peerId = PeerId(parsed.value("peer").toULongLong()), - .topicRootId = MsgId(parsed.value("topic").toLongLong()) + .topicRootId = MsgId(parsed.value("topic").toLongLong()), + .monoforumPeerId = PeerId( + parsed.value("monoforumpeer").toULongLong()), }, .msgId = MsgId(parsed.value("msg").toLongLong()), }; @@ -694,16 +721,18 @@ bool Manager::Private::showNotificationInTryCatch( .sessionId = peer->session().uniqueId(), .peerId = peer->id, .topicRootId = info.topicRootId, + .monoforumPeerId = info.monoforumPeerId, }; const auto notificationId = NotificationId{ .contextId = key, .msgId = info.itemId, }; - const auto idString = u"pid=%1&session=%2&peer=%3&topic=%4&msg=%5"_q + const auto idString = u"pid=%1&session=%2&peer=%3&topic=%4&monoforumpeer=%5&msg=%6"_q .arg(GetCurrentProcessId()) .arg(key.sessionId) .arg(key.peerId.value) .arg(info.topicRootId.bare) + .arg(info.monoforumPeerId.value) .arg(info.itemId.bare); const auto modern = Platform::IsWindows10OrGreater(); @@ -897,6 +926,10 @@ void Manager::doClearFromTopic(not_null topic) { _private->clearFromTopic(topic); } +void Manager::doClearFromSublist(not_null sublist) { + _private->clearFromSublist(sublist); +} + void Manager::doClearFromHistory(not_null history) { _private->clearFromHistory(history); } diff --git a/Telegram/SourceFiles/platform/win/notifications_manager_win.h b/Telegram/SourceFiles/platform/win/notifications_manager_win.h index 5e99c760a2..7f9a6ce8ef 100644 --- a/Telegram/SourceFiles/platform/win/notifications_manager_win.h +++ b/Telegram/SourceFiles/platform/win/notifications_manager_win.h @@ -31,6 +31,7 @@ protected: void doClearAllFast() override; void doClearFromItem(not_null item) override; void doClearFromTopic(not_null topic) override; + void doClearFromSublist(not_null sublist) override; void doClearFromHistory(not_null history) override; void doClearFromSession(not_null session) override; void onBeforeNotificationActivated(NotificationId id) override; diff --git a/Telegram/SourceFiles/storage/details/storage_settings_scheme.cpp b/Telegram/SourceFiles/storage/details/storage_settings_scheme.cpp index d9421433e6..ebef828a98 100644 --- a/Telegram/SourceFiles/storage/details/storage_settings_scheme.cpp +++ b/Telegram/SourceFiles/storage/details/storage_settings_scheme.cpp @@ -1084,6 +1084,7 @@ bool ReadSetting( context.sessionSettings().setHiddenPinnedMessageId( DeserializePeerId(i.key()), MsgId(0), // topicRootId + PeerId(0), // monoforumPeerId MsgId(i.value())); } context.legacyRead = true; diff --git a/Telegram/SourceFiles/storage/storage_shared_media.cpp b/Telegram/SourceFiles/storage/storage_shared_media.cpp index 0326ad3566..89ce8f6d3b 100644 --- a/Telegram/SourceFiles/storage/storage_shared_media.cpp +++ b/Telegram/SourceFiles/storage/storage_shared_media.cpp @@ -27,6 +27,7 @@ auto SharedMedia::enforceLists(Key key) return SharedMediaSliceUpdate( key.peerId, key.topicRootId, + key.monoforumPeerId, type, update); }) | rpl::start_to_stream(_sliceUpdated, _lifetime); @@ -50,10 +51,20 @@ void SharedMedia::add(SharedMediaAddNew &&query) { if (topicIt != end(_lists)) { addByIt(topicIt); } + const auto monoforumPeerIt = query.monoforumPeerId + ? _lists.find({ query.peerId, MsgId(), query.monoforumPeerId }) + : end(_lists); + if (monoforumPeerIt != end(_lists)) { + addByIt(monoforumPeerIt); + } } void SharedMedia::add(SharedMediaAddExisting &&query) { - auto peerIt = enforceLists({ query.peerId, query.topicRootId }); + auto peerIt = enforceLists({ + query.peerId, + query.topicRootId, + query.monoforumPeerId, + }); for (auto index = 0; index != kSharedMediaTypeCount; ++index) { auto type = static_cast(index); if (query.types.test(type)) { @@ -67,7 +78,11 @@ void SharedMedia::add(SharedMediaAddExisting &&query) { void SharedMedia::add(SharedMediaAddSlice &&query) { Expects(IsValidSharedMediaType(query.type)); - auto peerIt = enforceLists({ query.peerId, query.topicRootId }); + auto peerIt = enforceLists({ + query.peerId, + query.topicRootId, + query.monoforumPeerId, + }); auto index = static_cast(query.type); peerIt->second[index].addSlice( std::move(query.messageIds), @@ -90,11 +105,17 @@ void SharedMedia::remove(SharedMediaRemoveOne &&query) { } void SharedMedia::remove(SharedMediaRemoveAll &&query) { - auto peerIt = _lists.lower_bound({ query.peerId, query.topicRootId }); + auto peerIt = _lists.lower_bound({ + query.peerId, + query.topicRootId, + query.monoforumPeerId, + }); while (peerIt != end(_lists) && peerIt->first.peerId == query.peerId && (!query.topicRootId - || peerIt->first.topicRootId == query.topicRootId)) { + || peerIt->first.topicRootId == query.topicRootId) + && (!query.monoforumPeerId + || peerIt->first.monoforumPeerId == query.monoforumPeerId)) { for (auto index = 0; index != kSharedMediaTypeCount; ++index) { auto type = static_cast(index); if (query.types.test(type)) { @@ -118,13 +139,17 @@ void SharedMedia::invalidate(SharedMediaInvalidateBottom &&query) { } void SharedMedia::unload(SharedMediaUnloadThread &&query) { - _lists.erase({ query.peerId, query.topicRootId }); + _lists.erase({ query.peerId, query.topicRootId, query.monoforumPeerId }); } rpl::producer SharedMedia::query(SharedMediaQuery &&query) const { Expects(IsValidSharedMediaType(query.key.type)); - auto peerIt = _lists.find({ query.key.peerId, query.key.topicRootId }); + auto peerIt = _lists.find({ + query.key.peerId, + query.key.topicRootId, + query.key.monoforumPeerId, + }); if (peerIt != _lists.end()) { auto index = static_cast(query.key.type); return peerIt->second[index].query(SparseIdsListQuery( @@ -141,7 +166,11 @@ rpl::producer SharedMedia::query(SharedMediaQuery &&query) co SharedMediaResult SharedMedia::snapshot(const SharedMediaQuery &query) const { Expects(IsValidSharedMediaType(query.key.type)); - auto peerIt = _lists.find({ query.key.peerId, query.key.topicRootId }); + auto peerIt = _lists.find({ + query.key.peerId, + query.key.topicRootId, + query.key.monoforumPeerId, + }); if (peerIt != _lists.end()) { auto index = static_cast(query.key.type); return peerIt->second[index].snapshot(SparseIdsListQuery( @@ -155,7 +184,11 @@ SharedMediaResult SharedMedia::snapshot(const SharedMediaQuery &query) const { bool SharedMedia::empty(const SharedMediaKey &key) const { Expects(IsValidSharedMediaType(key.type)); - auto peerIt = _lists.find({ key.peerId, key.topicRootId }); + auto peerIt = _lists.find({ + key.peerId, + key.topicRootId, + key.monoforumPeerId, + }); if (peerIt != _lists.end()) { auto index = static_cast(key.type); return peerIt->second[index].empty(); diff --git a/Telegram/SourceFiles/storage/storage_shared_media.h b/Telegram/SourceFiles/storage/storage_shared_media.h index 697bd284c3..09f5cce406 100644 --- a/Telegram/SourceFiles/storage/storage_shared_media.h +++ b/Telegram/SourceFiles/storage/storage_shared_media.h @@ -42,16 +42,19 @@ struct SharedMediaAddNew { SharedMediaAddNew( PeerId peerId, MsgId topicRootId, + PeerId monoforumPeerId, SharedMediaTypesMask types, MsgId messageId) : peerId(peerId) , topicRootId(topicRootId) + , monoforumPeerId(monoforumPeerId) , messageId(messageId) , types(types) { } PeerId peerId = 0; MsgId topicRootId = 0; + PeerId monoforumPeerId = 0; MsgId messageId = 0; SharedMediaTypesMask types; @@ -61,11 +64,13 @@ struct SharedMediaAddExisting { SharedMediaAddExisting( PeerId peerId, MsgId topicRootId, + PeerId monoforumPeerId, SharedMediaTypesMask types, MsgId messageId, MsgRange noSkipRange) : peerId(peerId) , topicRootId(topicRootId) + , monoforumPeerId(monoforumPeerId) , messageId(messageId) , noSkipRange(noSkipRange) , types(types) { @@ -73,6 +78,7 @@ struct SharedMediaAddExisting { PeerId peerId = 0; MsgId topicRootId = 0; + PeerId monoforumPeerId = 0; MsgId messageId = 0; MsgRange noSkipRange; SharedMediaTypesMask types; @@ -83,12 +89,14 @@ struct SharedMediaAddSlice { SharedMediaAddSlice( PeerId peerId, MsgId topicRootId, + PeerId monoforumPeerId, SharedMediaType type, std::vector &&messageIds, MsgRange noSkipRange, std::optional count = std::nullopt) : peerId(peerId) , topicRootId(topicRootId) + , monoforumPeerId(monoforumPeerId) , messageIds(std::move(messageIds)) , noSkipRange(noSkipRange) , type(type) @@ -97,6 +105,7 @@ struct SharedMediaAddSlice { PeerId peerId = 0; MsgId topicRootId = 0; + PeerId monoforumPeerId = 0; std::vector messageIds; MsgRange noSkipRange; SharedMediaType type = SharedMediaType::kCount; @@ -135,9 +144,18 @@ struct SharedMediaRemoveAll { , topicRootId(topicRootId) , types(types) { } + SharedMediaRemoveAll( + PeerId peerId, + PeerId monoforumPeerId, + SharedMediaTypesMask types = SharedMediaTypesMask::All()) + : peerId(peerId) + , monoforumPeerId(monoforumPeerId) + , types(types) { + } PeerId peerId = 0; MsgId topicRootId = 0; + PeerId monoforumPeerId = 0; SharedMediaTypesMask types; }; @@ -154,10 +172,12 @@ struct SharedMediaKey { SharedMediaKey( PeerId peerId, MsgId topicRootId, + PeerId monoforumPeerId, SharedMediaType type, MsgId messageId) : peerId(peerId) , topicRootId(topicRootId) + , monoforumPeerId(monoforumPeerId) , type(type) , messageId(messageId) { } @@ -168,6 +188,7 @@ struct SharedMediaKey { PeerId peerId = 0; MsgId topicRootId = 0; + PeerId monoforumPeerId = 0; SharedMediaType type = SharedMediaType::kCount; MsgId messageId = 0; @@ -195,16 +216,19 @@ struct SharedMediaSliceUpdate { SharedMediaSliceUpdate( PeerId peerId, MsgId topicRootId, + PeerId monoforumPeerId, SharedMediaType type, const SparseIdsSliceUpdate &data) : peerId(peerId) , topicRootId(topicRootId) + , monoforumPeerId(monoforumPeerId) , type(type) , data(data) { } PeerId peerId = 0; MsgId topicRootId = 0; + PeerId monoforumPeerId = 0; SharedMediaType type = SharedMediaType::kCount; SparseIdsSliceUpdate data; }; @@ -212,13 +236,16 @@ struct SharedMediaSliceUpdate { struct SharedMediaUnloadThread { SharedMediaUnloadThread( PeerId peerId, - MsgId topicRootId) + MsgId topicRootId, + PeerId monoforumPeerId) : peerId(peerId) - , topicRootId(topicRootId) { + , topicRootId(topicRootId) + , monoforumPeerId(monoforumPeerId) { } PeerId peerId = 0; MsgId topicRootId = 0; + PeerId monoforumPeerId = 0; }; class SharedMedia { @@ -245,6 +272,7 @@ private: struct Key { PeerId peerId = 0; MsgId topicRootId = 0; + PeerId monoforumPeerId = 0; friend inline constexpr auto operator<=>(Key, Key) = default; }; diff --git a/Telegram/SourceFiles/window/notifications_manager.cpp b/Telegram/SourceFiles/window/notifications_manager.cpp index 36f27e4dc0..58dc24f52a 100644 --- a/Telegram/SourceFiles/window/notifications_manager.cpp +++ b/Telegram/SourceFiles/window/notifications_manager.cpp @@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/notify/data_notify_settings.h" #include "data/stickers/data_custom_emoji.h" #include "data/data_document_media.h" +#include "data/data_saved_sublist.h" #include "data/data_session.h" #include "data/data_channel.h" #include "data/data_forum_topic.h" @@ -349,6 +350,15 @@ void System::registerThread(not_null thread) { clearFromTopic(topic); }, i->second); } + } else if (const auto sublist = thread->asSublist()) { + const auto &[i, ok] = _watchedSublists.emplace( + sublist, + rpl::lifetime()); + if (ok) { + sublist->destroyed() | rpl::start_with_next([=] { + clearFromSublist(sublist); + }, i->second); + } } } @@ -426,6 +436,7 @@ void System::clearAll() { _waiters.clear(); _settingWaiters.clear(); _watchedTopics.clear(); + _watchedSublists.clear(); } void System::clearFromTopic(not_null topic) { @@ -445,6 +456,23 @@ void System::clearFromTopic(not_null topic) { showNext(); } +void System::clearFromSublist(not_null sublist) { + if (_manager) { + _manager->clearFromSublist(sublist); + } + + sublist->clearNotifications(); + _whenMaps.remove(sublist); + _whenAlerts.remove(sublist); + _waiters.remove(sublist); + _settingWaiters.remove(sublist); + + _watchedSublists.remove(sublist); + + _waitTimer.cancel(); + showNext(); +} + void System::clearForThreadIf(Fn)> predicate) { for (auto i = _whenMaps.begin(); i != _whenMaps.end();) { const auto thread = i->first; @@ -460,6 +488,8 @@ void System::clearForThreadIf(Fn)> predicate) { _settingWaiters.remove(thread); if (const auto topic = thread->asTopic()) { _watchedTopics.remove(topic); + } else if (const auto sublist = thread->asSublist()) { + _watchedSublists.remove(sublist); } } const auto clearFrom = [&](auto &map) { @@ -468,6 +498,8 @@ void System::clearForThreadIf(Fn)> predicate) { if (predicate(thread)) { if (const auto topic = thread->asTopic()) { _watchedTopics.remove(topic); + } else if (const auto sublist = thread->asSublist()) { + _watchedSublists.remove(sublist); } i = map.erase(i); } else { @@ -517,6 +549,15 @@ void System::clearIncomingFromTopic(not_null topic) { _whenAlerts.remove(topic); } +void System::clearIncomingFromSublist( + not_null sublist) { + if (_manager) { + _manager->clearFromSublist(sublist); + } + sublist->clearIncomingNotifications(); + _whenAlerts.remove(sublist); +} + void System::clearFromItem(not_null item) { if (_manager) { _manager->clearFromItem(item); @@ -533,6 +574,7 @@ void System::clearAllFast() { _waiters.clear(); _settingWaiters.clear(); _watchedTopics.clear(); + _watchedSublists.clear(); } void System::checkDelayed() { @@ -1114,10 +1156,14 @@ void Manager::notificationActivated( history->peer, id.msgId); const auto topic = item ? item->topic() : nullptr; + const auto sublist = item ? item->savedSublist() : nullptr; if (!options.draft.text.isEmpty()) { const auto topicRootId = topic ? topic->rootId() : id.contextId.topicRootId; + const auto monoforumPeerId = (sublist && sublist->parentChat()) + ? sublist->sublistPeer()->id + : id.contextId.monoforumPeerId; const auto replyToId = (id.msgId > 0 && !history->peer->isUser() && id.msgId != topicRootId) @@ -1129,6 +1175,7 @@ void Manager::notificationActivated( FullReplyTo{ .messageId = replyToId, .topicRootId = topicRootId, + .monoforumPeerId = monoforumPeerId, }, MessageCursor{ length, @@ -1167,13 +1214,13 @@ 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 sublist = item ? item->savedSublist() : nullptr; const auto guard = gsl::finally([&] { if (topic) { system()->clearFromTopic(topic); + } else if (sublist && sublist->parentChat()) { + system()->clearFromSublist(sublist); } else { system()->clearFromHistory(history); } @@ -1256,6 +1303,10 @@ void Manager::notificationReplied( const auto topicRootId = topic ? topic->rootId() : id.contextId.topicRootId; + const auto sublist = item ? item->savedSublist() : nullptr; + const auto monoforumPeerId = (sublist && sublist->parentChat()) + ? sublist->sublistPeer()->id + : id.contextId.monoforumPeerId; auto message = Api::MessageToSend(Api::SendAction(history)); message.textWithTags = reply; @@ -1268,6 +1319,7 @@ void Manager::notificationReplied( message.action.replyTo = { .messageId = { replyToId ? history->peer->id : 0, replyToId }, .topicRootId = topic ? topic->rootId() : 0, + .monoforumPeerId = monoforumPeerId, }; message.action.clearDraft = false; history->session().api().sendMessage(std::move(message)); @@ -1293,16 +1345,21 @@ void NativeManager::doShowNotification(NotificationFields &&fields) { && !reactionFrom && (item->out() || peer->isSelf()) && item->isFromScheduled(); - const auto topicWithChat = [&] { + const auto subWithChat = [&] { const auto name = peer->name(); const auto topic = item->topic(); - return topic ? (topic->title() + u" ("_q + name + ')') : name; + const auto sublist = item->savedSublist(); + return topic + ? (topic->title() + u" ("_q + name + ')') + : (sublist && sublist->parentChat()) + ? (sublist->sublistPeer()->shortName() + u" ("_q + name + ')') + : name; }; const auto title = options.hideNameAndPhoto ? AppName.utf16() : (scheduled && peer->isSelf()) ? tr::lng_notification_reminder(tr::now) - : topicWithChat(); + : subWithChat(); const auto fullTitle = addTargetAccountName(title, &peer->session()); const auto subtitle = reactionFrom ? (reactionFrom != peer ? reactionFrom->name() : QString()) @@ -1341,6 +1398,9 @@ void NativeManager::doShowNotification(NotificationFields &&fields) { doShowNativeNotification({ .peer = item->history()->peer, .topicRootId = item->topicRootId(), + .monoforumPeerId = (item->history()->amMonoforumAdmin() + ? item->sublistPeerId() + : PeerId()), .itemId = item->id, .title = scheduled ? WrapFromScheduled(fullTitle) : fullTitle, .subtitle = subtitle, diff --git a/Telegram/SourceFiles/window/notifications_manager.h b/Telegram/SourceFiles/window/notifications_manager.h index 9caa1dd264..b91afcfca0 100644 --- a/Telegram/SourceFiles/window/notifications_manager.h +++ b/Telegram/SourceFiles/window/notifications_manager.h @@ -17,6 +17,7 @@ class History; namespace Data { class Session; class ForumTopic; +class SavedSublist; class Thread; struct ItemNotification; enum class ItemNotificationType; @@ -109,8 +110,10 @@ public: void checkDelayed(); void schedule(Data::ItemNotification notification); void clearFromTopic(not_null topic); + void clearFromSublist(not_null sublist); void clearFromHistory(not_null history); void clearIncomingFromTopic(not_null topic); + void clearIncomingFromSublist(not_null sublist); void clearIncomingFromHistory(not_null history); void clearFromSession(not_null session); void clearFromItem(not_null item); @@ -221,6 +224,9 @@ private: base::flat_map< not_null, rpl::lifetime> _watchedTopics; + base::flat_map< + not_null, + rpl::lifetime> _watchedSublists; int _lastForwardedCount = 0; uint64 _lastHistorySessionId = 0; @@ -237,6 +243,7 @@ public: uint64 sessionId = 0; PeerId peerId = 0; MsgId topicRootId = 0; + PeerId monoforumPeerId = 0; friend inline auto operator<=>( const ContextId&, @@ -279,6 +286,9 @@ public: void clearFromTopic(not_null topic) { doClearFromTopic(topic); } + void clearFromSublist(not_null sublist) { + doClearFromSublist(sublist); + } void clearFromHistory(not_null history) { doClearFromHistory(history); } @@ -341,6 +351,8 @@ protected: virtual void doClearAllFast() = 0; virtual void doClearFromItem(not_null item) = 0; virtual void doClearFromTopic(not_null topic) = 0; + virtual void doClearFromSublist( + not_null sublist) = 0; virtual void doClearFromHistory(not_null history) = 0; virtual void doClearFromSession(not_null session) = 0; [[nodiscard]] virtual bool doSkipToast() const = 0; @@ -377,6 +389,7 @@ public: struct NotificationInfo { not_null peer; MsgId topicRootId = 0; + PeerId monoforumPeerId = 0; MsgId itemId = 0; QString title; QString subtitle; @@ -426,6 +439,8 @@ protected: } void doClearFromTopic(not_null topic) override { } + void doClearFromSublist(not_null sublist) override { + } void doClearFromHistory(not_null history) override { } void doClearFromSession(not_null session) override { diff --git a/Telegram/SourceFiles/window/notifications_manager_default.cpp b/Telegram/SourceFiles/window/notifications_manager_default.cpp index 44bf48131b..dcfd89dec5 100644 --- a/Telegram/SourceFiles/window/notifications_manager_default.cpp +++ b/Telegram/SourceFiles/window/notifications_manager_default.cpp @@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/painter.h" #include "ui/power_saving.h" #include "ui/ui_utility.h" +#include "data/data_saved_sublist.h" #include "data/data_session.h" #include "data/data_forum_topic.h" #include "data/stickers/data_custom_emoji.h" @@ -236,6 +237,7 @@ void Manager::showNextFromQueue() { this, queued.history, queued.topicRootId, + queued.monoforumPeerId, queued.peer, queued.author, queued.item, @@ -383,7 +385,25 @@ void Manager::doClearFromTopic(not_null topic) { } } for (const auto ¬ification : _notifications) { - if (notification->unlinkHistory(history, topicRootId)) { + if (notification->unlinkHistory(history, topicRootId, PeerId())) { + _positionsOutdated = true; + } + } + showNextFromQueue(); +} + +void Manager::doClearFromSublist(not_null sublist) { + const auto history = sublist->owningHistory(); + const auto sublistPeerId = sublist->sublistPeer()->id; + for (auto i = _queuedNotifications.begin(); i != _queuedNotifications.cend();) { + if (i->history == history && i->monoforumPeerId == sublistPeerId) { + i = _queuedNotifications.erase(i); + } else { + ++i; + } + } + for (const auto ¬ification : _notifications) { + if (notification->unlinkHistory(history, MsgId(), sublistPeerId)) { _positionsOutdated = true; } } @@ -618,6 +638,7 @@ Notification::Notification( not_null manager, not_null history, MsgId topicRootId, + PeerId monoforumPeerId, not_null peer, const QString &author, HistoryItem *item, @@ -633,6 +654,8 @@ Notification::Notification( , _history(history) , _topic(history->peer->forumTopicFor(topicRootId)) , _topicRootId(topicRootId) +, _sublist(history->peer->monoforumSublistFor(monoforumPeerId)) +, _monoforumPeerId(monoforumPeerId) , _userpicView(_peer->createUserpicView()) , _author(author) , _reaction(reaction) @@ -1149,10 +1172,14 @@ void Notification::changeHeight(int newHeight) { manager()->changeNotificationHeight(this, newHeight); } -bool Notification::unlinkHistory(History *history, MsgId topicRootId) { +bool Notification::unlinkHistory( + History *history, + MsgId topicRootId, + PeerId monoforumPeerId) { const auto unlink = _history && (history == _history || !history) - && (topicRootId == _topicRootId || !topicRootId); + && (topicRootId == _topicRootId || !topicRootId) + && (monoforumPeerId == _monoforumPeerId || !monoforumPeerId); if (unlink) { hideFast(); _history = nullptr; diff --git a/Telegram/SourceFiles/window/notifications_manager_default.h b/Telegram/SourceFiles/window/notifications_manager_default.h index 7c81282355..219ce8d83a 100644 --- a/Telegram/SourceFiles/window/notifications_manager_default.h +++ b/Telegram/SourceFiles/window/notifications_manager_default.h @@ -70,6 +70,7 @@ private: void doClearAll() override; void doClearAllFast() override; void doClearFromTopic(not_null topic) override; + void doClearFromSublist(not_null sublist) override; void doClearFromHistory(not_null history) override; void doClearFromSession(not_null session) override; void doClearFromItem(not_null item) override; @@ -111,6 +112,7 @@ private: not_null history; MsgId topicRootId = 0; + PeerId monoforumPeerId = 0; not_null peer; Data::ReactionId reaction; QString author; @@ -203,6 +205,7 @@ public: not_null manager, not_null history, MsgId topicRootId, + PeerId monoforumPeerId, not_null peer, const QString &author, HistoryItem *item, @@ -231,7 +234,10 @@ public: // Called only by Manager. bool unlinkItem(HistoryItem *del); - bool unlinkHistory(History *history = nullptr, MsgId topicRootId = 0); + bool unlinkHistory( + History *history = nullptr, + MsgId topicRootId = 0, + PeerId monoforumPeerId = 0); bool unlinkSession(not_null session); bool checkLastInput( bool hasReplyingNotifications, @@ -285,6 +291,8 @@ private: History *_history = nullptr; Data::ForumTopic *_topic = nullptr; MsgId _topicRootId = 0; + Data::SavedSublist *_sublist = nullptr; + PeerId _monoforumPeerId = 0; Ui::PeerUserpicView _userpicView; QString _author; Data::ReactionId _reaction; diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 183526a0a7..fc68d80a5a 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -3040,14 +3040,18 @@ void HidePinnedBar( not_null navigation, not_null peer, MsgId topicRootId, + PeerId monoforumPeerId, Fn onHidden) { const auto callback = crl::guard(navigation, [=](Fn &&close) { close(); auto &session = peer->session(); - const auto migrated = topicRootId ? nullptr : peer->migrateFrom(); + const auto migrated = (topicRootId || monoforumPeerId) + ? nullptr + : peer->migrateFrom(); const auto top = Data::ResolveTopPinnedId( peer, topicRootId, + monoforumPeerId, migrated); const auto universal = !top ? MsgId(0) @@ -3058,6 +3062,7 @@ void HidePinnedBar( session.settings().setHiddenPinnedMessageId( peer->id, topicRootId, + monoforumPeerId, universal); session.saveSettingsDelayed(); if (onHidden) { @@ -3091,6 +3096,7 @@ void UnpinAllMessages( const auto history = strong->owningHistory(); const auto topicRootId = strong->topicRootId(); const auto sublist = strong->asSublist(); + const auto monoforumPeerId = strong->monoforumPeerId(); using Flag = MTPmessages_UnpinAllMessages::Flag; api->request(MTPmessages_UnpinAllMessages( MTP_flags((topicRootId ? Flag::f_top_msg_id : Flag()) @@ -3104,7 +3110,7 @@ void UnpinAllMessages( if (offset > 0) { self(self); } else { - history->unpinMessagesFor(topicRootId); + history->unpinMessagesFor(topicRootId, monoforumPeerId); } }).send(); }; diff --git a/Telegram/SourceFiles/window/window_peer_menu.h b/Telegram/SourceFiles/window/window_peer_menu.h index 06c5ce626c..15435b34ba 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.h +++ b/Telegram/SourceFiles/window/window_peer_menu.h @@ -218,6 +218,7 @@ void HidePinnedBar( not_null navigation, not_null peer, MsgId topicRootId, + PeerId monoforumPeerId, Fn onHidden); void UnpinAllMessages( not_null navigation, diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 1fe5d152cc..5a49bab04d 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -2927,8 +2927,12 @@ void SessionController::openPhoto( if (openSharedStory(item) || openFakeItemStory(message.id, stories)) { return; } - _window->openInMediaView( - Media::View::OpenRequest(this, photo, item, message.topicRootId)); + _window->openInMediaView(Media::View::OpenRequest( + this, + photo, + item, + message.topicRootId, + message.monoforumPeerId)); } void SessionController::openPhoto( @@ -2963,11 +2967,17 @@ void SessionController::openDocument( document, item, message.topicRootId, + message.monoforumPeerId, false, usedTimestamp)); return; } - Data::ResolveDocument(this, document, item, message.topicRootId); + Data::ResolveDocument( + this, + document, + item, + message.topicRootId, + message.monoforumPeerId); } bool SessionController::openSharedStory(HistoryItem *item) { diff --git a/Telegram/SourceFiles/window/window_session_controller.h b/Telegram/SourceFiles/window/window_session_controller.h index 86b1e6f3be..fdeef9a221 100644 --- a/Telegram/SourceFiles/window/window_session_controller.h +++ b/Telegram/SourceFiles/window/window_session_controller.h @@ -523,6 +523,7 @@ public: struct MessageContext { FullMsgId id; MsgId topicRootId; + PeerId monoforumPeerId; }; void openPhoto( not_null photo,