From 734c41087901b974a130c1f053251bb7ae908666 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 9 Apr 2018 21:48:29 +0400 Subject: [PATCH] New notifications API, defaults for users/chats. --- Telegram/Resources/scheme.tl | 31 +-- Telegram/SourceFiles/apiwrap.cpp | 227 +++++++++++------- Telegram/SourceFiles/apiwrap.h | 30 +-- Telegram/SourceFiles/app.cpp | 51 +--- Telegram/SourceFiles/app.h | 8 +- Telegram/SourceFiles/application.cpp | 2 + .../SourceFiles/boxes/edit_caption_box.cpp | 1 + .../SourceFiles/boxes/mute_settings_box.cpp | 7 +- .../codegen/scheme/codegen_scheme.py | 4 +- Telegram/SourceFiles/config.h | 1 - .../SourceFiles/data/data_notify_settings.cpp | 185 +++++++------- .../SourceFiles/data/data_notify_settings.h | 21 +- Telegram/SourceFiles/data/data_peer.h | 16 +- Telegram/SourceFiles/data/data_session.cpp | 219 ++++++++++++++++- Telegram/SourceFiles/data/data_session.h | 36 +++ Telegram/SourceFiles/history/history.cpp | 7 +- .../SourceFiles/history/history_message.cpp | 2 +- .../SourceFiles/history/history_widget.cpp | 54 +++-- Telegram/SourceFiles/history/history_widget.h | 2 +- .../feed/info_feed_channels_controllers.cpp | 11 +- .../SourceFiles/info/info_wrap_widget.cpp | 9 +- .../info/profile/info_profile_actions.cpp | 8 +- .../info/profile/info_profile_values.cpp | 7 +- Telegram/SourceFiles/intro/introphone.cpp | 81 ++++--- Telegram/SourceFiles/intro/introphone.h | 6 +- Telegram/SourceFiles/mainwidget.cpp | 96 +------- Telegram/SourceFiles/mainwidget.h | 26 -- Telegram/SourceFiles/stdafx.h | 1 + Telegram/SourceFiles/ui/special_buttons.cpp | 13 +- .../window/notifications_manager.cpp | 66 ++--- .../window/notifications_manager.h | 10 +- .../SourceFiles/window/window_peer_menu.cpp | 27 +-- 32 files changed, 724 insertions(+), 541 deletions(-) diff --git a/Telegram/Resources/scheme.tl b/Telegram/Resources/scheme.tl index e2b1271b0..2aa48df00 100644 --- a/Telegram/Resources/scheme.tl +++ b/Telegram/Resources/scheme.tl @@ -304,17 +304,10 @@ auth.exportedAuthorization#df969c2d id:int bytes:bytes = auth.ExportedAuthorizat inputNotifyPeer#b8bc5b0c peer:InputPeer = InputNotifyPeer; inputNotifyUsers#193b4417 = InputNotifyPeer; inputNotifyChats#4a95e84e = InputNotifyPeer; -inputNotifyAll#a429b886 = InputNotifyPeer; -inputPeerNotifyEventsEmpty#f03064d8 = InputPeerNotifyEvents; -inputPeerNotifyEventsAll#e86a2c74 = InputPeerNotifyEvents; +inputPeerNotifySettings#9c3d198e flags:# show_previews:flags.0?Bool silent:flags.1?Bool mute_until:flags.2?int sound:flags.3?string = InputPeerNotifySettings; -inputPeerNotifySettings#38935eb2 flags:# show_previews:flags.0?true silent:flags.1?true mute_until:int sound:string = InputPeerNotifySettings; - -peerNotifyEventsEmpty#add53cb3 = PeerNotifyEvents; -peerNotifyEventsAll#6d1ded88 = PeerNotifyEvents; - -peerNotifySettings#9acda4c0 flags:# show_previews:flags.0?true silent:flags.1?true mute_until:int sound:string = PeerNotifySettings; +peerNotifySettings#af509d20 flags:# show_previews:flags.0?Bool silent:flags.1?Bool mute_until:flags.2?int sound:flags.3?string = PeerNotifySettings; peerSettings#818426cd flags:# report_spam:flags.0?true = PeerSettings; @@ -515,7 +508,6 @@ help.support#17c6b5f6 phone_number:string user:User = help.Support; notifyPeer#9fd40bd8 peer:Peer = NotifyPeer; notifyUsers#b4c83b4c = NotifyPeer; notifyChats#c007cec3 = NotifyPeer; -notifyAll#74d07c60 = NotifyPeer; sendMessageTypingAction#16bf744e = SendMessageAction; sendMessageCancelAction#fd5ec8f5 = SendMessageAction; @@ -568,7 +560,7 @@ documentAttributeFilename#15590068 file_name:string = DocumentAttribute; documentAttributeHasStickers#9801d2f7 = DocumentAttribute; messages.stickersNotModified#f1749a22 = messages.Stickers; -messages.stickers#8a8ecd32 hash:string stickers:Vector = messages.Stickers; +messages.stickers#e4599bbd hash:int stickers:Vector = messages.Stickers; stickerPack#12b299d4 emoticon:string documents:Vector = StickerPack; @@ -697,7 +689,7 @@ messages.savedGifs#2e0709a5 hash:int gifs:Vector = messages.SavedGifs; inputBotInlineMessageMediaAuto#3380c786 flags:# message:string entities:flags.1?Vector reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage; inputBotInlineMessageText#3dcd7a87 flags:# no_webpage:flags.0?true message:string entities:flags.1?Vector reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage; inputBotInlineMessageMediaGeo#c1b15d65 flags:# geo_point:InputGeoPoint period:int reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage; -inputBotInlineMessageMediaVenue#aaafadc8 flags:# geo_point:InputGeoPoint title:string address:string provider:string venue_id:string reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage; +inputBotInlineMessageMediaVenue#417bbf11 flags:# geo_point:InputGeoPoint title:string address:string provider:string venue_id:string venue_type:string reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage; inputBotInlineMessageMediaContact#2daf01a7 flags:# phone_number:string first_name:string last_name:string reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage; inputBotInlineMessageGame#4b425864 flags:# reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage; @@ -709,7 +701,7 @@ inputBotInlineResultGame#4fa417f2 id:string short_name:string send_message:Input botInlineMessageMediaAuto#764cf810 flags:# message:string entities:flags.1?Vector reply_markup:flags.2?ReplyMarkup = BotInlineMessage; botInlineMessageText#8c7f65e2 flags:# no_webpage:flags.0?true message:string entities:flags.1?Vector reply_markup:flags.2?ReplyMarkup = BotInlineMessage; botInlineMessageMediaGeo#b722de65 flags:# geo:GeoPoint period:int reply_markup:flags.2?ReplyMarkup = BotInlineMessage; -botInlineMessageMediaVenue#4366232e flags:# geo:GeoPoint title:string address:string provider:string venue_id:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage; +botInlineMessageMediaVenue#8a86659c flags:# geo:GeoPoint title:string address:string provider:string venue_id:string venue_type:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage; botInlineMessageMediaContact#35edb4d4 flags:# phone_number:string first_name:string last_name:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage; botInlineResult#11965f3a flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb:flags.4?WebDocument content:flags.5?WebDocument send_message:BotInlineMessage = BotInlineResult; @@ -848,6 +840,8 @@ webDocumentNoProxy#f9c8bcc6 url:string size:int mime_type:string attributes:Vect inputWebDocument#9bed434d url:string size:int mime_type:string attributes:Vector = InputWebDocument; inputWebFileLocation#c239d686 url:string access_hash:long = InputWebFileLocation; +inputWebFileGeoPointLocation#66275a62 geo_point:InputGeoPoint w:int h:int zoom:int scale:int = InputWebFileLocation; +inputWebFileGeoMessageLocation#553f32eb peer:InputPeer msg_id:int w:int h:int zoom:int scale:int = InputWebFileLocation; upload.webFile#21e753bc size:int mime_type:string file_type:storage.FileType mtime:int bytes:bytes = upload.WebFile; @@ -975,7 +969,6 @@ initConnection#785188b8 {X:Type} flags:# api_id:int device_model:string system_v invokeWithLayer#da9b0d0d {X:Type} layer:int query:!X = X; invokeWithoutUpdates#bf9459b7 {X:Type} query:!X = X; -auth.checkPhone#6fe51dfb phone_number:string = auth.CheckedPhone; auth.sendCode#86aef0ec flags:# allow_flashcall:flags.0?true phone_number:string current_number:flags.0?Bool api_id:int api_hash:string = auth.SentCode; auth.signUp#1b067634 phone_number:string phone_code_hash:string phone_code:string first_name:string last_name:string = auth.Authorization; auth.signIn#bcd51581 phone_number:string phone_code_hash:string phone_code:string = auth.Authorization; @@ -1078,7 +1071,7 @@ messages.sendEncryptedService#32d439a4 peer:InputEncryptedChat random_id:long da messages.receivedQueue#55a5bb66 max_qts:int = Vector; messages.reportEncryptedSpam#4b0c8c0f peer:InputEncryptedChat = Bool; messages.readMessageContents#36a73f77 id:Vector = messages.AffectedMessages; -messages.getStickers#85cb5182 flags:# exclude_featured:flags.0?true emoticon:string hash:string = messages.Stickers; +messages.getStickers#43d4f2c emoticon:string hash:int = messages.Stickers; messages.getAllStickers#1c9618b1 hash:int = messages.AllStickers; messages.getWebPagePreview#8b68b0cc flags:# message:string entities:flags.3?Vector = MessageMedia; messages.exportChatInvite#7d885289 chat_id:int = ExportedChatInvite; @@ -1102,8 +1095,8 @@ messages.getInlineBotResults#514e999d flags:# bot:InputUser peer:InputPeer geo_p messages.setInlineBotResults#eb5ea206 flags:# gallery:flags.0?true private:flags.1?true query_id:long results:Vector cache_time:int next_offset:flags.2?string switch_pm:flags.3?InlineBotSwitchPM = Bool; messages.sendInlineBotResult#b16e06fe flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true peer:InputPeer reply_to_msg_id:flags.0?int random_id:long query_id:long id:string = Updates; messages.getMessageEditData#fda68d36 peer:InputPeer id:int = messages.MessageEditData; -messages.editMessage#5d1b8dd flags:# no_webpage:flags.1?true stop_geo_live:flags.12?true peer:InputPeer id:int message:flags.11?string reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector geo_point:flags.13?InputGeoPoint = Updates; -messages.editInlineBotMessage#b0e08243 flags:# no_webpage:flags.1?true stop_geo_live:flags.12?true id:InputBotInlineMessageID message:flags.11?string reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector geo_point:flags.13?InputGeoPoint = Bool; +messages.editMessage#c000e4c8 flags:# no_webpage:flags.1?true stop_geo_live:flags.12?true peer:InputPeer id:int message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector geo_point:flags.13?InputGeoPoint = Updates; +messages.editInlineBotMessage#adc3e828 flags:# no_webpage:flags.1?true stop_geo_live:flags.12?true id:InputBotInlineMessageID message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector geo_point:flags.13?InputGeoPoint = Bool; messages.getBotCallbackAnswer#810a9fec flags:# game:flags.1?true peer:InputPeer msg_id:int data:flags.0?bytes = messages.BotCallbackAnswer; messages.setBotCallbackAnswer#d58f130a flags:# alert:flags.1?true query_id:long message:flags.0?string url:flags.2?string cache_time:int = Bool; messages.getPeerDialogs#e470bcfd peers:Vector = messages.PeerDialogs; @@ -1165,7 +1158,7 @@ help.saveAppLog#6f02f748 events:Vector = Bool; help.getInviteText#4d392343 = help.InviteText; help.getSupport#9cdf08cd = help.Support; help.getAppChangelog#9010ef6f prev_app_version:string = Updates; -help.getTermsOfService#350170f3 = help.TermsOfService; +help.getTermsOfService#8e59b7e7 country_iso2:string = help.TermsOfService; help.setBotUpdatesStatus#ec22cfcd pending_updates_count:int message:string = Bool; help.getCdnConfig#52029342 = CdnConfig; help.getRecentMeUrls#3dc0f114 referer:string = help.RecentMeUrls; @@ -1233,4 +1226,4 @@ langpack.getStrings#2e1ee318 lang_code:string keys:Vector = Vector; -// LAYER 78 +// LAYER 79 diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 6f8bd26bd..eb6b146d7 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -62,6 +62,7 @@ constexpr auto kReadFeaturedSetsTimeout = TimeMs(1000); constexpr auto kFileLoaderQueueStopTimeout = TimeMs(5000); constexpr auto kFeedReadTimeout = TimeMs(1000); constexpr auto kStickersByEmojiInvalidateTimeout = TimeMs(60 * 60 * 1000); +constexpr auto kNotifySettingSaveTimeout = TimeMs(1000); bool IsSilentPost(not_null item, bool silent) { const auto history = item->history(); @@ -128,7 +129,7 @@ FileLoadTo FileLoadTaskOptions(const ApiWrap::SendOptions &options) { const auto peer = options.history->peer; return FileLoadTo( peer->id, - peer->notifySilentPosts(), + Auth().data().notifySilentPosts(peer), options.replyTo); } @@ -142,7 +143,8 @@ ApiWrap::ApiWrap(not_null session) , _featuredSetsReadTimer([=] { readFeaturedSets(); }) , _fileLoader(std::make_unique(kFileLoaderQueueStopTimeout)) , _feedReadTimer([=] { readFeeds(); }) -, _proxyPromotionTimer([=] { refreshProxyPromotion(); }) { +, _proxyPromotionTimer([=] { refreshProxyPromotion(); }) +, _updateNotifySettingsTimer([=] { sendNotifySettingsUpdates(); }) { } void ApiWrap::requestChangelog( @@ -273,7 +275,7 @@ void ApiWrap::savePinnedOrder() { // )).done([=](const MTPUpdates &result) { // applyUpdates(result); // if (group) { -// channel->setFeed(Auth().data().feed(feedId)); +// channel->setFeed(_session->data().feed(feedId)); // } else { // channel->clearFeed(); // } @@ -542,7 +544,7 @@ void ApiWrap::applyPeerDialogs(const MTPmessages_PeerDialogs &dialogs) { //case mtpc_dialogFeed: { // #feed // const auto &fields = dialog.c_dialogFeed(); - // const auto feed = Auth().data().feed(fields.vfeed_id.v); + // const auto feed = _session->data().feed(fields.vfeed_id.v); // feed->applyDialog(fields); //} break; } @@ -1376,7 +1378,7 @@ void ApiWrap::deleteAllFromUser( } } - Auth().data().sendHistoryChangeNotifications(); + _session->data().sendHistoryChangeNotifications(); deleteAllFromUserSend(channel, from); } @@ -1393,7 +1395,7 @@ void ApiWrap::deleteAllFromUserSend( deleteAllFromUserSend(channel, from); } else if (const auto history = App::historyLoaded(channel)) { if (!history->lastMessageKnown()) { - Auth().api().requestDialogEntry(history); + requestDialogEntry(history); } } }).send(); @@ -1637,83 +1639,137 @@ void ApiWrap::leaveChannel(not_null channel) { } } -void ApiWrap::blockUser(UserData *user) { +void ApiWrap::blockUser(not_null user) { if (user->isBlocked()) { Notify::peerUpdatedDelayed(user, Notify::PeerUpdate::Flag::UserIsBlocked); - } else if (!_blockRequests.contains(user)) { + } else if (_blockRequests.find(user) == end(_blockRequests)) { auto requestId = request(MTPcontacts_Block(user->inputUser)).done([this, user](const MTPBool &result) { - _blockRequests.remove(user); + _blockRequests.erase(user); user->setBlockStatus(UserData::BlockStatus::Blocked); }).fail([this, user](const RPCError &error) { - _blockRequests.remove(user); + _blockRequests.erase(user); }).send(); - _blockRequests.insert(user, requestId); + _blockRequests.emplace(user, requestId); } } -void ApiWrap::unblockUser(UserData *user) { +void ApiWrap::unblockUser(not_null user) { if (!user->isBlocked()) { Notify::peerUpdatedDelayed(user, Notify::PeerUpdate::Flag::UserIsBlocked); - } else if (!_blockRequests.contains(user)) { + } else if (_blockRequests.find(user) == end(_blockRequests)) { auto requestId = request(MTPcontacts_Unblock(user->inputUser)).done([this, user](const MTPBool &result) { - _blockRequests.remove(user); + _blockRequests.erase(user); user->setBlockStatus(UserData::BlockStatus::NotBlocked); }).fail([this, user](const RPCError &error) { - _blockRequests.remove(user); + _blockRequests.erase(user); }).send(); - _blockRequests.insert(user, requestId); + _blockRequests.emplace(user, requestId); } } -void ApiWrap::exportInviteLink(PeerData *peer) { - if (_exportInviteRequests.contains(peer)) { +void ApiWrap::exportInviteLink(not_null peer) { + if (_exportInviteRequests.find(peer) != end(_exportInviteRequests)) { return; } - auto sendRequest = [this, peer] { - auto exportFail = [this, peer](const RPCError &error) { - _exportInviteRequests.remove(peer); + const auto sendRequest = [this, peer] { + const auto exportFail = [this, peer](const RPCError &error) { + _exportInviteRequests.erase(peer); }; - if (auto chat = peer->asChat()) { - return request(MTPmessages_ExportChatInvite(chat->inputChat)).done([this, chat](const MTPExportedChatInvite &result) { - _exportInviteRequests.remove(chat); - chat->setInviteLink((result.type() == mtpc_chatInviteExported) ? qs(result.c_chatInviteExported().vlink) : QString()); + if (const auto chat = peer->asChat()) { + return request(MTPmessages_ExportChatInvite( + chat->inputChat + )).done([=](const MTPExportedChatInvite &result) { + _exportInviteRequests.erase(chat); + chat->setInviteLink( + (result.type() == mtpc_chatInviteExported + ? qs(result.c_chatInviteExported().vlink) + : QString())); }).fail(exportFail).send(); - } else if (auto channel = peer->asChannel()) { - return request(MTPchannels_ExportInvite(channel->inputChannel)).done([this, channel](const MTPExportedChatInvite &result) { - _exportInviteRequests.remove(channel); - channel->setInviteLink((result.type() == mtpc_chatInviteExported) ? qs(result.c_chatInviteExported().vlink) : QString()); + } else if (const auto channel = peer->asChannel()) { + return request(MTPchannels_ExportInvite( + channel->inputChannel + )).done([=](const MTPExportedChatInvite &result) { + _exportInviteRequests.erase(channel); + channel->setInviteLink( + (result.type() == mtpc_chatInviteExported + ? qs(result.c_chatInviteExported().vlink) + : QString())); }).fail(exportFail).send(); } return 0; }; - if (auto requestId = sendRequest()) { - _exportInviteRequests.insert(peer, requestId); + if (const auto requestId = sendRequest()) { + _exportInviteRequests.emplace(peer, requestId); } } -void ApiWrap::requestNotifySetting(PeerData *peer) { - if (_notifySettingRequests.contains(peer)) return; - - auto notifyPeer = MTP_inputNotifyPeer(peer->input); - auto requestId = request(MTPaccount_GetNotifySettings(notifyPeer)).done([this, notifyPeer, peer](const MTPPeerNotifySettings &result) { - notifySettingReceived(notifyPeer, result); - _notifySettingRequests.remove(peer); - }).fail([this, notifyPeer, peer](const RPCError &error) { - notifySettingReceived(notifyPeer, MTP_peerNotifySettings( - MTP_flags(MTPDpeerNotifySettings::Flag::f_show_previews), - MTP_int(0), - MTP_string("default"))); - _notifySettingRequests.remove(peer); +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_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); + } + Unexpected("Type in ApiRequest::requestNotifySettings peer."); + } break; + } + Unexpected("Type in ApiRequest::requestNotifySettings."); + }(); + if (_notifySettingRequests.find(key) != end(_notifySettingRequests)) { + return; + } + auto requestId = request(MTPaccount_GetNotifySettings( + peer + )).done([=](const MTPPeerNotifySettings &result) { + notifySettingReceived(peer, result); + _notifySettingRequests.erase(key); + }).fail([=](const RPCError &error) { + notifySettingReceived(peer, MTP_peerNotifySettings( + MTP_flags(0), + MTPBool(), + MTPBool(), + MTPint(), + MTPstring())); + _notifySettingRequests.erase(key); }).send(); - _notifySettingRequests.insert(peer, requestId); + _notifySettingRequests.emplace(key, requestId); } -void ApiWrap::saveDraftToCloudDelayed(History *history) { - _draftsSaveRequestIds.insert(history, 0); +void ApiWrap::updateNotifySettingsDelayed(not_null peer) { + _updateNotifySettingsPeers.emplace(peer); + _updateNotifySettingsTimer.callOnce(kNotifySettingSaveTimeout); +} + +void ApiWrap::sendNotifySettingsUpdates() { + while (!_updateNotifySettingsPeers.empty()) { + const auto peer = *_updateNotifySettingsPeers.begin(); + _updateNotifySettingsPeers.erase(_updateNotifySettingsPeers.begin()); + request(MTPaccount_UpdateNotifySettings( + MTP_inputNotifyPeer(peer->input), + peer->notifySerialize() + )).afterDelay(_updateNotifySettingsPeers.empty() ? 0 : 10).send(); + } +} + +void ApiWrap::saveDraftToCloudDelayed(not_null history) { + _draftsSaveRequestIds.emplace(history, 0); if (!_draftsSaveTimer.isActive()) { _draftsSaveTimer.callOnce(kSaveCloudDraftTimeout); } @@ -1729,6 +1785,7 @@ void ApiWrap::savePrivacy(const MTPInputPrivacyKey &key, QVector(std::move(rules)))).done([this, keyTypeId](const MTPaccount_PrivacyRules &result) { Expects(result.type() == mtpc_account_privacyRules); + auto &rules = result.c_account_privacyRules(); App::feedUsers(rules.vusers); _privacySaveRequests.remove(keyTypeId); @@ -1904,9 +1961,9 @@ void ApiWrap::applyAffectedMessages( void ApiWrap::saveDraftsToCloud() { for (auto i = _draftsSaveRequestIds.begin(), e = _draftsSaveRequestIds.end(); i != e; ++i) { - if (i.value()) continue; // sent already + if (i->second) continue; // sent already - auto history = i.key(); + auto history = i->first; auto cloudDraft = history->cloudDraft(); auto localDraft = history->localDraft(); if (cloudDraft && cloudDraft->saveRequestId) { @@ -1935,8 +1992,8 @@ void ApiWrap::saveDraftsToCloud() { } } auto i = _draftsSaveRequestIds.find(history); - if (i != _draftsSaveRequestIds.cend() && i.value() == requestId) { - _draftsSaveRequestIds.remove(history); + if (i != _draftsSaveRequestIds.cend() && i->second == requestId) { + _draftsSaveRequestIds.erase(history); checkQuitPreventFinished(); } }).fail([this, history](const RPCError &error, mtpRequestId requestId) { @@ -1946,18 +2003,18 @@ void ApiWrap::saveDraftsToCloud() { } } auto i = _draftsSaveRequestIds.find(history); - if (i != _draftsSaveRequestIds.cend() && i.value() == requestId) { - _draftsSaveRequestIds.remove(history); + if (i != _draftsSaveRequestIds.cend() && i->second == requestId) { + _draftsSaveRequestIds.erase(history); checkQuitPreventFinished(); } }).send(); - i.value() = cloudDraft->saveRequestId; + i->second = cloudDraft->saveRequestId; } } bool ApiWrap::isQuitPrevent() { - if (_draftsSaveRequestIds.isEmpty()) { + if (_draftsSaveRequestIds.empty()) { return false; } LOG(("ApiWrap prevents quit, saving drafts...")); @@ -1966,7 +2023,7 @@ bool ApiWrap::isQuitPrevent() { } void ApiWrap::checkQuitPreventFinished() { - if (_draftsSaveRequestIds.isEmpty()) { + if (_draftsSaveRequestIds.empty()) { if (App::quitting()) { LOG(("ApiWrap doesn't prevent quit any more.")); } @@ -1974,41 +2031,43 @@ void ApiWrap::checkQuitPreventFinished() { } } -PeerData *ApiWrap::notifySettingReceived( +void ApiWrap::notifySettingReceived( MTPInputNotifyPeer notifyPeer, const MTPPeerNotifySettings &settings) { - PeerData *requestedPeer = nullptr; switch (notifyPeer.type()) { - case mtpc_inputNotifyAll: - App::main()->applyNotifySetting(MTP_notifyAll(), settings); - break; case mtpc_inputNotifyUsers: - App::main()->applyNotifySetting(MTP_notifyUsers(), settings); + _session->data().applyNotifySetting(MTP_notifyUsers(), settings); break; case mtpc_inputNotifyChats: - App::main()->applyNotifySetting(MTP_notifyChats(), settings); + _session->data().applyNotifySetting(MTP_notifyChats(), settings); break; case mtpc_inputNotifyPeer: { auto &peer = notifyPeer.c_inputNotifyPeer().vpeer; - switch (peer.type()) { - case mtpc_inputPeerEmpty: App::main()->applyNotifySetting( - MTP_notifyPeer(MTP_peerUser(MTP_int(0))), - settings); - break; - case mtpc_inputPeerSelf: requestedPeer = App::self(); break; - case mtpc_inputPeerUser: requestedPeer = App::user(peerFromUser(peer.c_inputPeerUser().vuser_id)); break; - case mtpc_inputPeerChat: requestedPeer = App::chat(peerFromChat(peer.c_inputPeerChat().vchat_id)); break; - case mtpc_inputPeerChannel: requestedPeer = App::channel(peerFromChannel(peer.c_inputPeerChannel().vchannel_id)); break; - } - if (requestedPeer) { - App::main()->applyNotifySetting( - MTP_notifyPeer(peerToMTP(requestedPeer->id)), + const auto apply = [&](PeerId peerId) { + _session->data().applyNotifySetting( + MTP_notifyPeer(peerToMTP(peerId)), settings); + }; + switch (peer.type()) { + case mtpc_inputPeerEmpty: + apply(0); + break; + case mtpc_inputPeerSelf: + apply(_session->userPeerId()); + break; + case mtpc_inputPeerUser: + apply(peerFromUser(peer.c_inputPeerUser().vuser_id)); + break; + case mtpc_inputPeerChat: + apply(peerFromChat(peer.c_inputPeerChat().vchat_id)); + break; + case mtpc_inputPeerChannel: + apply(peerFromChannel(peer.c_inputPeerChannel().vchannel_id)); + break; } } break; } _session->notifications().checkDelayed(); - return requestedPeer; } void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result) { @@ -2325,11 +2384,10 @@ std::vector> *ApiWrap::stickersByEmoji( if (sendRequest) { const auto hash = (it != _stickersByEmoji.end()) ? it->second.hash - : QString(); + : int32(0); request(MTPmessages_GetStickers( - MTP_flags(MTPmessages_GetStickers::Flag::f_exclude_featured), MTP_string(emoji->text()), - MTP_string(hash) + MTP_int(hash) )).done([=](const MTPmessages_Stickers &result) { if (result.type() == mtpc_messages_stickersNotModified) { return; @@ -2340,12 +2398,12 @@ std::vector> *ApiWrap::stickersByEmoji( entry.list.clear(); entry.list.reserve(data.vstickers.v.size()); for (const auto &sticker : data.vstickers.v) { - const auto document = Auth().data().document(sticker); + const auto document = _session->data().document(sticker); if (document->sticker()) { entry.list.push_back(document); } } - entry.hash = qs(data.vhash); + entry.hash = data.vhash.v; entry.received = getms(true); _session->data().notifyStickersUpdated(); }).send(); @@ -3490,7 +3548,8 @@ void ApiWrap::forwardMessages( readServerHistory(history); const auto channelPost = peer->isChannel() && !peer->isMegagroup(); - const auto silentPost = channelPost && peer->notifySilentPosts(); + const auto silentPost = channelPost + && _session->data().notifySilentPosts(peer); auto flags = MTPDmessage::Flags(0); auto sendFlags = MTPmessages_ForwardMessages::Flags(0); @@ -3665,7 +3724,7 @@ void ApiWrap::sendSharedContact( MTP_string(phone), MTP_string(firstName), MTP_string(lastName)); - sendMedia(item, media, peer->notifySilentPosts()); + sendMedia(item, media, _session->data().notifySilentPosts(peer)); if (const auto main = App::main()) { _session->data().sendHistoryChangeNotifications(); diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index fd3a8d300..4ba0c2507 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -137,13 +137,13 @@ public: void joinChannel(not_null channel); void leaveChannel(not_null channel); - void blockUser(UserData *user); - void unblockUser(UserData *user); + void blockUser(not_null user); + void unblockUser(not_null user); - void exportInviteLink(PeerData *peer); - void requestNotifySetting(PeerData *peer); - - void saveDraftToCloudDelayed(History *history); + void exportInviteLink(not_null peer); + void requestNotifySettings(const MTPInputNotifyPeer &peer); + void updateNotifySettingsDelayed(not_null peer); + void saveDraftToCloudDelayed(not_null history); void savePrivacy(const MTPInputPrivacyKey &key, QVector &&rules); void handlePrivacyChange(mtpTypeId keyTypeId, const MTPVector &rules); @@ -285,7 +285,7 @@ private: struct StickersByEmoji { std::vector> list; - QString hash; + int32 hash = 0; TimeMs received = 0; }; @@ -338,7 +338,7 @@ private: MsgRange range, const MTPupdates_ChannelDifference &result); - PeerData *notifySettingReceived( + void notifySettingReceived( MTPInputNotifyPeer peer, const MTPPeerNotifySettings &settings); @@ -440,6 +440,8 @@ private: void getProxyPromotionDelayed(TimeId now, TimeId next); void proxyPromotionDone(const MTPhelp_ProxyData &proxy); + void sendNotifySettingsUpdates(); + not_null _session; MessageDataRequests _messageDataRequests; @@ -480,12 +482,10 @@ private: QMap > _stickerSetRequests; QMap _channelAmInRequests; - QMap _blockRequests; - QMap _exportInviteRequests; - - QMap _notifySettingRequests; - - QMap _draftsSaveRequestIds; + std::map, mtpRequestId> _blockRequests; + std::map, mtpRequestId> _exportInviteRequests; + std::map _notifySettingRequests; + std::map, mtpRequestId> _draftsSaveRequestIds; base::Timer _draftsSaveTimer; base::flat_set _stickerSetDisenableRequests; @@ -575,5 +575,7 @@ private: TimeId _proxyPromotionNextRequestTime = TimeId(0); base::Timer _proxyPromotionTimer; + base::flat_set> _updateNotifySettingsPeers; + base::Timer _updateNotifySettingsTimer; }; diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 81f402f2d..4d6ab462d 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -53,9 +53,6 @@ namespace { using PeersData = QHash; PeersData peersData; - using MutedPeers = QMap, bool>; - MutedPeers mutedPeers; - using LocationsData = QHash; LocationsData locationsData; @@ -1153,14 +1150,23 @@ namespace { return i.value(); } - void enumerateUsers(base::lambda action) { - for_const (auto peer, peersData) { - if (auto user = peer->asUser()) { + void enumerateUsers(base::lambda)> action) { + for_const (const auto peer, peersData) { + if (const auto user = peer->asUser()) { action(user); } } } + void enumerateChatsChannels( + base::lambda)> action) { + for_const (const auto peer, peersData) { + if (!peer->isUser()) { + action(peer); + } + } + } + UserData *self() { return ::self; } @@ -1309,7 +1315,6 @@ namespace { void historyClearItems() { randomData.clear(); sentData.clear(); - mutedPeers.clear(); cSetSavedPeers(SavedPeers()); cSetSavedPeersByTime(SavedPeersByTime()); cSetRecentInlineBots(RecentInlineBots()); @@ -1748,38 +1753,6 @@ namespace { return QPixmap::fromImage(std::move(image), Qt::ColorOnly); } - void regMuted(not_null peer, TimeMs changeIn) { - ::mutedPeers.insert(peer, true); - App::main()->updateMutedIn(changeIn); - } - - void unregMuted(not_null peer) { - ::mutedPeers.remove(peer); - } - - void updateMuted() { - auto changeInMin = TimeMs(0); - for (auto i = ::mutedPeers.begin(); i != ::mutedPeers.end();) { - const auto history = App::historyLoaded(i.key()->id); - const auto muteFinishesIn = i.key()->notifyMuteFinishesIn(); - if (muteFinishesIn > 0) { - if (history) { - history->changeMute(true); - } - if (!changeInMin || muteFinishesIn < changeInMin) { - changeInMin = muteFinishesIn; - } - ++i; - } else { - if (history) { - history->changeMute(false); - } - i = ::mutedPeers.erase(i); - } - } - if (changeInMin) App::main()->updateMutedIn(changeInMin); - } - void rectWithCorners(Painter &p, QRect rect, const style::color &bg, RoundCorners index, RectParts corners) { auto parts = RectPart::Top | RectPart::NoTopBottom diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index f2e704924..aba1e31a7 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -135,7 +135,9 @@ namespace App { inline ChannelData *channelLoaded(ChannelId channelId) { return channel(channelId, PeerData::FullLoaded); } - void enumerateUsers(base::lambda action); + void enumerateUsers(base::lambda)> action); + void enumerateChatsChannels( + base::lambda)> action); UserData *self(); PeerData *peerByName(const QString &username); @@ -221,10 +223,6 @@ namespace App { QImage readImage(const QString &file, QByteArray *format = nullptr, bool opaque = true, bool *animated = nullptr, QByteArray *content = 0); QPixmap pixmapFromImageInPlace(QImage &&image); - void regMuted(not_null peer, TimeMs changeIn); - void unregMuted(not_null peer); - void updateMuted(); - void complexOverlayRect(Painter &p, QRect rect, ImageRoundRadius radius, RectParts corners); void complexLocationRect(Painter &p, QRect rect, ImageRoundRadius radius, RectParts corners); diff --git a/Telegram/SourceFiles/application.cpp b/Telegram/SourceFiles/application.cpp index ade50c895..3a07adea6 100644 --- a/Telegram/SourceFiles/application.cpp +++ b/Telegram/SourceFiles/application.cpp @@ -15,6 +15,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/crash_reports.h" #include "messenger.h" #include "base/timer.h" +#include "base/qthelp_url.h" +#include "base/qthelp_regex.h" #include "core/update_checker.h" #include "core/crash_report_window.h" diff --git a/Telegram/SourceFiles/boxes/edit_caption_box.cpp b/Telegram/SourceFiles/boxes/edit_caption_box.cpp index d0d4f5970..12d3fbdee 100644 --- a/Telegram/SourceFiles/boxes/edit_caption_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_caption_box.cpp @@ -372,6 +372,7 @@ void EditCaptionBox::save() { item->history()->peer->input, MTP_int(item->id), MTP_string(sending.text), + MTPInputMedia(), MTPnullMarkup, sentEntities, MTP_inputGeoPointEmpty()), diff --git a/Telegram/SourceFiles/boxes/mute_settings_box.cpp b/Telegram/SourceFiles/boxes/mute_settings_box.cpp index ab6a288e1..52bd0368c 100644 --- a/Telegram/SourceFiles/boxes/mute_settings_box.cpp +++ b/Telegram/SourceFiles/boxes/mute_settings_box.cpp @@ -8,7 +8,8 @@ Copyright (C) 2017, Nicholas Guriev #include "boxes/mute_settings_box.h" #include "lang/lang_keys.h" -#include "mainwidget.h" +#include "auth_session.h" +#include "data/data_session.h" #include "styles/style_boxes.h" #include "ui/special_buttons.h" #include "ui/widgets/checkbox.h" @@ -69,10 +70,8 @@ void MuteSettingsBox::prepare() { addButton(langFactory(lng_box_ok), [this, group] { auto muteForSeconds = group->value() * 3600; - App::main()->updateNotifySettings( + Auth().data().updateNotifySettings( _peer, - Data::NotifySettings::MuteChange::Mute, - Data::NotifySettings::SilentPostsChange::Ignore, muteForSeconds); closeBox(); }); diff --git a/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py b/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py index 6652a1caf..d21f83ef1 100644 --- a/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py +++ b/Telegram/SourceFiles/codegen/scheme/codegen_scheme.py @@ -55,8 +55,8 @@ addChildParentFlags('MTPDchannelForbidden', 'MTPDchannel'); parentFlagsCheck = {}; countedTypeIdExceptions = {}; -countedTypeIdExceptions[77] = countedTypeIdExceptions[78] = {} -countedTypeIdExceptions[77]['channel'] = countedTypeIdExceptions[78]['channel'] = True +countedTypeIdExceptions[77] = countedTypeIdExceptions[78] = countedTypeIdExceptions[79] = {} +countedTypeIdExceptions[77]['channel'] = countedTypeIdExceptions[78]['channel'] = countedTypeIdExceptions[79]['channel'] = True countedTypeIdExceptions['ipPortSecret'] = True countedTypeIdExceptions['accessPointRule'] = True countedTypeIdExceptions['help_configSimple'] = True diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h index 2db3a5e78..ac4bd2549 100644 --- a/Telegram/SourceFiles/config.h +++ b/Telegram/SourceFiles/config.h @@ -275,7 +275,6 @@ enum { WaitForChannelGetDifference = 1000, // 1s wait after show channel history before sending getChannelDifference MemoryForImageCache = 64 * 1024 * 1024, // after 64mb of unpacked images we try to clear some memory - NotifySettingSaveTimeout = 1000, // wait 1 second before saving notify setting to server IdleMsecs = 60 * 1000, // after 60secs without user input we think we are idle SendViewsTimeout = 1000, // send views each second diff --git a/Telegram/SourceFiles/data/data_notify_settings.cpp b/Telegram/SourceFiles/data/data_notify_settings.cpp index aa0cf5e91..ad5c19493 100644 --- a/Telegram/SourceFiles/data/data_notify_settings.cpp +++ b/Telegram/SourceFiles/data/data_notify_settings.cpp @@ -12,11 +12,12 @@ namespace { MTPinputPeerNotifySettings DefaultSettings() { const auto flags = MTPDpeerNotifySettings::Flag::f_show_previews; - const auto muteValue = TimeId(0); return MTP_inputPeerNotifySettings( - MTP_flags(mtpCastFlags(flags)), - MTP_int(muteValue), - MTP_string("default")); + MTP_flags(0), + MTPBool(), + MTPBool(), + MTPint(), + MTPstring()); } } // namespace @@ -25,98 +26,121 @@ class NotifySettingsValue { public: NotifySettingsValue(const MTPDpeerNotifySettings &data); - using MuteChange = NotifySettings::MuteChange; - using SilentPostsChange = NotifySettings::SilentPostsChange; - bool change(const MTPDpeerNotifySettings &data); bool change( - MuteChange mute, - SilentPostsChange silent, - int muteForSeconds); - TimeMs muteFinishesIn() const; - bool silentPosts() const; + base::optional muteForSeconds, + base::optional silentPosts); + + base::optional muteUntil() const; + base::optional silentPosts() const; MTPinputPeerNotifySettings serialize() const; private: bool change( - MTPDpeerNotifySettings::Flags flags, - TimeId mute, - QString sound); + base::optional mute, + base::optional sound, + base::optional showPreviews, + base::optional silentPosts); - MTPDpeerNotifySettings::Flags _flags; - TimeId _mute; - QString _sound; + base::optional _mute; + base::optional _sound; + base::optional _silent; + base::optional _showPreviews; }; -NotifySettingsValue::NotifySettingsValue(const MTPDpeerNotifySettings &data) -: _flags(data.vflags.v) -, _mute(data.vmute_until.v) -, _sound(qs(data.vsound)) { -} - -bool NotifySettingsValue::silentPosts() const { - return _flags & MTPDpeerNotifySettings::Flag::f_silent; +NotifySettingsValue::NotifySettingsValue( + const MTPDpeerNotifySettings &data) { + change(data); } bool NotifySettingsValue::change(const MTPDpeerNotifySettings &data) { - return change(data.vflags.v, data.vmute_until.v, qs(data.vsound)); + return change(data.has_mute_until() + ? base::make_optional(data.vmute_until.v) + : base::none, data.has_sound() + ? base::make_optional(qs(data.vsound)) + : base::none, data.has_show_previews() + ? base::make_optional(mtpIsTrue(data.vshow_previews)) + : base::none, data.has_silent() + ? base::make_optional(mtpIsTrue(data.vsilent)) + : base::none); } bool NotifySettingsValue::change( - MuteChange mute, - SilentPostsChange silent, - int muteForSeconds) { - const auto newFlags = [&] { - auto result = _flags; - if (silent == SilentPostsChange::Silent) { - result |= MTPDpeerNotifySettings::Flag::f_silent; - } else if (silent == SilentPostsChange::Notify) { - result &= ~MTPDpeerNotifySettings::Flag::f_silent; - } - return result; - }(); - const auto newMute = (mute == MuteChange::Mute) - ? (unixtime() + muteForSeconds) - : (mute == MuteChange::Ignore) ? _mute : 0; - const auto newSound = (newMute == 0 && _sound.isEmpty()) + base::optional muteForSeconds, + base::optional silentPosts) { + const auto now = unixtime(); + const auto notMuted = muteForSeconds + ? !(*muteForSeconds) + : (!_mute || *_mute <= now); + return change(muteForSeconds + ? base::make_optional((*muteForSeconds > 0) + ? (now + *muteForSeconds) + : 0) + : base::none, (_sound && _sound->isEmpty() && notMuted) ? qsl("default") - : _sound; - return change(newFlags, newMute, newSound); + : _sound, _showPreviews, silentPosts + ? base::make_optional(*silentPosts) + : base::none); } bool NotifySettingsValue::change( - MTPDpeerNotifySettings::Flags flags, - TimeId mute, - QString sound) { - if (_flags == flags && _mute == mute && _sound == sound) { + base::optional mute, + base::optional sound, + base::optional showPreviews, + base::optional silentPosts) { + if (_mute == mute + && _sound == sound + && _showPreviews == showPreviews + && _silent == silentPosts) { return false; } - _flags = flags; _mute = mute; _sound = sound; + _showPreviews = showPreviews; + _silent = silentPosts; return true; } -TimeMs NotifySettingsValue::muteFinishesIn() const { - auto now = unixtime(); - if (_mute > now) { - return (_mute - now + 1) * 1000LL; - } - return 0; +base::optional NotifySettingsValue::muteUntil() const { + return _mute; +} + +base::optional NotifySettingsValue::silentPosts() const { + return _silent; } MTPinputPeerNotifySettings NotifySettingsValue::serialize() const { + using Flag = MTPDinputPeerNotifySettings::Flag; + const auto flag = [](auto &&optional, Flag flag) { + return optional.has_value() ? flag : Flag(0); + }; return MTP_inputPeerNotifySettings( - MTP_flags(mtpCastFlags(_flags)), - MTP_int(_mute), - MTP_string(_sound)); + MTP_flags(flag(_mute, Flag::f_mute_until) + | flag(_sound, Flag::f_sound) + | flag(_silent, Flag::f_silent) + | flag(_showPreviews, Flag::f_show_previews)), + MTP_bool(_showPreviews ? *_showPreviews : true), + MTP_bool(_silent ? *_silent : false), + MTP_int(_mute ? *_mute : false), + MTP_string(_sound ? *_sound : QString())); } +NotifySettings::NotifySettings() = default; + bool NotifySettings::change(const MTPPeerNotifySettings &settings) { Expects(settings.type() == mtpc_peerNotifySettings); auto &data = settings.c_peerNotifySettings(); + const auto empty = !data.vflags.v; + if (empty) { + if (!_known || _value) { + _known = true; + _value = nullptr; + return true; + } + return false; + } if (_value) { return _value->change(data); } @@ -125,47 +149,42 @@ bool NotifySettings::change(const MTPPeerNotifySettings &settings) { return true; } -NotifySettings::NotifySettings() = default; - bool NotifySettings::change( - MuteChange mute, - SilentPostsChange silent, - int muteForSeconds) { - Expects(mute != MuteChange::Mute || muteForSeconds > 0); - - if (mute == MuteChange::Ignore && silent == SilentPostsChange::Ignore) { + base::optional muteForSeconds, + base::optional silentPosts) { + if (!muteForSeconds && !silentPosts) { return false; + } else if (_value) { + return _value->change(muteForSeconds, silentPosts); } - if (_value) { - return _value->change(mute, silent, muteForSeconds); - } - const auto flags = MTPDpeerNotifySettings::Flag::f_show_previews - | ((silent == SilentPostsChange::Silent) - ? MTPDpeerNotifySettings::Flag::f_silent - : MTPDpeerNotifySettings::Flag(0)); - const auto muteUntil = (mute == MuteChange::Mute) - ? (unixtime() + muteForSeconds) + using Flag = MTPDpeerNotifySettings::Flag; + const auto flags = (muteForSeconds ? Flag::f_mute_until : Flag(0)) + | (silentPosts ? Flag::f_silent : Flag(0)); + const auto muteUntil = muteForSeconds + ? (unixtime() + *muteForSeconds) : 0; return change(MTP_peerNotifySettings( MTP_flags(flags), - MTP_int(muteUntil), - MTP_string("default"))); + MTPBool(), + silentPosts ? MTP_bool(*silentPosts) : MTPBool(), + muteForSeconds ? MTP_int(unixtime() + *muteForSeconds) : MTPint(), + MTPstring())); } -TimeMs NotifySettings::muteFinishesIn() const { +base::optional NotifySettings::muteUntil() const { return _value - ? _value->muteFinishesIn() - : 0LL; + ? _value->muteUntil() + : base::none; } bool NotifySettings::settingsUnknown() const { return !_known; } -bool NotifySettings::silentPosts() const { +base::optional NotifySettings::silentPosts() const { return _value ? _value->silentPosts() - : false; + : base::none; } MTPinputPeerNotifySettings NotifySettings::serialize() const { diff --git a/Telegram/SourceFiles/data/data_notify_settings.h b/Telegram/SourceFiles/data/data_notify_settings.h index 660a29efb..bdce3fb27 100644 --- a/Telegram/SourceFiles/data/data_notify_settings.h +++ b/Telegram/SourceFiles/data/data_notify_settings.h @@ -15,25 +15,16 @@ class NotifySettings { public: NotifySettings(); - enum class MuteChange { - Ignore, - Mute, - Unmute, - }; - enum class SilentPostsChange { - Ignore, - Silent, - Notify, - }; + static constexpr auto kDefaultMutePeriod = 86400 * 365; bool change(const MTPPeerNotifySettings &settings); bool change( - MuteChange mute, - SilentPostsChange silent, - int muteForSeconds); - TimeMs muteFinishesIn() const; + base::optional muteForSeconds, + base::optional silentPosts); + bool settingsUnknown() const; - bool silentPosts() const; + base::optional muteUntil() const; + base::optional silentPosts() const; MTPinputPeerNotifySettings serialize() const; ~NotifySettings(); diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h index d1790c61b..1b98a8011 100644 --- a/Telegram/SourceFiles/data/data_peer.h +++ b/Telegram/SourceFiles/data/data_peer.h @@ -68,30 +68,26 @@ public: bool isVerified() const; bool isMegagroup() const; - TimeMs notifyMuteFinishesIn() const { - return _notify.muteFinishesIn(); + base::optional notifyMuteUntil() const { + return _notify.muteUntil(); } bool notifyChange(const MTPPeerNotifySettings &settings) { return _notify.change(settings); } bool notifyChange( - Data::NotifySettings::MuteChange mute, - Data::NotifySettings::SilentPostsChange silent, - int muteForSeconds) { - return _notify.change(mute, silent, muteForSeconds); + base::optional muteForSeconds, + base::optional silentPosts) { + return _notify.change(muteForSeconds, silentPosts); } bool notifySettingsUnknown() const { return _notify.settingsUnknown(); } - bool notifySilentPosts() const { + base::optional notifySilentPosts() const { return _notify.silentPosts(); } MTPinputPeerNotifySettings notifySerialize() const { return _notify.serialize(); } - bool isMuted() const { - return (notifyMuteFinishesIn() > 0); - } bool canWrite() const; UserData *asUser(); diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 8486fcde7..d3705c9e4 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "observer_peer.h" #include "auth_session.h" #include "apiwrap.h" +#include "window/notifications_manager.h" #include "history/history.h" #include "history/history_item_components.h" #include "history/history_media.h" @@ -26,6 +27,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Data { namespace { +constexpr auto kMaxNotifyCheckDelay = 24 * 3600 * TimeMs(1000); + using ViewElement = HistoryView::Element; // s: box 100x100 @@ -59,7 +62,8 @@ void UpdateImage(ImagePtr &old, ImagePtr now) { Session::Session(not_null session) : _session(session) -, _groups(this) { +, _groups(this) +, _unmuteByFinishedTimer([=] { unmuteByFinished(); }) { setupContactViewsViewer(); setupChannelLeavingViewer(); } @@ -545,6 +549,77 @@ void Session::setIsPinned(const Dialogs::Key &key, bool pinned) { } } +NotifySettings &Session::defaultNotifySettings( + not_null peer) { + return peer->isUser() + ? _defaultUserNotifySettings + : _defaultChatNotifySettings; +} + +const NotifySettings &Session::defaultNotifySettings( + not_null peer) const { + return peer->isUser() + ? _defaultUserNotifySettings + : _defaultChatNotifySettings; +} + +void Session::updateNotifySettingsLocal(not_null peer) { + const auto history = App::historyLoaded(peer->id); + auto changesIn = TimeMs(0); + const auto muted = notifyIsMuted(peer, &changesIn); + if (history && history->changeMute(muted)) { + // Notification already sent. + } else { + Notify::peerUpdatedDelayed( + peer, + Notify::PeerUpdate::Flag::NotificationsEnabled); + } + + if (muted) { + _mutedPeers.emplace(peer); + unmuteByFinishedDelayed(changesIn); + if (history) { + _session->notifications().clearFromHistory(history); + } + } else { + _mutedPeers.erase(peer); + } +} + +void Session::unmuteByFinishedDelayed(TimeMs delay) { + accumulate_max(delay, kMaxNotifyCheckDelay); + if (!_unmuteByFinishedTimer.isActive() + || _unmuteByFinishedTimer.remainingTime() > delay) { + _unmuteByFinishedTimer.callOnce(delay); + } +} + +void Session::unmuteByFinished() { + auto changesInMin = TimeMs(0); + for (auto i = begin(_mutedPeers); i != end(_mutedPeers);) { + const auto history = App::historyLoaded((*i)->id); + auto changesIn = TimeMs(0); + const auto muted = notifyIsMuted(*i, &changesIn); + if (muted) { + if (history) { + history->changeMute(true); + } + if (!changesInMin || changesInMin > changesIn) { + changesInMin = changesIn; + } + ++i; + } else { + if (history) { + history->changeMute(false); + } + i = _mutedPeers.erase(i); + } + } + if (changesInMin) { + unmuteByFinishedDelayed(changesInMin); + } +} + not_null Session::photo(PhotoId id) { auto i = _photos.find(id); if (i == _photos.end()) { @@ -1579,6 +1654,148 @@ rpl::producer Session::defaultFeedIdValue() const { return _defaultFeedId.value(); } +void Session::requestNotifySettings(not_null peer) { + if (peer->notifySettingsUnknown()) { + _session->api().requestNotifySettings( + MTP_inputNotifyPeer(peer->input)); + } + if (defaultNotifySettings(peer).settingsUnknown()) { + _session->api().requestNotifySettings(peer->isUser() + ? MTP_inputNotifyUsers() + : MTP_inputNotifyChats()); + } +} + +void Session::applyNotifySetting( + const MTPNotifyPeer ¬ifyPeer, + const MTPPeerNotifySettings &settings) { + switch (notifyPeer.type()) { + case mtpc_notifyUsers: { + if (_defaultUserNotifySettings.change(settings)) { + _defaultUserNotifyUpdates.fire({}); + + App::enumerateUsers([&](not_null user) { + if (!user->notifySettingsUnknown() + && ((!user->notifyMuteUntil() + && _defaultUserNotifySettings.muteUntil()) + || (!user->notifySilentPosts() + && _defaultUserNotifySettings.silentPosts()))) { + updateNotifySettingsLocal(user); + } + }); + } + } break; + case mtpc_notifyChats: { + if (_defaultChatNotifySettings.change(settings)) { + _defaultChatNotifyUpdates.fire({}); + + App::enumerateChatsChannels([&](not_null peer) { + if (!peer->notifySettingsUnknown() + && ((!peer->notifyMuteUntil() + && _defaultUserNotifySettings.muteUntil()) + || (!peer->notifySilentPosts() + && _defaultUserNotifySettings.silentPosts()))) { + if (!peer->notifyMuteUntil()) { + int a = 0; + } + updateNotifySettingsLocal(peer); + } + }); + } + } break; + case mtpc_notifyPeer: { + const auto &data = notifyPeer.c_notifyPeer(); + if (const auto peer = App::peerLoaded(peerFromMTP(data.vpeer))) { + if (peer->notifyChange(settings)) { + updateNotifySettingsLocal(peer); + } + } + } break; + } +} + +void Session::updateNotifySettings( + not_null peer, + base::optional muteForSeconds, + base::optional silentPosts) { + if (peer->notifyChange(muteForSeconds, silentPosts)) { + updateNotifySettingsLocal(peer); + _session->api().updateNotifySettingsDelayed(peer); + } +} + +bool Session::notifyIsMuted( + not_null peer, + TimeMs *changesIn) const { + const auto resultFromUntil = [&](TimeId until) { + const auto now = unixtime(); + const auto result = (until > now) ? (until - now) : 0; + if (changesIn) { + *changesIn = (result > 0) + ? std::min(result * TimeMs(1000), kMaxNotifyCheckDelay) + : kMaxNotifyCheckDelay; + } + return (result > 0); + }; + if (const auto until = peer->notifyMuteUntil()) { + return resultFromUntil(*until); + } + const auto &settings = defaultNotifySettings(peer); + if (const auto until = settings.muteUntil()) { + return resultFromUntil(*until); + } + return false; +} + +bool Session::notifySilentPosts(not_null peer) const { + if (const auto silent = peer->notifySilentPosts()) { + return *silent; + } + const auto &settings = defaultNotifySettings(peer); + if (const auto silent = settings.silentPosts()) { + return *silent; + } + return false; +} + +bool Session::notifyMuteUnknown(not_null peer) const { + if (peer->notifySettingsUnknown()) { + return true; + } else if (const auto nonDefault = peer->notifyMuteUntil()) { + return false; + } + return defaultNotifySettings(peer).settingsUnknown(); +} + +bool Session::notifySilentPostsUnknown( + not_null peer) const { + if (peer->notifySettingsUnknown()) { + return true; + } else if (const auto nonDefault = peer->notifySilentPosts()) { + return false; + } + return defaultNotifySettings(peer).settingsUnknown(); +} + +bool Session::notifySettingsUnknown(not_null peer) const { + return notifyMuteUnknown(peer) || notifySilentPostsUnknown(peer); +} + +rpl::producer<> Session::defaultUserNotifyUpdates() const { + return _defaultUserNotifyUpdates.events(); +} + +rpl::producer<> Session::defaultChatNotifyUpdates() const { + return _defaultChatNotifyUpdates.events(); +} + +rpl::producer<> Session::defaultNotifyUpdates( + not_null peer) const { + return peer->isUser() + ? defaultUserNotifyUpdates() + : defaultChatNotifyUpdates(); +} + void Session::forgetMedia() { for (const auto &[id, photo] : _photos) { photo->forget(); diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index c3bea5698..fbbf39b9d 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "chat_helpers/stickers.h" #include "dialogs/dialogs_key.h" #include "data/data_groups.h" +#include "base/timer.h" class HistoryItem; @@ -358,6 +359,26 @@ public: FeedId defaultFeedId() const; rpl::producer defaultFeedIdValue() const; + void requestNotifySettings(not_null peer); + void applyNotifySetting( + const MTPNotifyPeer ¬ifyPeer, + const MTPPeerNotifySettings &settings); + void updateNotifySettings( + not_null peer, + base::optional muteForSeconds, + base::optional silentPosts = base::none); + bool notifyIsMuted( + not_null peer, + TimeMs *changesIn = nullptr) const; + bool notifySilentPosts(not_null peer) const; + bool notifyMuteUnknown(not_null peer) const; + bool notifySilentPostsUnknown(not_null peer) const; + bool notifySettingsUnknown(not_null peer) const; + rpl::producer<> defaultUserNotifyUpdates() const; + rpl::producer<> defaultChatNotifyUpdates() const; + rpl::producer<> defaultNotifyUpdates( + not_null peer) const; + void forgetMedia(); void setMimeForwardIds(MessageIdsList &&list); @@ -453,6 +474,14 @@ private: void clearPinnedDialogs(); void setIsPinned(const Dialogs::Key &key, bool pinned); + NotifySettings &defaultNotifySettings(not_null peer); + const NotifySettings &defaultNotifySettings( + not_null peer) const; + void unmuteByFinished(); + void unmuteByFinishedDelayed(TimeMs delay); + void updateNotifySettingsLocal(not_null peer); + void sendNotifySettingsUpdates(); + template void enumerateItemViews( not_null item, @@ -548,6 +577,13 @@ private: PeerData *_proxyPromoted = nullptr; + NotifySettings _defaultUserNotifySettings; + NotifySettings _defaultChatNotifySettings; + rpl::event_stream<> _defaultUserNotifyUpdates; + rpl::event_stream<> _defaultChatNotifyUpdates; + std::unordered_set> _mutedPeers; + base::Timer _unmuteByFinishedTimer; + MessageIdsList _mimeForwardIds; rpl::lifetime _lifetime; diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index 100b38b2c..8a52b63c6 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -224,7 +224,7 @@ History::History(const PeerId &peerId) : Entry(this) , peer(App::peer(peerId)) , cloudDraftTextCache(st::dialogsTextWidthMin) -, _mute(peer->isMuted()) +, _mute(Auth().data().notifyIsMuted(peer)) , _sendActionText(st::dialogsTextWidthMin) { if (const auto user = peer->asUser()) { if (user->botInfo) { @@ -2194,10 +2194,9 @@ void History::applyDialog(const MTPDdialog &data) { } } } - App::main()->applyNotifySetting( + Auth().data().applyNotifySetting( MTP_notifyPeer(data.vpeer), - data.vnotify_settings, - this); + data.vnotify_settings); if (data.has_draft() && data.vdraft.type() == mtpc_draftMessage) { Data::applyPeerCloudDraft(peer->id, data.vdraft.c_draftMessage()); } diff --git a/Telegram/SourceFiles/history/history_message.cpp b/Telegram/SourceFiles/history/history_message.cpp index 74de41096..9d3794bb5 100644 --- a/Telegram/SourceFiles/history/history_message.cpp +++ b/Telegram/SourceFiles/history/history_message.cpp @@ -610,7 +610,7 @@ bool HistoryMessage::allowsEdit(TimeId now) const { return true; } if (out()) { - return !isPost() || channel->canPublish(); + return isPost() ? channel->canPublish() : channel->canWrite(); } } return out(); diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index d23486ddf..91a74c759 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -665,7 +665,7 @@ HistoryWidget::HistoryWidget( } } if (update.flags & UpdateFlag::NotificationsEnabled) { - updateNotifySettings(); + updateNotifyControls(); } if (update.flags & UpdateFlag::RestrictionReasonChanged) { auto restriction = _peer->restrictionReason(); @@ -699,6 +699,12 @@ HistoryWidget::HistoryWidget( } } })); + rpl::merge( + Auth().data().defaultUserNotifyUpdates(), + Auth().data().defaultChatNotifyUpdates() + ) | rpl::start_with_next([=] { + updateNotifyControls(); + }, lifetime()); subscribe(Auth().data().queryItemVisibility(), [this](const Data::Session::ItemVisibilityQuery &query) { if (_a_show.animating() || _history != query.item->history() @@ -1848,10 +1854,8 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re updateTopBarSelection(); if (_channel) { - updateNotifySettings(); - if (_peer->notifySettingsUnknown()) { - Auth().api().requestNotifySetting(_peer); - } + updateNotifyControls(); + Auth().data().requestNotifySettings(_peer); refreshSilentToggle(); } @@ -1955,15 +1959,15 @@ void HistoryWidget::updateFieldSubmitSettings() { _field->setSubmitSettings(settings); } -void HistoryWidget::updateNotifySettings() { +void HistoryWidget::updateNotifyControls() { if (!_peer || !_peer->isChannel()) return; _muteUnmute->setText(lang(_history->mute() ? lng_channel_unmute : lng_channel_mute).toUpper()); - if (!_peer->notifySettingsUnknown()) { + if (!Auth().data().notifySilentPostsUnknown(_peer)) { if (_silent) { - _silent->setChecked(_peer->notifySilentPosts()); + _silent->setChecked(Auth().data().notifySilentPosts(_peer)); } else if (hasSilentToggle()) { refreshSilentToggle(); updateControlsGeometry(); @@ -2925,6 +2929,7 @@ void HistoryWidget::saveEditMsg() { _history->peer->input, MTP_int(_editMsgId), MTP_string(sending.text), + MTPInputMedia(), MTPnullMarkup, sentEntities, MTP_inputGeoPointEmpty()), @@ -3078,10 +3083,10 @@ void HistoryWidget::onJoinChannel() { } void HistoryWidget::onMuteUnmute() { - const auto muteState = _history->mute() - ? Data::NotifySettings::MuteChange::Unmute - : Data::NotifySettings::MuteChange::Mute; - App::main()->updateNotifySettings(_peer, muteState); + const auto muteForSeconds = _history->mute() + ? 0 + : Data::NotifySettings::kDefaultMutePeriod; + Auth().data().updateNotifySettings(_peer, muteForSeconds); } void HistoryWidget::onBroadcastSilentChange() { @@ -3633,7 +3638,7 @@ bool HistoryWidget::hasSilentToggle() const { && _peer->isChannel() && !_peer->isMegagroup() && _peer->canWrite() - && !_peer->notifySettingsUnknown(); + && !Auth().data().notifySilentPostsUnknown(_peer); } void HistoryWidget::inlineBotResolveDone( @@ -4094,7 +4099,7 @@ void HistoryWidget::updateFieldPlaceholder() { const auto peer = _history ? _history->peer.get() : nullptr; _field->setPlaceholder(langFactory( (peer && peer->isChannel() && !peer->isMegagroup()) - ? (peer->notifySilentPosts() + ? (Auth().data().notifySilentPosts(peer) ? lng_broadcast_silent_ph : lng_broadcast_ph) : lng_message_ph)); @@ -4412,7 +4417,9 @@ void HistoryWidget::sendFileConfirmed( flags |= MTPDmessage::Flag::f_grouped_id; } auto messageFromId = channelPost ? 0 : Auth().userId(); - auto messagePostAuthor = channelPost ? (Auth().user()->firstName + ' ' + Auth().user()->lastName) : QString(); + auto messagePostAuthor = channelPost + ? App::peerName(Auth().user()) + : QString(); if (file->type == SendMediaType::Photo) { auto photoFlags = MTPDmessageMediaPhoto::Flag::f_photo | 0; auto photo = MTP_messageMediaPhoto( @@ -5385,7 +5392,7 @@ void HistoryWidget::onInlineResultSend( sendFlags |= MTPmessages_SendInlineBotResult::Flag::f_reply_to_msg_id; } bool channelPost = _peer->isChannel() && !_peer->isMegagroup(); - bool silentPost = channelPost && _peer->notifySilentPosts(); + bool silentPost = channelPost && Auth().data().notifySilentPosts(_peer); if (channelPost) { flags |= MTPDmessage::Flag::f_views; flags |= MTPDmessage::Flag::f_post; @@ -5403,7 +5410,9 @@ void HistoryWidget::onInlineResultSend( } auto messageFromId = channelPost ? 0 : Auth().userId(); - auto messagePostAuthor = channelPost ? (Auth().user()->firstName + ' ' + Auth().user()->lastName) : QString(); + auto messagePostAuthor = channelPost + ? App::peerName(Auth().user()) + : QString(); MTPint messageDate = MTP_int(unixtime()); UserId messageViaBotId = bot ? peerToUser(bot->id) : 0; MsgId messageId = newId.msg; @@ -5594,7 +5603,7 @@ bool HistoryWidget::sendExistingDocument( sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to_msg_id; } bool channelPost = _peer->isChannel() && !_peer->isMegagroup(); - bool silentPost = channelPost && _peer->notifySilentPosts(); + bool silentPost = channelPost && Auth().data().notifySilentPosts(_peer); if (channelPost) { flags |= MTPDmessage::Flag::f_views; flags |= MTPDmessage::Flag::f_post; @@ -5608,7 +5617,8 @@ bool HistoryWidget::sendExistingDocument( sendFlags |= MTPmessages_SendMedia::Flag::f_silent; } auto messageFromId = channelPost ? 0 : Auth().userId(); - auto messagePostAuthor = channelPost ? (Auth().user()->firstName + ' ' + Auth().user()->lastName) : QString(); + auto messagePostAuthor = channelPost + ? App::peerName(Auth().user()) : QString(); TextUtilities::Trim(caption); auto sentEntities = TextUtilities::EntitiesToMTP( @@ -5690,7 +5700,7 @@ void HistoryWidget::sendExistingPhoto( sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to_msg_id; } bool channelPost = _peer->isChannel() && !_peer->isMegagroup(); - bool silentPost = channelPost && _peer->notifySilentPosts(); + bool silentPost = channelPost && Auth().data().notifySilentPosts(_peer); if (channelPost) { flags |= MTPDmessage::Flag::f_views; flags |= MTPDmessage::Flag::f_post; @@ -5704,7 +5714,9 @@ void HistoryWidget::sendExistingPhoto( sendFlags |= MTPmessages_SendMedia::Flag::f_silent; } auto messageFromId = channelPost ? 0 : Auth().userId(); - auto messagePostAuthor = channelPost ? (Auth().user()->firstName + ' ' + Auth().user()->lastName) : QString(); + auto messagePostAuthor = channelPost + ? App::peerName(Auth().user()) + : QString(); TextUtilities::Trim(caption); auto sentEntities = TextUtilities::EntitiesToMTP( diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index 5a6b92874..5ca18c875 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -318,7 +318,7 @@ public: void setInnerFocus(); - void updateNotifySettings(); + void updateNotifyControls(); void saveGif(DocumentData *doc); diff --git a/Telegram/SourceFiles/info/feed/info_feed_channels_controllers.cpp b/Telegram/SourceFiles/info/feed/info_feed_channels_controllers.cpp index c75e85719..42592d8e6 100644 --- a/Telegram/SourceFiles/info/feed/info_feed_channels_controllers.cpp +++ b/Telegram/SourceFiles/info/feed/info_feed_channels_controllers.cpp @@ -212,18 +212,17 @@ base::unique_qptr ChannelsController::rowContextMenu( void NotificationsController::Start(not_null feed) { const auto initBox = [=](not_null box) { box->addButton(langFactory(lng_settings_save), [=] { - const auto main = App::main(); const auto count = box->peerListFullRowsCount(); for (auto i = 0; i != count; ++i) { const auto row = box->peerListRowAt(i); const auto peer = row->peer(); const auto muted = !row->checked(); - if (muted != peer->isMuted()) { - main->updateNotifySettings( + if (muted != Auth().data().notifyIsMuted(peer)) { + Auth().data().updateNotifySettings( peer, (muted - ? Data::NotifySettings::MuteChange::Mute - : Data::NotifySettings::MuteChange::Unmute)); + ? Data::NotifySettings::kDefaultMutePeriod + : 0)); } } box->closeBox(); @@ -320,7 +319,7 @@ void NotificationsController::applyFeedDialogs( auto notMutedChannels = ranges::view::all( channels ) | ranges::view::filter([](not_null channel) { - return !channel->isMuted(); + return !Auth().data().notifyIsMuted(channel); }); delegate()->peerListAddSelectedRows(notMutedChannels); for (const auto channel : channels) { diff --git a/Telegram/SourceFiles/info/info_wrap_widget.cpp b/Telegram/SourceFiles/info/info_wrap_widget.cpp index cee5368d5..72b1527c2 100644 --- a/Telegram/SourceFiles/info/info_wrap_widget.cpp +++ b/Telegram/SourceFiles/info/info_wrap_widget.cpp @@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_peer_menu.h" #include "boxes/peer_list_box.h" #include "auth_session.h" +#include "data/data_session.h" #include "mainwidget.h" #include "lang/lang_keys.h" #include "styles/style_info.h" @@ -449,10 +450,10 @@ void WrapWidget::addProfileNotificationsButton() { ? st::infoLayerTopBarNotifications : st::infoTopBarNotifications))); notifications->addClickHandler([peer] { - const auto muteState = peer->isMuted() - ? Data::NotifySettings::MuteChange::Unmute - : Data::NotifySettings::MuteChange::Mute; - App::main()->updateNotifySettings(peer, muteState); + const auto muteForSeconds = Auth().data().notifyIsMuted(peer) + ? 0 + : Data::NotifySettings::kDefaultMutePeriod; + Auth().data().updateNotifySettings(peer, muteForSeconds); }); Profile::NotificationsEnabledValue( peer diff --git a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp index 685298e3d..10a76fc01 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp @@ -310,10 +310,10 @@ object_ptr DetailsFiller::setupMuteToggle() { result->toggleOn( NotificationsEnabledValue(peer) )->addClickHandler([=] { - const auto muteState = peer->isMuted() - ? Data::NotifySettings::MuteChange::Unmute - : Data::NotifySettings::MuteChange::Mute; - App::main()->updateNotifySettings(peer, muteState); + const auto muteForSeconds = Auth().data().notifyIsMuted(peer) + ? 0 + : Data::NotifySettings::kDefaultMutePeriod; + Auth().data().updateNotifySettings(peer, muteForSeconds); }); object_ptr( result, diff --git a/Telegram/SourceFiles/info/profile/info_profile_values.cpp b/Telegram/SourceFiles/info/profile/info_profile_values.cpp index a2bde3ada..de133e4c8 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_values.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_values.cpp @@ -115,11 +115,14 @@ rpl::producer LinkValue( rpl::producer NotificationsEnabledValue( not_null peer) { - return Notify::PeerUpdateValue( + return rpl::merge( + Notify::PeerUpdateValue( peer, Notify::PeerUpdate::Flag::NotificationsEnabled + ) | rpl::map([] { return rpl::empty_value(); }), + Auth().data().defaultNotifyUpdates(peer) ) | rpl::map([peer] { - return !peer->isMuted(); + return !Auth().data().notifyIsMuted(peer); }) | rpl::distinct_until_changed(); } diff --git a/Telegram/SourceFiles/intro/introphone.cpp b/Telegram/SourceFiles/intro/introphone.cpp index 2cf89553d..f337b7110 100644 --- a/Telegram/SourceFiles/intro/introphone.cpp +++ b/Telegram/SourceFiles/intro/introphone.cpp @@ -106,22 +106,22 @@ void PhoneWidget::hidePhoneError() { } } -void PhoneWidget::showSignup() { - showPhoneError(langFactory(lng_bad_phone_noreg)); - if (!_signup) { - auto signupText = lng_phone_notreg(lt_link_start, textcmdStartLink(1), lt_link_end, textcmdStopLink(), lt_signup_start, textcmdStartLink(2), lt_signup_end, textcmdStopLink()); - auto inner = object_ptr(this, signupText, Ui::FlatLabel::InitType::Rich, st::introDescription); - _signup.create(this, std::move(inner)); - _signup->entity()->setLink(1, std::make_shared(qsl("https://telegram.org"), false)); - _signup->entity()->setLink(2, std::make_shared([this] { - toSignUp(); - })); - _signup->hide(anim::type::instant); - updateSignupGeometry(); - } - _signup->show(anim::type::normal); - hideDescription(); -} +//void PhoneWidget::showSignup() { +// showPhoneError(langFactory(lng_bad_phone_noreg)); +// if (!_signup) { +// auto signupText = lng_phone_notreg(lt_link_start, textcmdStartLink(1), lt_link_end, textcmdStopLink(), lt_signup_start, textcmdStartLink(2), lt_signup_end, textcmdStopLink()); +// auto inner = object_ptr(this, signupText, Ui::FlatLabel::InitType::Rich, st::introDescription); +// _signup.create(this, std::move(inner)); +// _signup->entity()->setLink(1, std::make_shared(qsl("https://telegram.org"), false)); +// _signup->entity()->setLink(2, std::make_shared([this] { +// toSignUp(); +// })); +// _signup->hide(anim::type::instant); +// updateSignupGeometry(); +// } +// _signup->show(anim::type::normal); +// hideDescription(); +//} void PhoneWidget::countryChanged() { if (!_changed) { @@ -149,7 +149,8 @@ void PhoneWidget::submit() { _sentPhone = fullNumber(); Messenger::Instance().mtp()->setUserPhone(_sentPhone); - _sentRequest = MTP::send(MTPauth_CheckPhone(MTP_string(_sentPhone)), rpcDone(&PhoneWidget::phoneCheckDone), rpcFail(&PhoneWidget::phoneSubmitFail)); + //_sentRequest = MTP::send(MTPauth_CheckPhone(MTP_string(_sentPhone)), rpcDone(&PhoneWidget::phoneCheckDone), rpcFail(&PhoneWidget::phoneSubmitFail)); + _sentRequest = MTP::send(MTPauth_SendCode(MTP_flags(0), MTP_string(_sentPhone), MTPBool(), MTP_int(ApiId), MTP_string(ApiHash)), rpcDone(&PhoneWidget::phoneSubmitDone), rpcFail(&PhoneWidget::phoneSubmitFail)); } void PhoneWidget::stopCheck() { @@ -168,22 +169,22 @@ void PhoneWidget::onCheckRequest() { stopCheck(); } } - -void PhoneWidget::phoneCheckDone(const MTPauth_CheckedPhone &result) { - stopCheck(); - - auto &d = result.c_auth_checkedPhone(); - if (mtpIsTrue(d.vphone_registered)) { - hidePhoneError(); - - _checkRequest->start(1000); - - _sentRequest = MTP::send(MTPauth_SendCode(MTP_flags(0), MTP_string(_sentPhone), MTPBool(), MTP_int(ApiId), MTP_string(ApiHash)), rpcDone(&PhoneWidget::phoneSubmitDone), rpcFail(&PhoneWidget::phoneSubmitFail)); - } else { - showSignup(); - _sentRequest = 0; - } -} +// +//void PhoneWidget::phoneCheckDone(const MTPauth_CheckedPhone &result) { +// stopCheck(); +// +// auto &d = result.c_auth_checkedPhone(); +// if (mtpIsTrue(d.vphone_registered)) { +// hidePhoneError(); +// +// _checkRequest->start(1000); +// +// _sentRequest = MTP::send(MTPauth_SendCode(MTP_flags(0), MTP_string(_sentPhone), MTPBool(), MTP_int(ApiId), MTP_string(ApiHash)), rpcDone(&PhoneWidget::phoneSubmitDone), rpcFail(&PhoneWidget::phoneSubmitFail)); +// } else { +// showSignup(); +// _sentRequest = 0; +// } +//} void PhoneWidget::phoneSubmitDone(const MTPauth_SentCode &result) { stopCheck(); @@ -209,13 +210,13 @@ void PhoneWidget::phoneSubmitDone(const MTPauth_SentCode &result) { goNext(new Intro::CodeWidget(parentWidget(), getData())); } -void PhoneWidget::toSignUp() { - hideError(); // Hide error, but leave the signup label visible. - - _checkRequest->start(1000); - - _sentRequest = MTP::send(MTPauth_SendCode(MTP_flags(0), MTP_string(_sentPhone), MTPBool(), MTP_int(ApiId), MTP_string(ApiHash)), rpcDone(&PhoneWidget::phoneSubmitDone), rpcFail(&PhoneWidget::phoneSubmitFail)); -} +//void PhoneWidget::toSignUp() { +// hideError(); // Hide error, but leave the signup label visible. +// +// _checkRequest->start(1000); +// +// _sentRequest = MTP::send(MTPauth_SendCode(MTP_flags(0), MTP_string(_sentPhone), MTPBool(), MTP_int(ApiId), MTP_string(ApiHash)), rpcDone(&PhoneWidget::phoneSubmitDone), rpcFail(&PhoneWidget::phoneSubmitFail)); +//} bool PhoneWidget::phoneSubmitFail(const RPCError &error) { if (MTP::isFloodError(error)) { diff --git a/Telegram/SourceFiles/intro/introphone.h b/Telegram/SourceFiles/intro/introphone.h index 970b41e31..975d9b0a4 100644 --- a/Telegram/SourceFiles/intro/introphone.h +++ b/Telegram/SourceFiles/intro/introphone.h @@ -48,18 +48,18 @@ private: void updateSignupGeometry(); void countryChanged(); - void phoneCheckDone(const MTPauth_CheckedPhone &result); + //void phoneCheckDone(const MTPauth_CheckedPhone &result); void phoneSubmitDone(const MTPauth_SentCode &result); bool phoneSubmitFail(const RPCError &error); - void toSignUp(); + //void toSignUp(); QString fullNumber() const; void stopCheck(); void showPhoneError(base::lambda textFactory); void hidePhoneError(); - void showSignup(); + //void showSignup(); bool _changed = false; diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index a96628f40..a5e2b52a3 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -228,7 +228,6 @@ MainWidget::MainWidget( connect(&_byPtsTimer, SIGNAL(timeout()), this, SLOT(onGetDifferenceTimeByPts())); connect(&_byMinChannelTimer, SIGNAL(timeout()), this, SLOT(getDifference())); connect(&_failDifferenceTimer, SIGNAL(timeout()), this, SLOT(onGetDifferenceTimeAfterFail())); - connect(&updateNotifySettingTimer, SIGNAL(timeout()), this, SLOT(onUpdateNotifySettings())); subscribe(Media::Player::Updated(), [this](const AudioMsgId &audioId) { if (audioId.type() != AudioMsgId::Type::Video) { handleAudioUpdate(audioId); @@ -268,7 +267,6 @@ MainWidget::MainWidget( QCoreApplication::instance()->installEventFilter(this); - connect(&_updateMutedTimer, SIGNAL(timeout()), this, SLOT(onUpdateMuted())); connect(&_viewsIncrementTimer, SIGNAL(timeout()), this, SLOT(onViewsIncrement())); using Update = Window::Theme::BackgroundUpdate; @@ -715,20 +713,9 @@ void MainWidget::finishForwarding(not_null history) { dialogsToUp(); } -void MainWidget::updateMutedIn(TimeMs delay) { - accumulate_min(delay, 24 * 3600 * 1000LL); - if (!_updateMutedTimer.isActive() - || _updateMutedTimer.remainingTime() > delay) { - _updateMutedTimer.start(delay); - } -} - -void MainWidget::onUpdateMuted() { - App::updateMuted(); -} - bool MainWidget::onSendPaths(const PeerId &peerId) { Expects(peerId != 0); + auto peer = App::peer(peerId); if (!peer->canWrite()) { Ui::show(Box(lang(lng_forward_send_files_cant))); @@ -1296,7 +1283,8 @@ void MainWidget::sendMessage(const MessageToSend &message) { flags |= MTPDmessage::Flag::f_media; } bool channelPost = peer->isChannel() && !peer->isMegagroup(); - bool silentPost = channelPost && peer->notifySilentPosts(); + bool silentPost = channelPost + && Auth().data().notifySilentPosts(peer); if (channelPost) { flags |= MTPDmessage::Flag::f_views; flags |= MTPDmessage::Flag::f_post; @@ -1319,7 +1307,9 @@ void MainWidget::sendMessage(const MessageToSend &message) { history->clearCloudDraft(); } auto messageFromId = channelPost ? 0 : Auth().userId(); - auto messagePostAuthor = channelPost ? (Auth().user()->firstName + ' ' + Auth().user()->lastName) : QString(); + auto messagePostAuthor = channelPost + ? App::peerName(Auth().user()) + : QString(); lastMessage = history->addNewMessage( MTP_message( MTP_flags(flags), @@ -3307,22 +3297,6 @@ void MainWidget::searchInChat(Dialogs::Key chat) { } } -void MainWidget::onUpdateNotifySettings() { - if (this != App::main()) return; - - while (!updateNotifySettingPeers.empty()) { - auto peer = *updateNotifySettingPeers.begin(); - updateNotifySettingPeers.erase(updateNotifySettingPeers.begin()); - MTP::send( - MTPaccount_UpdateNotifySettings( - MTP_inputNotifyPeer(peer->input), - peer->notifySerialize()), - RPCResponseHandler(), - 0, - updateNotifySettingPeers.empty() ? 0 : 10); - } -} - void MainWidget::feedUpdateVector( const MTPVector &updates, bool skipMessageIds) { @@ -3996,62 +3970,6 @@ void MainWidget::startWithSelf(const MTPUserFull &result) { } } -void MainWidget::applyNotifySetting( - const MTPNotifyPeer ¬ifyPeer, - const MTPPeerNotifySettings &settings, - History *history) { - if (notifyPeer.type() != mtpc_notifyPeer) { - // Ignore those for now, they were not ever used. - return; - } - - const auto &data = notifyPeer.c_notifyPeer(); - const auto peer = App::peerLoaded(peerFromMTP(data.vpeer)); - if (!peer || !peer->notifyChange(settings)) { - return; - } - - updateNotifySettingsLocal(peer, history); -} - -void MainWidget::updateNotifySettings( - not_null peer, - Data::NotifySettings::MuteChange mute, - Data::NotifySettings::SilentPostsChange silent, - int muteForSeconds) { - if (peer->notifyChange(mute, silent, muteForSeconds)) { - updateNotifySettingsLocal(peer); - updateNotifySettingPeers.insert(peer); - updateNotifySettingTimer.start(NotifySettingSaveTimeout); - } -} - -void MainWidget::updateNotifySettingsLocal( - not_null peer, - History *history) { - if (!history) { - history = App::historyLoaded(peer->id); - } - - const auto muteFinishesIn = peer->notifyMuteFinishesIn(); - const auto muted = (muteFinishesIn > 0); - if (history && history->changeMute(muted)) { - // Notification already sent. - } else { - Notify::peerUpdatedDelayed( - peer, - Notify::PeerUpdate::Flag::NotificationsEnabled); - } - if (muted) { - App::regMuted(peer, muteFinishesIn); - if (history) { - Auth().notifications().clearFromHistory(history); - } - } else { - App::unregMuted(peer); - } -} - void MainWidget::incrementSticker(DocumentData *sticker) { if (!sticker || !sticker->sticker()) return; if (sticker->sticker()->set.type() == mtpc_inputStickerSetEmpty) return; @@ -4940,7 +4858,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { case mtpc_updateNotifySettings: { auto &d = update.c_updateNotifySettings(); - applyNotifySetting(d.vpeer, d.vnotify_settings); + Auth().data().applyNotifySetting(d.vpeer, d.vnotify_settings); } break; case mtpc_updateDcOptions: { diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 31147d06e..fa7770d16 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -93,17 +93,6 @@ public: void stickersBox(const MTPInputStickerSet &set); bool started(); - void applyNotifySetting( - const MTPNotifyPeer ¬ifyPeer, - const MTPPeerNotifySettings &settings, - History *history = 0); - - void updateNotifySettings( - not_null peer, - Data::NotifySettings::MuteChange mute, - Data::NotifySettings::SilentPostsChange silent - = Data::NotifySettings::SilentPostsChange::Ignore, - int muteForSeconds = 86400 * 365); void incrementSticker(DocumentData *sticker); @@ -275,8 +264,6 @@ public: void cancelForwarding(not_null history); void finishForwarding(not_null history); - void updateMutedIn(TimeMs delay); - // Does offerPeer or showPeerHistory. void choosePeer(PeerId peerId, MsgId showAtMsgId); void clearBotStartToken(PeerData *peer); @@ -355,14 +342,10 @@ public slots: void updateOnline(bool gotOtherOffline = false); void checkIdleFinish(); - void onUpdateNotifySettings(); - void onCacheBackground(); void onInviteImport(); - void onUpdateMuted(); - void onViewsIncrement(); protected: @@ -535,15 +518,9 @@ private: void ensureFirstColumnResizeAreaCreated(); void ensureThirdColumnResizeAreaCreated(); - void updateNotifySettingsLocal( - not_null peer, - History *history = nullptr); - not_null _controller; bool _started = false; - SingleTimer _updateMutedTimer; - QString _inviteHash; Animation _a_show; @@ -607,9 +584,6 @@ private: TimeMs _lastSetOnline = 0; bool _isIdle = false; - base::flat_set> updateNotifySettingPeers; - SingleTimer updateNotifySettingTimer; - int32 _failDifferenceTimeout = 1; // growing timeout for getDifference calls, if it fails typedef QMap ChannelFailDifferenceTimeout; ChannelFailDifferenceTimeout _channelFailDifferenceTimeout; // growing timeout for getChannelDifference calls, if it fails diff --git a/Telegram/SourceFiles/stdafx.h b/Telegram/SourceFiles/stdafx.h index ff0690ce3..f751893b4 100644 --- a/Telegram/SourceFiles/stdafx.h +++ b/Telegram/SourceFiles/stdafx.h @@ -54,6 +54,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include #include +#include #include #include diff --git a/Telegram/SourceFiles/ui/special_buttons.cpp b/Telegram/SourceFiles/ui/special_buttons.cpp index 6196505a1..dbc33c63c 100644 --- a/Telegram/SourceFiles/ui/special_buttons.cpp +++ b/Telegram/SourceFiles/ui/special_buttons.cpp @@ -918,8 +918,8 @@ QPoint FeedUserpicButton::countInnerPosition() const { SilentToggle::SilentToggle(QWidget *parent, not_null channel) : IconButton(parent, st::historySilentToggle) , _channel(channel) -, _checked(_channel->notifySilentPosts()) { - Expects(!_channel->notifySettingsUnknown()); +, _checked(Auth().data().notifySilentPosts(_channel)) { + Expects(!Auth().data().notifySilentPostsUnknown(_channel)); if (_checked) { refreshIconOverrides(); @@ -962,13 +962,10 @@ void SilentToggle::mouseReleaseEvent(QMouseEvent *e) { setChecked(!_checked); IconButton::mouseReleaseEvent(e); Ui::Tooltip::Show(0, this); - const auto silentState = _checked - ? Data::NotifySettings::SilentPostsChange::Silent - : Data::NotifySettings::SilentPostsChange::Notify; - App::main()->updateNotifySettings( + Auth().data().updateNotifySettings( _channel, - Data::NotifySettings::MuteChange::Ignore, - silentState); + base::none, + _checked); } QString SilentToggle::tooltipText() const { diff --git a/Telegram/SourceFiles/window/notifications_manager.cpp b/Telegram/SourceFiles/window/notifications_manager.cpp index 81c413ddd..7a6ab813b 100644 --- a/Telegram/SourceFiles/window/notifications_manager.cpp +++ b/Telegram/SourceFiles/window/notifications_manager.cpp @@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_item_components.h" #include "history/feed/history_feed_section.h" #include "lang/lang_keys.h" +#include "data/data_session.h" #include "window/window_controller.h" #include "mainwindow.h" #include "mainwidget.h" @@ -59,7 +60,7 @@ void System::createManager() { void System::schedule(History *history, HistoryItem *item) { if (App::quitting() || !history->currentNotification() || !AuthSession::Exists()) return; - auto notifyByFrom = (!history->peer->isUser() && item->mentionsMe()) + const auto notifyBy = (!history->peer->isUser() && item->mentionsMe()) ? item->from().get() : nullptr; @@ -68,35 +69,31 @@ void System::schedule(History *history, HistoryItem *item) { return; } - auto haveSetting = !history->peer->notifySettingsUnknown(); - if (haveSetting) { - if (history->peer->isMuted()) { - if (notifyByFrom) { - haveSetting = !item->from()->notifySettingsUnknown(); - if (haveSetting) { - if (notifyByFrom->isMuted()) { - history->popNotification(item); - return; - } - } else { - Auth().api().requestNotifySetting(notifyByFrom); + Auth().data().requestNotifySettings(history->peer); + if (notifyBy) { + Auth().data().requestNotifySettings(notifyBy); + } + auto haveSetting = !Auth().data().notifyMuteUnknown(history->peer); + if (haveSetting && Auth().data().notifyIsMuted(history->peer)) { + if (notifyBy) { + haveSetting = !Auth().data().notifyMuteUnknown(notifyBy); + if (haveSetting) { + if (Auth().data().notifyIsMuted(notifyBy)) { + history->popNotification(item); + return; } - } else { - history->popNotification(item); - return; } + } else { + history->popNotification(item); + return; } - } else { - if (notifyByFrom && notifyByFrom->notifySettingsUnknown()) { - Auth().api().requestNotifySetting(notifyByFrom); - } - Auth().api().requestNotifySetting(history->peer); } if (!item->notificationReady()) { haveSetting = false; } - int delay = item->Has() ? 500 : 100, t = unixtime(); + auto delay = item->Has() ? 500 : 100; + auto t = unixtime(); auto ms = getms(true); bool isOnline = App::main()->lastWasOnline(), otherNotOld = ((cOtherOnline() * 1000LL) + Global::OnlineCloudTimeout() > t * 1000LL); bool otherLaterThanMe = (cOtherOnline() * 1000LL + (ms - App::main()->lastSetOnline()) > t * 1000LL); @@ -107,7 +104,7 @@ void System::schedule(History *history, HistoryItem *item) { } auto when = ms + delay; - _whenAlerts[history].insert(when, notifyByFrom); + _whenAlerts[history].insert(when, notifyBy); if (Global::DesktopNotify() && !Platform::Notifications::SkipToast()) { auto &whenMap = _whenMaps[history]; if (whenMap.constFind(item->id) == whenMap.cend()) { @@ -117,7 +114,7 @@ void System::schedule(History *history, HistoryItem *item) { auto &addTo = haveSetting ? _waiters : _settingWaiters; auto it = addTo.constFind(history); if (it == addTo.cend() || it->when > when) { - addTo.insert(history, Waiter(item->id, when, notifyByFrom)); + addTo.insert(history, Waiter(item->id, when, notifyBy)); } } if (haveSetting) { @@ -171,12 +168,12 @@ void System::checkDelayed() { const auto peer = history->peer; auto loaded = false; auto muted = false; - if (!peer->notifySettingsUnknown()) { - if (!peer->isMuted()) { + if (!Auth().data().notifyMuteUnknown(peer)) { + if (!Auth().data().notifyIsMuted(peer)) { loaded = true; - } else if (const auto from = i.value().notifyByFrom) { - if (!from->notifySettingsUnknown()) { - if (!from->isMuted()) { + } else if (const auto from = i.value().notifyBy) { + if (!Auth().data().notifyMuteUnknown(from)) { + if (!Auth().data().notifyIsMuted(from)) { loaded = true; } else { loaded = muted = true; @@ -220,11 +217,14 @@ void System::showNext() { for (auto i = _whenAlerts.begin(); i != _whenAlerts.end();) { while (!i.value().isEmpty() && i.value().begin().key() <= ms) { const auto peer = i.key()->peer; - const auto peerUnknown = peer->notifySettingsUnknown(); - const auto peerAlert = peerUnknown ? false : !peer->isMuted(); + const auto peerUnknown = Auth().data().notifyMuteUnknown(peer); + const auto peerAlert = !peerUnknown + && !Auth().data().notifyIsMuted(peer); const auto from = i.value().begin().value(); - const auto fromUnknown = (!from || from->notifySettingsUnknown()); - const auto fromAlert = fromUnknown ? false : !from->isMuted(); + const auto fromUnknown = (!from + || Auth().data().notifyMuteUnknown(from)); + const auto fromAlert = !fromUnknown + && !Auth().data().notifyIsMuted(from); if (peerAlert || fromAlert) { alert = true; } diff --git a/Telegram/SourceFiles/window/notifications_manager.h b/Telegram/SourceFiles/window/notifications_manager.h index b40094582..83a8936be 100644 --- a/Telegram/SourceFiles/window/notifications_manager.h +++ b/Telegram/SourceFiles/window/notifications_manager.h @@ -83,14 +83,14 @@ private: QMap> _whenMaps; struct Waiter { - Waiter(MsgId msg, TimeMs when, PeerData *notifyByFrom) - : msg(msg) - , when(when) - , notifyByFrom(notifyByFrom) { + Waiter(MsgId msg, TimeMs when, PeerData *notifyBy) + : msg(msg) + , when(when) + , notifyBy(notifyBy) { } MsgId msg; TimeMs when; - PeerData *notifyByFrom; + PeerData *notifyBy; }; using Waiters = QMap; Waiters _waiters; diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 7dbf160e1..3d038503e 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -28,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/info_memento.h" #include "info/info_controller.h" #include "info/feed/info_feed_channels_controllers.h" +#include "info/profile/info_profile_values.h" #include "data/data_session.h" #include "data/data_feed.h" #include "dialogs/dialogs_key.h" @@ -634,32 +635,24 @@ void PeerMenuAddChannelMembers(not_null channel) { void PeerMenuAddMuteAction( not_null peer, const PeerMenuCallback &addAction) { - if (peer->notifySettingsUnknown()) { - Auth().api().requestNotifySetting(peer); - } - auto muteText = [](bool isMuted) { + Auth().data().requestNotifySettings(peer); + const auto muteText = [](bool isMuted) { return lang(isMuted ? lng_enable_notifications_from_tray : lng_disable_notifications_from_tray); }; - auto muteAction = addAction(muteText(peer->isMuted()), [=] { - if (!peer->isMuted()) { + const auto muteAction = addAction(QString("-"), [=] { + if (!Auth().data().notifyIsMuted(peer)) { Ui::show(Box(peer)); } else { - App::main()->updateNotifySettings( - peer, - Data::NotifySettings::MuteChange::Unmute); + Auth().data().updateNotifySettings(peer, 0); } }); - auto lifetime = Notify::PeerUpdateViewer( - peer, - Notify::PeerUpdate::Flag::NotificationsEnabled - ) | rpl::map([=] { - return peer->isMuted(); - }) | rpl::distinct_until_changed( - ) | rpl::start_with_next([=](bool muted) { - muteAction->setText(muteText(muted)); + auto lifetime = Info::Profile::NotificationsEnabledValue( + peer + ) | rpl::start_with_next([=](bool enabled) { + muteAction->setText(muteText(!enabled)); }); Ui::AttachAsChild(muteAction, std::move(lifetime));