2
0
mirror of https://github.com/telegramdesktop/tdesktop synced 2025-08-31 14:38:15 +00:00

Support per-topic notification settings.

This commit is contained in:
John Preston
2022-10-13 00:23:14 +04:00
parent 24843e3acd
commit 92a4b27e65
31 changed files with 713 additions and 293 deletions

View File

@@ -37,6 +37,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_photo.h"
#include "data/data_web_page.h"
#include "data/data_folder.h"
#include "data/data_forum_topic.h"
#include "data/data_media_types.h"
#include "data/data_sparse_ids.h"
#include "data/data_search_controller.h"
@@ -150,7 +151,7 @@ ApiWrap::ApiWrap(not_null<Main::Session*> session)
, _dialogsLoadState(std::make_unique<DialogsLoadState>())
, _fileLoader(std::make_unique<TaskQueue>(kFileLoaderQueueStopTimeout))
, _topPromotionTimer([=] { refreshTopPromotion(); })
, _updateNotifySettingsTimer([=] { sendNotifySettingsUpdates(); })
, _updateNotifyTimer([=] { sendNotifySettingsUpdates(); })
, _authorizations(std::make_unique<Api::Authorizations>(this))
, _attachedStickers(std::make_unique<Api::AttachedStickers>(this))
, _blockedPeers(std::make_unique<Api::BlockedPeers>(this))
@@ -1323,27 +1324,25 @@ void ApiWrap::deleteAllFromParticipantSend(
void ApiWrap::scheduleStickerSetRequest(uint64 setId, uint64 access) {
if (!_stickerSetRequests.contains(setId)) {
_stickerSetRequests.insert(setId, qMakePair(access, 0));
_stickerSetRequests.emplace(setId, StickerSetRequest{ access });
}
}
void ApiWrap::requestStickerSets() {
for (auto i = _stickerSetRequests.begin(), j = i, e = _stickerSetRequests.end(); i != e; i = j) {
++j;
if (i.value().second) continue;
auto waitMs = (j == e) ? 0 : kSmallDelayMs;
const auto id = MTP_inputStickerSetID(
MTP_long(i.key()),
MTP_long(i.value().first));
i.value().second = request(MTPmessages_GetStickerSet(
id,
for (auto &[id, info] : _stickerSetRequests) {
if (info.id) {
continue;
}
info.id = request(MTPmessages_GetStickerSet(
MTP_inputStickerSetID(
MTP_long(id),
MTP_long(info.accessHash)),
MTP_int(0) // hash
)).done([=, setId = i.key()](const MTPmessages_StickerSet &result) {
)).done([=, setId = id](const MTPmessages_StickerSet &result) {
gotStickerSet(setId, result);
}).fail([=, setId = i.key()] {
}).fail([=, setId = id] {
_stickerSetRequests.remove(setId);
}).afterDelay(waitMs).send();
}).afterDelay(kSmallDelayMs).send();
}
}
@@ -1671,7 +1670,7 @@ void ApiWrap::joinChannel(not_null<ChannelData*> channel) {
_channelAmInRequests.remove(channel);
}).send();
_channelAmInRequests.insert(channel, requestId);
_channelAmInRequests.emplace(channel, requestId);
}
}
@@ -1690,44 +1689,48 @@ void ApiWrap::leaveChannel(not_null<ChannelData*> channel) {
_channelAmInRequests.remove(channel);
}).send();
_channelAmInRequests.insert(channel, requestId);
_channelAmInRequests.emplace(channel, requestId);
}
}
void ApiWrap::requestNotifySettings(const MTPInputNotifyPeer &peer) {
const auto key = [&] {
switch (peer.type()) {
case mtpc_inputNotifyUsers: return peerFromUser(0);
case mtpc_inputNotifyChats: return peerFromChat(0);
case mtpc_inputNotifyBroadcasts: return peerFromChannel(0);
case mtpc_inputNotifyPeer: {
const auto &inner = peer.c_inputNotifyPeer().vpeer();
switch (inner.type()) {
case mtpc_inputPeerSelf:
return _session->userPeerId();
case mtpc_inputPeerEmpty:
return PeerId(0);
case mtpc_inputPeerChannel:
return peerFromChannel(
inner.c_inputPeerChannel().vchannel_id());
case mtpc_inputPeerChat:
return peerFromChat(inner.c_inputPeerChat().vchat_id());
case mtpc_inputPeerUser:
return peerFromUser(inner.c_inputPeerUser().vuser_id());
}
const auto peerFromInput = [&](const MTPInputPeer &inputPeer) {
return inputPeer.match([&](const MTPDinputPeerSelf &) {
return _session->userPeerId();
}, [](const MTPDinputPeerEmpty &) {
return PeerId(0);
}, [](const MTPDinputPeerChannel &data) {
return peerFromChannel(data.vchannel_id());
}, [](const MTPDinputPeerChat &data) {
return peerFromChat(data.vchat_id());
}, [](const MTPDinputPeerUser &data) {
return peerFromUser(data.vuser_id());
}, [](const auto &) -> PeerId {
Unexpected("Type in ApiRequest::requestNotifySettings peer.");
} break;
}
Unexpected("Type in ApiRequest::requestNotifySettings.");
}();
if (_notifySettingRequests.find(key) != end(_notifySettingRequests)) {
});
};
const auto key = peer.match([](const MTPDinputNotifyUsers &) {
return NotifySettingsKey{ peerFromUser(1) };
}, [](const MTPDinputNotifyChats &) {
return NotifySettingsKey{ peerFromChat(1) };
}, [](const MTPDinputNotifyBroadcasts &) {
return NotifySettingsKey{ peerFromChannel(1) };
}, [&](const MTPDinputNotifyPeer &data) {
return NotifySettingsKey{ peerFromInput(data.vpeer()) };
}, [&](const MTPDinputNotifyForumTopic &data) {
return NotifySettingsKey{
peerFromInput(data.vpeer()),
data.vtop_msg_id().v,
};
});
if (_notifySettingRequests.contains(key)) {
return;
}
const auto requestId = request(MTPaccount_GetNotifySettings(
peer
)).done([=](const MTPPeerNotifySettings &result) {
applyNotifySettings(peer, result);
_notifySettingRequests.erase(key);
_notifySettingRequests.remove(key);
}).fail([=] {
applyNotifySettings(
peer,
@@ -1741,34 +1744,50 @@ void ApiWrap::requestNotifySettings(const MTPInputNotifyPeer &peer) {
MTPNotificationSound()));
_notifySettingRequests.erase(key);
}).send();
_notifySettingRequests.emplace(key, requestId);
}
void ApiWrap::updateNotifySettingsDelayed(not_null<const PeerData*> peer) {
_updateNotifySettingsPeers.emplace(peer);
_updateNotifySettingsTimer.callOnce(kNotifySettingSaveTimeout);
void ApiWrap::updateNotifySettingsDelayed(
not_null<const Data::ForumTopic*> topic) {
if (_updateNotifyTopics.emplace(topic).second) {
topic->destroyed(
) | rpl::start_with_next([=] {
_updateNotifyTopics.remove(topic);
}, _updateNotifyQueueLifetime);
_updateNotifyTimer.callOnce(kNotifySettingSaveTimeout);
}
}
void ApiWrap::updateDefaultNotifySettingsDelayed(Data::DefaultNotify type) {
_updateNotifySettingsDefaults.emplace(type);
_updateNotifySettingsTimer.callOnce(kNotifySettingSaveTimeout);
void ApiWrap::updateNotifySettingsDelayed(not_null<const PeerData*> peer) {
if (_updateNotifyPeers.emplace(peer).second) {
_updateNotifyTimer.callOnce(kNotifySettingSaveTimeout);
}
}
void ApiWrap::updateNotifySettingsDelayed(Data::DefaultNotify type) {
if (_updateNotifyDefaults.emplace(type).second) {
_updateNotifyTimer.callOnce(kNotifySettingSaveTimeout);
}
}
void ApiWrap::sendNotifySettingsUpdates() {
while (!_updateNotifySettingsPeers.empty()) {
const auto peer = *_updateNotifySettingsPeers.begin();
_updateNotifySettingsPeers.erase(_updateNotifySettingsPeers.begin());
_updateNotifyQueueLifetime.destroy();
for (const auto topic : base::take(_updateNotifyTopics)) {
request(MTPaccount_UpdateNotifySettings(
MTP_inputNotifyForumTopic(
topic->channel()->input,
MTP_int(topic->rootId())),
topic->notify().serialize()
)).afterDelay(kSmallDelayMs).send();
}
for (const auto peer : base::take(_updateNotifyPeers)) {
request(MTPaccount_UpdateNotifySettings(
MTP_inputNotifyPeer(peer->input),
peer->notifySerialize()
)).afterDelay(_updateNotifySettingsPeers.empty() ? 0 : 10).send();
peer->notify().serialize()
)).afterDelay(kSmallDelayMs).send();
}
const auto &settings = session().data().notifySettings();
while (!_updateNotifySettingsDefaults.empty()) {
const auto type = *_updateNotifySettingsDefaults.begin();
_updateNotifySettingsDefaults.erase(
_updateNotifySettingsDefaults.begin());
for (const auto type : base::take(_updateNotifyDefaults)) {
const auto input = [&] {
switch (type) {
case Data::DefaultNotify::User: return MTP_inputNotifyUsers();
@@ -1781,8 +1800,9 @@ void ApiWrap::sendNotifySettingsUpdates() {
request(MTPaccount_UpdateNotifySettings(
input,
settings.defaultSettings(type).serialize()
)).afterDelay(_updateNotifySettingsDefaults.empty() ? 0 : 10).send();
)).afterDelay(kSmallDelayMs).send();
}
session().mtp().sendAnything();
}
void ApiWrap::saveDraftToCloudDelayed(not_null<History*> history) {
@@ -2147,7 +2167,9 @@ void ApiWrap::applyNotifySettings(
Core::App().notifications().checkDelayed();
}
void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result) {
void ApiWrap::gotStickerSet(
uint64 setId,
const MTPmessages_StickerSet &result) {
_stickerSetRequests.remove(setId);
result.match([&](const MTPDmessages_stickerSet &data) {
_session->data().stickers().feedSetFull(data);
@@ -2156,18 +2178,20 @@ void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result)
});
}
void ApiWrap::requestWebPageDelayed(WebPageData *page) {
if (page->pendingTill <= 0) return;
_webPagesPending.insert(page, 0);
void ApiWrap::requestWebPageDelayed(not_null<WebPageData*> page) {
if (page->pendingTill <= 0) {
return;
}
_webPagesPending.emplace(page, 0);
auto left = (page->pendingTill - base::unixtime::now()) * 1000;
if (!_webPagesTimer.isActive() || left <= _webPagesTimer.remainingTime()) {
_webPagesTimer.callOnce((left < 0 ? 0 : left) + 1);
}
}
void ApiWrap::clearWebPageRequest(WebPageData *page) {
void ApiWrap::clearWebPageRequest(not_null<WebPageData*> page) {
_webPagesPending.remove(page);
if (_webPagesPending.isEmpty() && _webPagesTimer.isActive()) {
if (_webPagesPending.empty() && _webPagesTimer.isActive()) {
_webPagesTimer.cancel();
}
}
@@ -2185,11 +2209,12 @@ void ApiWrap::resolveWebPages() {
ids.reserve(_webPagesPending.size());
int32 t = base::unixtime::now(), m = INT_MAX;
for (auto i = _webPagesPending.begin(); i != _webPagesPending.cend(); ++i) {
if (i.value() > 0) continue;
if (i.key()->pendingTill <= t) {
const auto item = _session->data().findWebPageItem(i.key());
if (item) {
for (auto &[page, requestId] : _webPagesPending) {
if (requestId > 0) {
continue;
}
if (page->pendingTill <= t) {
if (const auto item = _session->data().findWebPageItem(page)) {
if (const auto channel = item->history()->peer->asChannel()) {
auto channelMap = idsByChannel.find(channel);
if (channelMap == idsByChannel.cend()) {
@@ -2204,14 +2229,14 @@ void ApiWrap::resolveWebPages() {
channelMap->second.second.push_back(
MTP_inputMessageID(MTP_int(item->id)));
}
i.value() = -channelMap->second.first - 2;
requestId = -channelMap->second.first - 2;
} else {
ids.push_back(MTP_inputMessageID(MTP_int(item->id)));
i.value() = -1;
requestId = -1;
}
}
} else {
m = qMin(m, i.key()->pendingTill - t);
m = std::min(m, page->pendingTill - t);
}
}
@@ -2237,9 +2262,10 @@ void ApiWrap::resolveWebPages() {
}).afterDelay(kSmallDelayMs).send();
}
if (requestId || !reqsByIndex.isEmpty()) {
for (auto &pendingRequestId : _webPagesPending) {
if (pendingRequestId > 0) continue;
if (pendingRequestId < 0) {
for (auto &[page, pendingRequestId] : _webPagesPending) {
if (pendingRequestId > 0) {
continue;
} else if (pendingRequestId < 0) {
if (pendingRequestId == -1) {
pendingRequestId = requestId;
} else {
@@ -2248,9 +2274,8 @@ void ApiWrap::resolveWebPages() {
}
}
}
if (m < INT_MAX) {
_webPagesTimer.callOnce(m * 1000);
_webPagesTimer.callOnce(std::min(m, 86400) * crl::time(1000));
}
}
@@ -2441,10 +2466,10 @@ void ApiWrap::refreshFileReference(
void ApiWrap::gotWebPages(ChannelData *channel, const MTPmessages_Messages &result, mtpRequestId req) {
WebPageData::ApplyChanges(_session, channel, result);
for (auto i = _webPagesPending.begin(); i != _webPagesPending.cend();) {
if (i.value() == req) {
if (i.key()->pendingTill > 0) {
i.key()->pendingTill = -1;
_session->data().notifyWebPageUpdateDelayed(i.key());
if (i->second == req) {
if (i->first->pendingTill > 0) {
i->first->pendingTill = -1;
_session->data().notifyWebPageUpdateDelayed(i->first);
}
i = _webPagesPending.erase(i);
} else {