mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-07-11 16:22:55 +02:00
Support shared media / pins for sublists.
This commit is contained in:
parent
ffe6786ad1
commit
dfc1ec3ccf
83 changed files with 1105 additions and 221 deletions
|
@ -2978,17 +2978,27 @@ void ApiWrap::resolveJumpToDate(
|
|||
Fn<void(not_null<PeerData*>, 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 <typename Callback>
|
||||
void ApiWrap::requestMessageAfterDate(
|
||||
not_null<PeerData*> peer,
|
||||
MsgId topicRootId,
|
||||
const QDate &date,
|
||||
Callback &&callback) {
|
||||
not_null<PeerData*> 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<PeerData*> peer,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
const QDate &date,
|
||||
Fn<void(not_null<PeerData*>, 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<PeerData*> 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<PeerData*> 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();
|
||||
|
|
|
@ -289,6 +289,7 @@ public:
|
|||
void requestSharedMedia(
|
||||
not_null<PeerData*> peer,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
Storage::SharedMediaType type,
|
||||
MsgId messageId,
|
||||
SliceType slice);
|
||||
|
@ -505,18 +506,21 @@ private:
|
|||
void resolveJumpToHistoryDate(
|
||||
not_null<PeerData*> peer,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
const QDate &date,
|
||||
Fn<void(not_null<PeerData*>, MsgId)> callback);
|
||||
template <typename Callback>
|
||||
void requestMessageAfterDate(
|
||||
not_null<PeerData*> peer,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
const QDate &date,
|
||||
Callback &&callback);
|
||||
|
||||
void sharedMediaDone(
|
||||
not_null<PeerData*> peer,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
SharedMediaType type,
|
||||
Api::SearchResult &&parsed);
|
||||
void globalMediaDone(
|
||||
|
@ -665,6 +669,7 @@ private:
|
|||
struct SharedMediaRequest {
|
||||
not_null<PeerData*> peer;
|
||||
MsgId topicRootId = 0;
|
||||
PeerId monoforumPeerId = 0;
|
||||
SharedMediaType mediaType = {};
|
||||
MsgId aroundId = 0;
|
||||
SliceType sliceType = {};
|
||||
|
|
|
@ -24,10 +24,15 @@ namespace {
|
|||
[[nodiscard]] bool IsOldForPin(
|
||||
MsgId id,
|
||||
not_null<PeerData*> 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<State>();
|
||||
const auto api = box->lifetime().make_state<MTP::Sender>(
|
||||
&peer->session().mtp());
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -187,7 +187,8 @@ void ResolveDocument(
|
|||
Window::SessionController *controller,
|
||||
not_null<DocumentData*> 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 });
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ void ResolveDocument(
|
|||
Window::SessionController *controller,
|
||||
not_null<DocumentData*> document,
|
||||
HistoryItem *item,
|
||||
MsgId topicRootId);
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId);
|
||||
|
||||
} // namespace Data
|
||||
|
|
|
@ -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(), {});
|
||||
}
|
||||
|
||||
|
|
|
@ -152,6 +152,7 @@ rpl::producer<SparseIdsMergedSlice> HistoryMergedViewer(
|
|||
auto createSimpleViewer = [=](
|
||||
PeerId peerId,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
SparseIdsSlice::Key simpleKey,
|
||||
int limitBefore,
|
||||
int limitAfter) {
|
||||
|
@ -161,11 +162,10 @@ rpl::producer<SparseIdsMergedSlice> 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));
|
||||
|
|
|
@ -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<PeerData*> 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<PeerData*> 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,
|
||||
|
|
|
@ -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<PeerData*> peer,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
PeerData *migrated = nullptr);
|
||||
[[nodiscard]] FullMsgId ResolveMinPinnedId(
|
||||
not_null<PeerData*> peer,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
PeerData *migrated = nullptr);
|
||||
|
||||
} // namespace Data
|
||||
|
|
|
@ -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<PeerData*> 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<not_null<PeerData*>>();
|
||||
auto peerIds = QVector<MTPInputPeer>();
|
||||
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<void()> finish) {
|
||||
using Flag = MTPmessages_GetSavedDialogsByID::Flag;
|
||||
return session().api().request(
|
||||
MTPmessages_GetSavedDialogsByID(
|
||||
MTP_flags(Flag::f_parent_peer),
|
||||
_parentChat->input,
|
||||
MTP_vector<MTPInputPeer>(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<PeerData*> peer) {
|
||||
if (const auto request = _sublistRequests.take(peer)) {
|
||||
for (const auto &callback : request->callbacks) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SavedMessages::requestSublist(
|
||||
not_null<PeerData*> peer,
|
||||
Fn<void()> 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<MTPSavedDialog>*)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<PeerData*> 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<PeerData*> 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, {});
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Dialogs::MainList*> chatsList();
|
||||
[[nodiscard]] not_null<SavedSublist*> sublist(not_null<PeerData*> peer);
|
||||
[[nodiscard]] SavedSublist *sublistLoaded(not_null<PeerData*> peer);
|
||||
void requestSublist(not_null<PeerData*> peer, Fn<void()> done = nullptr);
|
||||
|
||||
[[nodiscard]] rpl::producer<> chatsListChanges() const;
|
||||
[[nodiscard]] rpl::producer<> chatsListLoadedEvents() const;
|
||||
|
@ -59,13 +70,31 @@ public:
|
|||
[[nodiscard]] auto recentSublists() const
|
||||
-> const std::vector<not_null<SavedSublist*>> &;
|
||||
|
||||
void clear();
|
||||
|
||||
[[nodiscard]] rpl::lifetime &lifetime();
|
||||
|
||||
private:
|
||||
struct SublistRequest {
|
||||
mtpRequestId id = 0;
|
||||
std::vector<Fn<void()>> 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<PeerData*> peer);
|
||||
|
||||
void sendLoadMore();
|
||||
void sendLoadMoreRequests();
|
||||
|
@ -80,13 +109,14 @@ private:
|
|||
base::flat_map<
|
||||
not_null<PeerData*>,
|
||||
std::unique_ptr<SavedSublist>> _sublists;
|
||||
base::flat_map<not_null<PeerData*>, SublistRequest> _sublistRequests;
|
||||
base::flat_set<not_null<PeerData*>> _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;
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -132,6 +132,7 @@ GlobalMediaResult ParseGlobalMediaResult(
|
|||
std::optional<SearchRequest> PrepareSearchRequest(
|
||||
not_null<PeerData*> peer,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
Storage::SharedMediaType type,
|
||||
const QString &query,
|
||||
MsgId messageId,
|
||||
|
@ -168,11 +169,14 @@ std::optional<SearchRequest> 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<MTPReaction>(), // saved_reaction
|
||||
MTP_int(topicRootId),
|
||||
filter,
|
||||
|
@ -369,12 +373,14 @@ rpl::producer<SparseIdsMergedSlice> 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<SparseIdsMergedSlice> SearchController::idsSlice(
|
|||
SparseIdsMergedSlice::Key(
|
||||
query.peerId,
|
||||
query.topicRootId,
|
||||
query.monoforumPeerId,
|
||||
query.migratedPeerId,
|
||||
aroundId),
|
||||
limitBefore,
|
||||
|
@ -394,6 +401,7 @@ rpl::producer<SparseIdsMergedSlice> SearchController::idsSlice(
|
|||
rpl::producer<SparseIdsSlice> SearchController::simpleIdsSlice(
|
||||
PeerId peerId,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
MsgId aroundId,
|
||||
const Query &query,
|
||||
int limitBefore,
|
||||
|
@ -402,8 +410,12 @@ rpl::producer<SparseIdsSlice> 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<SparseIdsSlice> SearchController::simpleIdsSlice(
|
|||
_session->data().itemRemoved(
|
||||
) | rpl::filter([=](not_null<const HistoryItem*> item) {
|
||||
return (item->history()->peer->id == peerId)
|
||||
&& (!topicRootId || item->topicRootId() == topicRootId);
|
||||
&& (!topicRootId || item->topicRootId() == topicRootId)
|
||||
&& (!monoforumPeerId
|
||||
|| item->sublistPeerId() == monoforumPeerId);
|
||||
}) | rpl::filter([=](not_null<const HistoryItem*> 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,
|
||||
|
|
|
@ -61,6 +61,7 @@ struct GlobalMediaResult {
|
|||
[[nodiscard]] std::optional<SearchRequest> PrepareSearchRequest(
|
||||
not_null<PeerData*> 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<SparseIdsSlice> simpleIdsSlice(
|
||||
PeerId peerId,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
MsgId aroundId,
|
||||
const Query &query,
|
||||
int limitBefore,
|
||||
|
|
|
@ -404,6 +404,7 @@ void Session::clear() {
|
|||
channel->setFlags(channel->flags()
|
||||
& ~(ChannelDataFlag::Forum | ChannelDataFlag::MonoforumAdmin));
|
||||
}
|
||||
_savedMessages->clear();
|
||||
|
||||
_sendActionManager->clear();
|
||||
|
||||
|
|
|
@ -110,11 +110,13 @@ rpl::producer<SparseIdsSlice> 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<SparseIdsSlice> 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<SparseIdsSlice> 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<SparseIdsMergedSlice> SharedMediaMergedViewer(
|
|||
auto createSimpleViewer = [=](
|
||||
PeerId peerId,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
SparseIdsSlice::Key simpleKey,
|
||||
int limitBefore,
|
||||
int limitAfter) {
|
||||
|
@ -244,6 +250,7 @@ rpl::producer<SparseIdsMergedSlice> SharedMediaMergedViewer(
|
|||
Storage::SharedMediaKey(
|
||||
peerId,
|
||||
topicRootId,
|
||||
monoforumPeerId,
|
||||
key.type,
|
||||
simpleKey),
|
||||
limitBefore,
|
||||
|
|
|
@ -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<MessageId>(key.universalId)
|
||||
? v::get<MessageId>(key.universalId)
|
||||
|
@ -130,6 +134,7 @@ public:
|
|||
return {
|
||||
key.peerId,
|
||||
key.topicRootId,
|
||||
key.monoforumPeerId,
|
||||
key.migratedPeerId,
|
||||
ServerMaxMsgId - 1
|
||||
};
|
||||
|
|
|
@ -377,7 +377,10 @@ rpl::producer<SparseIdsMergedSlice> SparseIdsMergedSlice::CreateViewer(
|
|||
int limitBefore,
|
||||
int limitAfter,
|
||||
Fn<SimpleViewerFunction> 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> SparseIdsMergedSlice::CreateViewer(
|
|||
auto partViewer = simpleViewer(
|
||||
key.peerId,
|
||||
key.topicRootId,
|
||||
key.monoforumPeerId,
|
||||
SparseIdsMergedSlice::PartKey(key),
|
||||
limitBefore,
|
||||
limitAfter
|
||||
|
@ -405,6 +409,7 @@ rpl::producer<SparseIdsMergedSlice> SparseIdsMergedSlice::CreateViewer(
|
|||
auto migratedViewer = simpleViewer(
|
||||
key.migratedPeerId,
|
||||
MsgId(0), // topicRootId
|
||||
PeerId(0), // monoforumPeerId
|
||||
SparseIdsMergedSlice::MigratedKey(key),
|
||||
limitBefore,
|
||||
limitAfter);
|
||||
|
|
|
@ -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<SparseIdsSlice>(
|
||||
PeerId peerId,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
SparseIdsSlice::Key simpleKey,
|
||||
int limitBefore,
|
||||
int limitAfter);
|
||||
|
|
|
@ -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() };
|
||||
|
|
|
@ -651,8 +651,38 @@ void History::destroyMessagesBySublist(not_null<PeerData*> 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<HistoryItem*> 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<HistoryItem*> 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<HistoryItem*> 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<Data::Thread*>(this)
|
||||
: peer->monoforum()
|
||||
? peer->monoforum()->sublistLoaded(owner().peer(monoforumPeerId))
|
||||
: nullptr;
|
||||
: monoforumPeerId
|
||||
? peer->monoforumSublistFor(monoforumPeerId)
|
||||
: static_cast<Data::Thread*>(this);
|
||||
}
|
||||
|
||||
const Data::Thread *History::threadFor(
|
||||
|
|
|
@ -141,7 +141,7 @@ public:
|
|||
void destroyMessagesByTopic(MsgId topicRootId);
|
||||
void destroyMessagesBySublist(not_null<PeerData*> sublistPeer);
|
||||
|
||||
void unpinMessagesFor(MsgId topicRootId);
|
||||
void unpinMessagesFor(MsgId topicRootId, PeerId monoforumPeerId);
|
||||
|
||||
not_null<HistoryItem*> addNewMessage(
|
||||
MsgId id,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,7 +151,7 @@ void ChatMemento::setFromTopic(not_null<Data::ForumTopic*> 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<DocumentData*> document) {
|
|||
void ChatWidget::listOpenPhoto(
|
||||
not_null<PhotoData*> 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(
|
||||
|
|
|
@ -394,6 +394,7 @@ private:
|
|||
rpl::variable<bool> _areComments = false;
|
||||
|
||||
Data::SavedSublist *_sublist = nullptr;
|
||||
PeerId _monoforumPeerId;
|
||||
|
||||
std::shared_ptr<SendActionPainter> _sendAction;
|
||||
std::shared_ptr<Ui::ChatTheme> _theme;
|
||||
|
|
|
@ -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<Data::MessagesSlice> PinnedWidget::listSource(
|
|||
SparseIdsMergedSlice::Key(
|
||||
_history->peer->id,
|
||||
_thread->topicRootId(),
|
||||
_thread->monoforumPeerId(),
|
||||
_migratedPeer ? _migratedPeer->id : 0,
|
||||
messageId),
|
||||
Storage::SharedMediaType::Pinned),
|
||||
|
|
|
@ -86,6 +86,7 @@ void PinnedTracker::refreshViewer() {
|
|||
SparseIdsMergedSlice::Key(
|
||||
peer->id,
|
||||
_thread->topicRootId(),
|
||||
_thread->monoforumPeerId(),
|
||||
_migratedPeer ? _migratedPeer->id : 0,
|
||||
_viewerAroundId),
|
||||
Storage::SharedMediaType::Pinned),
|
||||
|
|
|
@ -751,7 +751,7 @@ void TopBarWidget::infoClicked() {
|
|||
_controller->showSection(std::make_shared<Info::Memento>(topic));
|
||||
} else if (const auto sublist = key.sublist()) {
|
||||
_controller->showSection(std::make_shared<Info::Memento>(
|
||||
sublist->owningHistory()->peer,
|
||||
sublist,
|
||||
Info::Section(Storage::SharedMediaType::Photo)));
|
||||
} else if (key.peer()->savedSublistsInfo()) {
|
||||
_controller->showSection(std::make_shared<Info::Memento>(
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace Info {
|
|||
namespace CommonGroups {
|
||||
|
||||
Memento::Memento(not_null<UserData*> user)
|
||||
: ContentMemento(user, nullptr, PeerId()) {
|
||||
: ContentMemento(user, nullptr, nullptr, PeerId()) {
|
||||
}
|
||||
|
||||
Section Memento::section() const {
|
||||
|
|
|
@ -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<Ui::RpWidget*> 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<PeerData*> 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) {
|
||||
|
|
|
@ -210,6 +210,7 @@ public:
|
|||
ContentMemento(
|
||||
not_null<PeerData*> 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 = {};
|
||||
|
|
|
@ -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<PeerData*> peer) : _value(peer) {
|
|||
Key::Key(not_null<Data::ForumTopic*> topic) : _value(topic) {
|
||||
}
|
||||
|
||||
Key::Key(not_null<Data::SavedSublist*> 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<not_null<Data::SavedSublist*>>(
|
||||
&_value)) {
|
||||
return *sublist;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UserData *Key::settingsSelf() const {
|
||||
if (const auto tag = std::get_if<Settings::Tag>(&_value)) {
|
||||
return tag->self;
|
||||
|
@ -195,6 +210,7 @@ rpl::producer<SparseIdsMergedSlice> AbstractController::mediaSource(
|
|||
SparseIdsMergedSlice::Key(
|
||||
peer()->id,
|
||||
topicId,
|
||||
sublist() ? sublist()->sublistPeer()->id : PeerId(),
|
||||
migratedPeerId(),
|
||||
aroundId),
|
||||
section().mediaType()),
|
||||
|
@ -487,6 +503,7 @@ rpl::producer<SparseIdsMergedSlice> Controller::mediaSource(
|
|||
SparseIdsMergedSlice::Key(
|
||||
query.peerId,
|
||||
query.topicRootId,
|
||||
query.monoforumPeerId,
|
||||
query.migratedPeerId,
|
||||
aroundId),
|
||||
query.type),
|
||||
|
|
|
@ -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<PeerData*> peer);
|
||||
explicit Key(not_null<Data::ForumTopic*> topic);
|
||||
explicit Key(not_null<Data::SavedSublist*> 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<PeerData*>,
|
||||
not_null<Data::ForumTopic*>,
|
||||
not_null<Data::SavedSublist*>,
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -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<Data::ForumTopic*> topic, Section section)
|
|||
: Memento(DefaultStack(topic, section)) {
|
||||
}
|
||||
|
||||
Memento::Memento(not_null<Data::SavedSublist*> sublist)
|
||||
: Memento(sublist, Section::Type::Profile) {
|
||||
}
|
||||
|
||||
Memento::Memento(not_null<Data::SavedSublist*> 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<std::shared_ptr<ContentMemento>> stack)
|
||||
: _stack(std::move(stack)) {
|
||||
auto topics = base::flat_set<not_null<Data::ForumTopic*>>();
|
||||
auto sublists = base::flat_set<not_null<Data::SavedSublist*>>();
|
||||
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<std::shared_ptr<ContentMemento>> 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<std::shared_ptr<ContentMemento>> Memento::DefaultStack(
|
||||
|
@ -104,6 +131,14 @@ std::vector<std::shared_ptr<ContentMemento>> Memento::DefaultStack(
|
|||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<ContentMemento>> Memento::DefaultStack(
|
||||
not_null<Data::SavedSublist*> sublist,
|
||||
Section section) {
|
||||
auto result = std::vector<std::shared_ptr<ContentMemento>>();
|
||||
result.push_back(DefaultContent(sublist, section));
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<ContentMemento>> Memento::DefaultStack(
|
||||
Settings::Tag settings,
|
||||
Section section) {
|
||||
|
@ -205,6 +240,20 @@ std::shared_ptr<ContentMemento> Memento::DefaultContent(
|
|||
Unexpected("Wrong section type in Info::Memento::DefaultContent()");
|
||||
}
|
||||
|
||||
std::shared_ptr<ContentMemento> Memento::DefaultContent(
|
||||
not_null<Data::SavedSublist*> sublist,
|
||||
Section section) {
|
||||
switch (section.type()) {
|
||||
case Section::Type::Profile:
|
||||
return std::make_shared<Profile::Memento>(sublist);
|
||||
case Section::Type::Media:
|
||||
return std::make_shared<Media::Memento>(
|
||||
sublist,
|
||||
section.mediaType());
|
||||
}
|
||||
Unexpected("Wrong section type in Info::Memento::DefaultContent()");
|
||||
}
|
||||
|
||||
object_ptr<Window::SectionWidget> Memento::createWidget(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller,
|
||||
|
|
|
@ -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<PeerData*> peer, Section section);
|
||||
explicit Memento(not_null<Data::ForumTopic*> topic);
|
||||
Memento(not_null<Data::ForumTopic*> topic, Section section);
|
||||
explicit Memento(not_null<Data::SavedSublist*> sublist);
|
||||
Memento(not_null<Data::SavedSublist*> sublist, Section section);
|
||||
Memento(Settings::Tag settings, Section section);
|
||||
Memento(not_null<PollData*> poll, FullMsgId contextId);
|
||||
Memento(
|
||||
|
@ -94,6 +97,9 @@ private:
|
|||
static std::vector<std::shared_ptr<ContentMemento>> DefaultStack(
|
||||
not_null<Data::ForumTopic*> topic,
|
||||
Section section);
|
||||
static std::vector<std::shared_ptr<ContentMemento>> DefaultStack(
|
||||
not_null<Data::SavedSublist*> sublist,
|
||||
Section section);
|
||||
static std::vector<std::shared_ptr<ContentMemento>> DefaultStack(
|
||||
Settings::Tag settings,
|
||||
Section section);
|
||||
|
@ -111,6 +117,9 @@ private:
|
|||
static std::shared_ptr<ContentMemento> DefaultContent(
|
||||
not_null<Data::ForumTopic*> topic,
|
||||
Section section);
|
||||
static std::shared_ptr<ContentMemento> DefaultContent(
|
||||
not_null<Data::SavedSublist*> sublist,
|
||||
Section section);
|
||||
|
||||
std::vector<std::shared_ptr<ContentMemento>> _stack;
|
||||
rpl::event_stream<> _removeRequests;
|
||||
|
|
|
@ -147,12 +147,18 @@ not_null<Ui::SettingsButton*> AddButton(
|
|||
not_null<Window::SessionNavigation*> navigation,
|
||||
not_null<PeerData*> 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);
|
||||
|
|
|
@ -42,6 +42,7 @@ using Type = Storage::SharedMediaType;
|
|||
not_null<Window::SessionNavigation*> navigation,
|
||||
not_null<PeerData*> peer,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
PeerData *migrated,
|
||||
Type type,
|
||||
Ui::MultiSlideTracker &tracker);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<PhotoData*> 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;
|
||||
}
|
||||
|
|
|
@ -158,6 +158,7 @@ private:
|
|||
void setupSelectRestriction();
|
||||
|
||||
[[nodiscard]] MsgId topicRootId() const;
|
||||
[[nodiscard]] PeerId monoforumPeerId() const;
|
||||
|
||||
QMargins padding() const;
|
||||
bool isItemLayout(
|
||||
|
|
|
@ -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<AbstractController*> 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<const HistoryItem*> item) {
|
||||
|
|
|
@ -105,6 +105,7 @@ private:
|
|||
|
||||
const not_null<PeerData*> _peer;
|
||||
const MsgId _topicRootId = 0;
|
||||
const PeerId _monoforumPeerId = 0;
|
||||
PeerData * const _migrated = nullptr;
|
||||
const Type _type = Type::Photo;
|
||||
|
||||
|
|
|
@ -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)
|
|||
? 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*> controller)
|
|||
}
|
||||
|
||||
Memento::Memento(not_null<PeerData*> peer, PeerId migratedPeerId, Type type)
|
||||
: Memento(peer, nullptr, migratedPeerId, type) {
|
||||
: Memento(peer, nullptr, nullptr, migratedPeerId, type) {
|
||||
}
|
||||
|
||||
Memento::Memento(not_null<Data::ForumTopic*> topic, Type type)
|
||||
: Memento(topic->channel(), topic, PeerId(), type) {
|
||||
: Memento(topic->channel(), topic, nullptr, PeerId(), type) {
|
||||
}
|
||||
|
||||
Memento::Memento(not_null<Data::SavedSublist*> sublist, Type type)
|
||||
: Memento(sublist->owningHistory()->peer, nullptr, sublist, PeerId(), type) {
|
||||
}
|
||||
|
||||
Memento::Memento(
|
||||
not_null<PeerData*> 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();
|
||||
|
|
|
@ -35,6 +35,7 @@ public:
|
|||
explicit Memento(not_null<Controller*> controller);
|
||||
Memento(not_null<PeerData*> peer, PeerId migratedPeerId, Type type);
|
||||
Memento(not_null<Data::ForumTopic*> topic, Type type);
|
||||
Memento(not_null<Data::SavedSublist*> sublist, Type type);
|
||||
|
||||
using SearchState = Api::DelayedSearchController::SavedState;
|
||||
|
||||
|
@ -92,6 +93,7 @@ private:
|
|||
Memento(
|
||||
not_null<PeerData*> peer,
|
||||
Data::ForumTopic *topic,
|
||||
Data::SavedSublist *sublist,
|
||||
PeerId migratedPeerId,
|
||||
Type type);
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ Memento::Memento(not_null<Controller*> controller)
|
|||
}
|
||||
|
||||
Memento::Memento(not_null<PeerData*> peer, PeerId migratedPeerId)
|
||||
: ContentMemento(peer, nullptr, migratedPeerId) {
|
||||
: ContentMemento(peer, nullptr, nullptr, migratedPeerId) {
|
||||
}
|
||||
|
||||
Section Memento::section() const {
|
||||
|
|
|
@ -678,7 +678,7 @@ void InnerWidget::restoreState(not_null<Memento*> memento) {
|
|||
}
|
||||
|
||||
Memento::Memento(not_null<PeerData*> peer)
|
||||
: ContentMemento(peer, nullptr, PeerId()) {
|
||||
: ContentMemento(peer, nullptr, nullptr, PeerId()) {
|
||||
}
|
||||
|
||||
Section Memento::section() const {
|
||||
|
|
|
@ -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<Ui::RpWidget> 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<Ui::RpWidget> InnerWidget::setupSharedMedia(
|
|||
content,
|
||||
_controller,
|
||||
_peer,
|
||||
_topic ? _topic->rootId() : 0,
|
||||
_topic ? _topic->rootId() : MsgId(),
|
||||
_sublist ? _sublist->sublistPeer()->id : PeerId(),
|
||||
_migrated,
|
||||
type,
|
||||
tracker);
|
||||
|
|
|
@ -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<PeerData*> _peer;
|
||||
PeerData * const _migrated = nullptr;
|
||||
Data::ForumTopic * const _topic = nullptr;
|
||||
Data::SavedSublist * const _sublist = nullptr;
|
||||
|
||||
PeerData *_reactionGroup = nullptr;
|
||||
|
||||
|
|
|
@ -543,6 +543,7 @@ rpl::producer<int> KickedCountValue(not_null<ChannelData*> channel) {
|
|||
rpl::producer<int> SharedMediaCountValue(
|
||||
not_null<PeerData*> peer,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
PeerData *migrated,
|
||||
Storage::SharedMediaType type) {
|
||||
auto aroundId = 0;
|
||||
|
@ -553,6 +554,7 @@ rpl::producer<int> SharedMediaCountValue(
|
|||
SparseIdsMergedSlice::Key(
|
||||
peer->id,
|
||||
topicRootId,
|
||||
monoforumPeerId,
|
||||
migrated ? migrated->id : 0,
|
||||
aroundId),
|
||||
type),
|
||||
|
|
|
@ -113,6 +113,7 @@ struct LinkWithUrl {
|
|||
[[nodiscard]] rpl::producer<int> SharedMediaCountValue(
|
||||
not_null<PeerData*> peer,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
PeerData *migrated,
|
||||
Storage::SharedMediaType type);
|
||||
[[nodiscard]] rpl::producer<int> CommonGroupsCountValue(
|
||||
|
|
|
@ -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*> controller)
|
|||
: Memento(
|
||||
controller->peer(),
|
||||
controller->topic(),
|
||||
controller->sublist(),
|
||||
controller->migratedPeerId(),
|
||||
{ v::null }) {
|
||||
}
|
||||
|
@ -33,20 +36,25 @@ Memento::Memento(
|
|||
not_null<PeerData*> peer,
|
||||
PeerId migratedPeerId,
|
||||
Origin origin)
|
||||
: Memento(peer, nullptr, migratedPeerId, origin) {
|
||||
: Memento(peer, nullptr, nullptr, migratedPeerId, origin) {
|
||||
}
|
||||
|
||||
Memento::Memento(
|
||||
not_null<PeerData*> 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<Data::ForumTopic*> topic)
|
||||
: ContentMemento(topic->channel(), topic, 0) {
|
||||
: ContentMemento(topic->channel(), topic, nullptr, 0) {
|
||||
}
|
||||
|
||||
Memento::Memento(not_null<Data::SavedSublist*> sublist)
|
||||
: ContentMemento(sublist->owningHistory()->peer, nullptr, sublist, 0) {
|
||||
}
|
||||
|
||||
Section Memento::section() const {
|
||||
|
|
|
@ -35,6 +35,7 @@ public:
|
|||
PeerId migratedPeerId,
|
||||
Origin origin = { v::null });
|
||||
explicit Memento(not_null<Data::ForumTopic*> topic);
|
||||
explicit Memento(not_null<Data::SavedSublist*> sublist);
|
||||
|
||||
object_ptr<ContentWidget> createWidget(
|
||||
QWidget *parent,
|
||||
|
@ -56,6 +57,7 @@ private:
|
|||
Memento(
|
||||
not_null<PeerData*> peer,
|
||||
Data::ForumTopic *topic,
|
||||
Data::SavedSublist *sublist,
|
||||
PeerId migratedPeerId,
|
||||
Origin origin);
|
||||
|
||||
|
|
|
@ -188,7 +188,7 @@ std::shared_ptr<Main::SessionShow> InnerWidget::peerListUiShow() {
|
|||
}
|
||||
|
||||
Memento::Memento(not_null<PeerData*> peer)
|
||||
: ContentMemento(peer, nullptr, PeerId()) {
|
||||
: ContentMemento(peer, nullptr, nullptr, PeerId()) {
|
||||
}
|
||||
|
||||
Section Memento::section() const {
|
||||
|
|
|
@ -29,7 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
namespace Info::Saved {
|
||||
|
||||
SublistsMemento::SublistsMemento(not_null<Main::Session*> 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);
|
||||
|
|
|
@ -438,7 +438,7 @@ std::shared_ptr<Main::SessionShow> InnerWidget::peerListUiShow() {
|
|||
}
|
||||
|
||||
Memento::Memento(not_null<PeerData*> peer)
|
||||
: ContentMemento(peer, nullptr, PeerId()) {
|
||||
: ContentMemento(peer, nullptr, nullptr, PeerId()) {
|
||||
}
|
||||
|
||||
Section Memento::section() const {
|
||||
|
|
|
@ -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 {};
|
||||
}
|
||||
|
|
|
@ -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
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<bool> 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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -85,6 +85,7 @@ struct Instance::ShuffleData {
|
|||
std::vector<UniversalMsgId> 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<const Data*> 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<const Data*> 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<const Data*> 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*> 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*> data) {
|
|||
SliceKey(
|
||||
raw->history->peer->id,
|
||||
raw->topicRootId,
|
||||
raw->monoforumPeerId,
|
||||
raw->migrated ? raw->migrated->peer->id : 0,
|
||||
last),
|
||||
data->overview),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -30,11 +30,13 @@ public:
|
|||
Window::SessionController *controller,
|
||||
not_null<PhotoData*> 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<DocumentData*> 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<Data::CloudTheme> _cloudTheme = std::nullopt;
|
||||
bool _continueStreaming = false;
|
||||
crl::time _startTime = 0;
|
||||
|
|
|
@ -366,6 +366,7 @@ struct OverlayWidget::PipWrap {
|
|||
struct OverlayWidget::ItemContext {
|
||||
not_null<HistoryItem*> 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<Info::Memento>(
|
||||
topic,
|
||||
Info::Section(*overviewType))
|
||||
: _monoforumPeerId
|
||||
? std::make_shared<Info::Memento>(
|
||||
sublist,
|
||||
Info::Section(*overviewType))
|
||||
: std::make_shared<Info::Memento>(
|
||||
_history->peer,
|
||||
Info::Section(*overviewType)));
|
||||
|
@ -3017,6 +3028,7 @@ auto OverlayWidget::sharedMediaKey() const -> std::optional<SharedMediaKey> {
|
|||
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<SharedMediaKey> {
|
|||
(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<DocumentData*>(&items[index])) {
|
||||
return { *document, _message, _topicRootId };
|
||||
return { *document, _message, _topicRootId, _monoforumPeerId };
|
||||
} else if (const auto photo = std::get_if<PhotoData*>(&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<not_null<PeerData*>>(&context)) {
|
||||
_peer = *peer;
|
||||
|
|
|
@ -170,6 +170,7 @@ private:
|
|||
not_null<DocumentData*>> 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
|
||||
|
||||
|
|
|
@ -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<HistoryItem*> item);
|
||||
void clearFromTopic(not_null<Data::ForumTopic*> topic);
|
||||
void clearFromSublist(not_null<Data::SavedSublist*> sublist);
|
||||
void clearFromHistory(not_null<History*> history);
|
||||
void clearFromSession(not_null<Main::Session*> session);
|
||||
void clearNotification(NotificationId id);
|
||||
|
@ -367,6 +370,8 @@ Manager::Private::Private(not_null<Manager*> 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<HistoryItem*> 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<Data::ForumTopic*> topic) {
|
|||
});
|
||||
}
|
||||
|
||||
void Manager::Private::clearFromSublist(
|
||||
not_null<Data::SavedSublist*> sublist) {
|
||||
_notifications.remove(ContextId{
|
||||
.sessionId = sublist->session().uniqueId(),
|
||||
.peerId = sublist->owningHistory()->peer->id,
|
||||
.monoforumPeerId = sublist->sublistPeer()->id,
|
||||
});
|
||||
}
|
||||
|
||||
void Manager::Private::clearFromHistory(not_null<History*> history) {
|
||||
const auto sessionId = history->session().uniqueId();
|
||||
const auto peerId = history->peer->id;
|
||||
|
@ -889,6 +909,10 @@ void Manager::doClearFromTopic(not_null<Data::ForumTopic*> topic) {
|
|||
_private->clearFromTopic(topic);
|
||||
}
|
||||
|
||||
void Manager::doClearFromSublist(not_null<Data::SavedSublist*> sublist) {
|
||||
_private->clearFromSublist(sublist);
|
||||
}
|
||||
|
||||
void Manager::doClearFromHistory(not_null<History*> history) {
|
||||
_private->clearFromHistory(history);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ protected:
|
|||
void doClearAllFast() override;
|
||||
void doClearFromItem(not_null<HistoryItem*> item) override;
|
||||
void doClearFromTopic(not_null<Data::ForumTopic*> topic) override;
|
||||
void doClearFromSublist(not_null<Data::SavedSublist*> sublist) override;
|
||||
void doClearFromHistory(not_null<History*> history) override;
|
||||
void doClearFromSession(not_null<Main::Session*> session) override;
|
||||
bool doSkipToast() const override;
|
||||
|
|
|
@ -25,6 +25,7 @@ protected:
|
|||
void doClearAllFast() override;
|
||||
void doClearFromItem(not_null<HistoryItem*> item) override;
|
||||
void doClearFromTopic(not_null<Data::ForumTopic*> topic) override;
|
||||
void doClearFromSublist(not_null<Data::SavedSublist*> sublist) override;
|
||||
void doClearFromHistory(not_null<History*> history) override;
|
||||
void doClearFromSession(not_null<Main::Session*> session) override;
|
||||
QString accountNameSeparator() override;
|
||||
|
|
|
@ -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<HistoryItem*> item);
|
||||
void clearFromTopic(not_null<Data::ForumTopic*> topic);
|
||||
void clearFromSublist(not_null<Data::SavedSublist*> sublist);
|
||||
void clearFromHistory(not_null<History*> history);
|
||||
void clearFromSession(not_null<Main::Session*> 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<NotificationId>();
|
||||
auto clearFromTopics = base::flat_set<ContextId>();
|
||||
auto clearFromSublists = base::flat_set<ContextId>();
|
||||
auto clearFromHistories = base::flat_set<ContextId>();
|
||||
auto clearFromSessions = base::flat_set<uint64>();
|
||||
{
|
||||
|
@ -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<HistoryItem*> 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<Data::ForumTopic*> topic) {
|
|||
} });
|
||||
}
|
||||
|
||||
void Manager::Private::clearFromSublist(
|
||||
not_null<Data::SavedSublist*> sublist) {
|
||||
putClearTask(ClearFromSublist{ ContextId{
|
||||
.sessionId = sublist->session().uniqueId(),
|
||||
.peerId = sublist->owningHistory()->peer->id,
|
||||
.monoforumPeerId = sublist->sublistPeer()->id,
|
||||
} });
|
||||
}
|
||||
|
||||
void Manager::Private::clearFromHistory(not_null<History*> history) {
|
||||
putClearTask(ClearFromHistory{ ContextId{
|
||||
.sessionId = history->session().uniqueId(),
|
||||
|
@ -511,6 +554,10 @@ void Manager::doClearFromTopic(not_null<Data::ForumTopic*> topic) {
|
|||
_private->clearFromTopic(topic);
|
||||
}
|
||||
|
||||
void Manager::doClearFromSublist(not_null<Data::SavedSublist*> sublist) {
|
||||
_private->clearFromSublist(sublist);
|
||||
}
|
||||
|
||||
void Manager::doClearFromHistory(not_null<History*> history) {
|
||||
_private->clearFromHistory(history);
|
||||
}
|
||||
|
|
|
@ -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<HistoryItem*> item);
|
||||
void clearFromTopic(not_null<Data::ForumTopic*> topic);
|
||||
void clearFromSublist(not_null<Data::SavedSublist*> sublist);
|
||||
void clearFromHistory(not_null<History*> history);
|
||||
void clearFromSession(not_null<Main::Session*> session);
|
||||
void beforeNotificationActivated(NotificationId id);
|
||||
|
@ -508,6 +511,7 @@ void Manager::Private::clearFromItem(not_null<HistoryItem*> 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<Data::ForumTopic*> topic) {
|
|||
}
|
||||
}
|
||||
|
||||
void Manager::Private::clearFromSublist(
|
||||
not_null<Data::SavedSublist*> 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*> 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<Data::ForumTopic*> topic) {
|
|||
_private->clearFromTopic(topic);
|
||||
}
|
||||
|
||||
void Manager::doClearFromSublist(not_null<Data::SavedSublist*> sublist) {
|
||||
_private->clearFromSublist(sublist);
|
||||
}
|
||||
|
||||
void Manager::doClearFromHistory(not_null<History*> history) {
|
||||
_private->clearFromHistory(history);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ protected:
|
|||
void doClearAllFast() override;
|
||||
void doClearFromItem(not_null<HistoryItem*> item) override;
|
||||
void doClearFromTopic(not_null<Data::ForumTopic*> topic) override;
|
||||
void doClearFromSublist(not_null<Data::SavedSublist*> sublist) override;
|
||||
void doClearFromHistory(not_null<History*> history) override;
|
||||
void doClearFromSession(not_null<Main::Session*> session) override;
|
||||
void onBeforeNotificationActivated(NotificationId id) override;
|
||||
|
|
|
@ -1084,6 +1084,7 @@ bool ReadSetting(
|
|||
context.sessionSettings().setHiddenPinnedMessageId(
|
||||
DeserializePeerId(i.key()),
|
||||
MsgId(0), // topicRootId
|
||||
PeerId(0), // monoforumPeerId
|
||||
MsgId(i.value()));
|
||||
}
|
||||
context.legacyRead = true;
|
||||
|
|
|
@ -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<SharedMediaType>(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<int>(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<SharedMediaType>(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<SharedMediaResult> 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<int>(query.key.type);
|
||||
return peerIt->second[index].query(SparseIdsListQuery(
|
||||
|
@ -141,7 +166,11 @@ rpl::producer<SharedMediaResult> 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<int>(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<int>(key.type);
|
||||
return peerIt->second[index].empty();
|
||||
|
|
|
@ -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<MsgId> &&messageIds,
|
||||
MsgRange noSkipRange,
|
||||
std::optional<int> 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<MsgId> 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;
|
||||
};
|
||||
|
|
|
@ -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<Data::Thread*> 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<Data::ForumTopic*> topic) {
|
||||
|
@ -445,6 +456,23 @@ void System::clearFromTopic(not_null<Data::ForumTopic*> topic) {
|
|||
showNext();
|
||||
}
|
||||
|
||||
void System::clearFromSublist(not_null<Data::SavedSublist*> 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<bool(not_null<Data::Thread*>)> predicate) {
|
||||
for (auto i = _whenMaps.begin(); i != _whenMaps.end();) {
|
||||
const auto thread = i->first;
|
||||
|
@ -460,6 +488,8 @@ void System::clearForThreadIf(Fn<bool(not_null<Data::Thread*>)> 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<bool(not_null<Data::Thread*>)> 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<Data::ForumTopic*> topic) {
|
|||
_whenAlerts.remove(topic);
|
||||
}
|
||||
|
||||
void System::clearIncomingFromSublist(
|
||||
not_null<Data::SavedSublist*> sublist) {
|
||||
if (_manager) {
|
||||
_manager->clearFromSublist(sublist);
|
||||
}
|
||||
sublist->clearIncomingNotifications();
|
||||
_whenAlerts.remove(sublist);
|
||||
}
|
||||
|
||||
void System::clearFromItem(not_null<HistoryItem*> 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,
|
||||
|
|
|
@ -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<Data::ForumTopic*> topic);
|
||||
void clearFromSublist(not_null<Data::SavedSublist*> sublist);
|
||||
void clearFromHistory(not_null<History*> history);
|
||||
void clearIncomingFromTopic(not_null<Data::ForumTopic*> topic);
|
||||
void clearIncomingFromSublist(not_null<Data::SavedSublist*> sublist);
|
||||
void clearIncomingFromHistory(not_null<History*> history);
|
||||
void clearFromSession(not_null<Main::Session*> session);
|
||||
void clearFromItem(not_null<HistoryItem*> item);
|
||||
|
@ -221,6 +224,9 @@ private:
|
|||
base::flat_map<
|
||||
not_null<Data::ForumTopic*>,
|
||||
rpl::lifetime> _watchedTopics;
|
||||
base::flat_map<
|
||||
not_null<Data::SavedSublist*>,
|
||||
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<Data::ForumTopic*> topic) {
|
||||
doClearFromTopic(topic);
|
||||
}
|
||||
void clearFromSublist(not_null<Data::SavedSublist*> sublist) {
|
||||
doClearFromSublist(sublist);
|
||||
}
|
||||
void clearFromHistory(not_null<History*> history) {
|
||||
doClearFromHistory(history);
|
||||
}
|
||||
|
@ -341,6 +351,8 @@ protected:
|
|||
virtual void doClearAllFast() = 0;
|
||||
virtual void doClearFromItem(not_null<HistoryItem*> item) = 0;
|
||||
virtual void doClearFromTopic(not_null<Data::ForumTopic*> topic) = 0;
|
||||
virtual void doClearFromSublist(
|
||||
not_null<Data::SavedSublist*> sublist) = 0;
|
||||
virtual void doClearFromHistory(not_null<History*> history) = 0;
|
||||
virtual void doClearFromSession(not_null<Main::Session*> session) = 0;
|
||||
[[nodiscard]] virtual bool doSkipToast() const = 0;
|
||||
|
@ -377,6 +389,7 @@ public:
|
|||
struct NotificationInfo {
|
||||
not_null<PeerData*> peer;
|
||||
MsgId topicRootId = 0;
|
||||
PeerId monoforumPeerId = 0;
|
||||
MsgId itemId = 0;
|
||||
QString title;
|
||||
QString subtitle;
|
||||
|
@ -426,6 +439,8 @@ protected:
|
|||
}
|
||||
void doClearFromTopic(not_null<Data::ForumTopic*> topic) override {
|
||||
}
|
||||
void doClearFromSublist(not_null<Data::SavedSublist*> sublist) override {
|
||||
}
|
||||
void doClearFromHistory(not_null<History*> history) override {
|
||||
}
|
||||
void doClearFromSession(not_null<Main::Session*> session) override {
|
||||
|
|
|
@ -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<Data::ForumTopic*> 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<Data::SavedSublist*> 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*> manager,
|
||||
not_null<History*> history,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
not_null<PeerData*> 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;
|
||||
|
|
|
@ -70,6 +70,7 @@ private:
|
|||
void doClearAll() override;
|
||||
void doClearAllFast() override;
|
||||
void doClearFromTopic(not_null<Data::ForumTopic*> topic) override;
|
||||
void doClearFromSublist(not_null<Data::SavedSublist*> sublist) override;
|
||||
void doClearFromHistory(not_null<History*> history) override;
|
||||
void doClearFromSession(not_null<Main::Session*> session) override;
|
||||
void doClearFromItem(not_null<HistoryItem*> item) override;
|
||||
|
@ -111,6 +112,7 @@ private:
|
|||
|
||||
not_null<History*> history;
|
||||
MsgId topicRootId = 0;
|
||||
PeerId monoforumPeerId = 0;
|
||||
not_null<PeerData*> peer;
|
||||
Data::ReactionId reaction;
|
||||
QString author;
|
||||
|
@ -203,6 +205,7 @@ public:
|
|||
not_null<Manager*> manager,
|
||||
not_null<History*> history,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
not_null<PeerData*> 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<Main::Session*> 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;
|
||||
|
|
|
@ -3040,14 +3040,18 @@ void HidePinnedBar(
|
|||
not_null<Window::SessionNavigation*> navigation,
|
||||
not_null<PeerData*> peer,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
Fn<void()> onHidden) {
|
||||
const auto callback = crl::guard(navigation, [=](Fn<void()> &&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();
|
||||
};
|
||||
|
|
|
@ -218,6 +218,7 @@ void HidePinnedBar(
|
|||
not_null<Window::SessionNavigation*> navigation,
|
||||
not_null<PeerData*> peer,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
Fn<void()> onHidden);
|
||||
void UnpinAllMessages(
|
||||
not_null<Window::SessionNavigation*> navigation,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -523,6 +523,7 @@ public:
|
|||
struct MessageContext {
|
||||
FullMsgId id;
|
||||
MsgId topicRootId;
|
||||
PeerId monoforumPeerId;
|
||||
};
|
||||
void openPhoto(
|
||||
not_null<PhotoData*> photo,
|
||||
|
|
Loading…
Add table
Reference in a new issue