From 36bb23c54c9fb5c8e8133e63839655d37b3e7047 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Fri, 1 Apr 2022 13:18:07 +0300 Subject: [PATCH] Moved out data of notify settings to separated module. --- Telegram/CMakeLists.txt | 2 + Telegram/SourceFiles/api/api_updates.cpp | 5 +- Telegram/SourceFiles/apiwrap.cpp | 10 +- .../SourceFiles/boxes/mute_settings_box.cpp | 3 +- Telegram/SourceFiles/data/data_session.cpp | 235 +--------------- Telegram/SourceFiles/data/data_session.h | 41 +-- .../data/notify/data_notify_settings.cpp | 253 ++++++++++++++++++ .../data/notify/data_notify_settings.h | 67 +++++ Telegram/SourceFiles/history/history.cpp | 3 +- .../SourceFiles/history/history_widget.cpp | 13 +- .../view/history_view_contact_status.cpp | 3 +- .../info/profile/info_profile_values.cpp | 3 +- Telegram/SourceFiles/menu/menu_mute.cpp | 10 +- Telegram/SourceFiles/ui/special_buttons.cpp | 3 +- .../window/notifications_manager.cpp | 6 +- .../SourceFiles/window/window_peer_menu.cpp | 9 +- 16 files changed, 380 insertions(+), 286 deletions(-) create mode 100644 Telegram/SourceFiles/data/notify/data_notify_settings.cpp create mode 100644 Telegram/SourceFiles/data/notify/data_notify_settings.h diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index a8fe64446f..67ac6f187c 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -395,6 +395,8 @@ PRIVATE core/version.h countries/countries_manager.cpp countries/countries_manager.h + data/notify/data_notify_settings.cpp + data/notify/data_notify_settings.h data/notify/data_peer_notify_settings.cpp data/notify/data_peer_notify_settings.h data/stickers/data_stickers_set.cpp diff --git a/Telegram/SourceFiles/api/api_updates.cpp b/Telegram/SourceFiles/api/api_updates.cpp index 49d755305b..963e6b302a 100644 --- a/Telegram/SourceFiles/api/api_updates.cpp +++ b/Telegram/SourceFiles/api/api_updates.cpp @@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mtproto/mtp_instance.h" #include "mtproto/mtproto_config.h" #include "mtproto/mtproto_dc_options.h" +#include "data/notify/data_notify_settings.h" #include "data/stickers/data_stickers.h" #include "data/data_session.h" #include "data/data_user.h" @@ -1906,7 +1907,9 @@ void Updates::feedUpdate(const MTPUpdate &update) { case mtpc_updateNotifySettings: { auto &d = update.c_updateNotifySettings(); - session().data().applyNotifySetting(d.vpeer(), d.vnotify_settings()); + session().data().notifySettings().applyNotifySetting( + d.vpeer(), + d.vnotify_settings()); } break; case mtpc_updateDcOptions: { diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 3615a8c728..9265e809d6 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_views.h" #include "api/api_confirm_phone.h" #include "api/api_unread_things.h" +#include "data/notify/data_notify_settings.h" #include "data/stickers/data_stickers.h" #include "data/data_drafts.h" #include "data/data_changes.h" @@ -2089,22 +2090,23 @@ void ApiWrap::clearModifyRequest(const QString &key) { void ApiWrap::applyNotifySettings( MTPInputNotifyPeer notifyPeer, const MTPPeerNotifySettings &settings) { + auto ¬ifySettings = _session->data().notifySettings(); switch (notifyPeer.type()) { case mtpc_inputNotifyUsers: - _session->data().applyNotifySetting(MTP_notifyUsers(), settings); + notifySettings.applyNotifySetting(MTP_notifyUsers(), settings); break; case mtpc_inputNotifyChats: - _session->data().applyNotifySetting(MTP_notifyChats(), settings); + notifySettings.applyNotifySetting(MTP_notifyChats(), settings); break; case mtpc_inputNotifyBroadcasts: - _session->data().applyNotifySetting( + notifySettings.applyNotifySetting( MTP_notifyBroadcasts(), settings); break; case mtpc_inputNotifyPeer: { auto &peer = notifyPeer.c_inputNotifyPeer().vpeer(); const auto apply = [&](PeerId peerId) { - _session->data().applyNotifySetting( + notifySettings.applyNotifySetting( MTP_notifyPeer(peerToMTP(peerId)), settings); }; diff --git a/Telegram/SourceFiles/boxes/mute_settings_box.cpp b/Telegram/SourceFiles/boxes/mute_settings_box.cpp index be5137f9a0..6ec93f7922 100644 --- a/Telegram/SourceFiles/boxes/mute_settings_box.cpp +++ b/Telegram/SourceFiles/boxes/mute_settings_box.cpp @@ -9,6 +9,7 @@ Copyright (C) 2017, Nicholas Guriev #include "lang/lang_keys.h" #include "main/main_session.h" +#include "data/notify/data_notify_settings.h" #include "data/data_session.h" #include "data/data_peer.h" #include "ui/special_buttons.h" @@ -75,7 +76,7 @@ void MuteSettingsBox::prepare() { _save = [=] { const auto muteForSeconds = group->value() * 3600; - _peer->owner().updateNotifySettings( + _peer->owner().notifySettings().updateNotifySettings( _peer, muteForSeconds); closeBox(); diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 9e58f8b330..ee65b6b3bd 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -36,6 +36,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "passport/passport_form_controller.h" #include "lang/lang_keys.h" // tr::lng_deleted(tr::now) in user name #include "data/stickers/data_stickers.h" +#include "data/notify/data_notify_settings.h" #include "data/data_changes.h" #include "data/data_group_call.h" #include "data/data_media_types.h" @@ -70,8 +71,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Data { namespace { -constexpr auto kMaxNotifyCheckDelay = 24 * 3600 * crl::time(1000); - using ViewElement = HistoryView::Element; // s: box 100x100 @@ -232,7 +231,6 @@ Session::Session(not_null session) , _ttlCheckTimer([=] { checkTTLs(); }) , _selfDestructTimer([=] { checkSelfDestructItems(); }) , _pollsClosingTimer([=] { checkPollsClosings(); }) -, _unmuteByFinishedTimer([=] { unmuteByFinished(); }) , _groups(this) , _chatsFilters(std::make_unique(this)) , _scheduledMessages(std::make_unique(this)) @@ -243,7 +241,8 @@ Session::Session(not_null session) , _histories(std::make_unique(this)) , _stickers(std::make_unique(this)) , _sponsoredMessages(std::make_unique(this)) -, _reactions(std::make_unique(this)) { +, _reactions(std::make_unique(this)) +, _notifySettings(std::make_unique(this)) { _cache->open(_session->local().cacheKey()); _bigFileCache->open(_session->local().cacheBigFileKey()); @@ -2222,81 +2221,6 @@ Session::SentData Session::messageSentData(uint64 randomId) const { return (i != end(_sentMessagesData)) ? i->second : SentData(); } -PeerNotifySettings &Session::defaultNotifySettings( - not_null peer) { - return peer->isUser() - ? _defaultUserNotifySettings - : (peer->isChat() || peer->isMegagroup()) - ? _defaultChatNotifySettings - : _defaultBroadcastNotifySettings; -} - -const PeerNotifySettings &Session::defaultNotifySettings( - not_null peer) const { - return peer->isUser() - ? _defaultUserNotifySettings - : (peer->isChat() || peer->isMegagroup()) - ? _defaultChatNotifySettings - : _defaultBroadcastNotifySettings; -} - -void Session::updateNotifySettingsLocal(not_null peer) { - const auto history = historyLoaded(peer->id); - auto changesIn = crl::time(0); - const auto muted = notifyIsMuted(peer, &changesIn); - if (history && history->changeMute(muted)) { - // Notification already sent. - } else { - session().changes().peerUpdated( - peer, - PeerUpdate::Flag::Notifications); - } - - if (muted) { - _mutedPeers.emplace(peer); - unmuteByFinishedDelayed(changesIn); - if (history) { - Core::App().notifications().clearIncomingFromHistory(history); - } - } else { - _mutedPeers.erase(peer); - } -} - -void Session::unmuteByFinishedDelayed(crl::time delay) { - accumulate_min(delay, kMaxNotifyCheckDelay); - if (!_unmuteByFinishedTimer.isActive() - || _unmuteByFinishedTimer.remainingTime() > delay) { - _unmuteByFinishedTimer.callOnce(delay); - } -} - -void Session::unmuteByFinished() { - auto changesInMin = crl::time(0); - for (auto i = begin(_mutedPeers); i != end(_mutedPeers);) { - const auto history = historyLoaded((*i)->id); - auto changesIn = crl::time(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); - } -} - HistoryItem *Session::addNewMessage( const MTPMessage &data, MessageFlags localFlags, @@ -3874,135 +3798,15 @@ auto Session::dialogsRowReplacements() const return _dialogsRowReplacements.events(); } -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() - : (peer->isChat() || peer->isMegagroup()) - ? MTP_inputNotifyChats() - : MTP_inputNotifyBroadcasts()); - } -} - -void Session::applyNotifySetting( - const MTPNotifyPeer ¬ifyPeer, - const MTPPeerNotifySettings &settings) { - const auto goodForUpdate = [&]( - not_null peer, - const PeerNotifySettings &settings) { - return !peer->notifySettingsUnknown() - && ((!peer->notifyMuteUntil() && settings.muteUntil()) - || (!peer->notifySilentPosts() && settings.silentPosts()) - || (!peer->notifySoundIsNone() && settings.soundIsNone())); - }; - - switch (notifyPeer.type()) { - case mtpc_notifyUsers: { - if (_defaultUserNotifySettings.change(settings)) { - _defaultUserNotifyUpdates.fire({}); - - enumerateUsers([&](not_null user) { - if (goodForUpdate(user, _defaultUserNotifySettings)) { - updateNotifySettingsLocal(user); - } - }); - } - } break; - case mtpc_notifyChats: { - if (_defaultChatNotifySettings.change(settings)) { - _defaultChatNotifyUpdates.fire({}); - - enumerateGroups([&](not_null peer) { - if (goodForUpdate(peer, _defaultChatNotifySettings)) { - updateNotifySettingsLocal(peer); - } - }); - } - } break; - case mtpc_notifyBroadcasts: { - if (_defaultBroadcastNotifySettings.change(settings)) { - _defaultBroadcastNotifyUpdates.fire({}); - - enumerateChannels([&](not_null channel) { - if (goodForUpdate(channel, _defaultBroadcastNotifySettings)) { - updateNotifySettingsLocal(channel); - } - }); - } - } break; - case mtpc_notifyPeer: { - const auto &data = notifyPeer.c_notifyPeer(); - if (const auto peer = peerLoaded(peerFromMTP(data.vpeer()))) { - if (peer->notifyChange(settings)) { - updateNotifySettingsLocal(peer); - } - } - } break; - } -} - -void Session::updateNotifySettings( - not_null peer, - std::optional muteForSeconds, - std::optional silentPosts, - std::optional soundIsNone) { - if (peer->notifyChange(muteForSeconds, silentPosts, soundIsNone)) { - updateNotifySettingsLocal(peer); - _session->api().updateNotifySettingsDelayed(peer); - } -} - -void Session::resetNotifySettingsToDefault(not_null peer) { - const auto empty = MTP_peerNotifySettings( - MTP_flags(0), - MTPBool(), - MTPBool(), - MTPint(), - MTPNotificationSound(), - MTPNotificationSound(), - MTPNotificationSound()); - if (peer->notifyChange(empty)) { - updateNotifySettingsLocal(peer); - _session->api().updateNotifySettingsDelayed(peer); - } -} - bool Session::notifyIsMuted(not_null peer) const { - return notifyIsMuted(peer, nullptr); -} - -bool Session::notifyIsMuted( - not_null peer, - crl::time *changesIn) const { - const auto resultFromUntil = [&](TimeId until) { - const auto now = base::unixtime::now(); - const auto result = (until > now) ? (until - now) : 0; - if (changesIn) { - *changesIn = (result > 0) - ? std::min(result * crl::time(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 true; + return notifySettings().notifyIsMuted(peer, nullptr); } bool Session::notifySilentPosts(not_null peer) const { if (const auto silent = peer->notifySilentPosts()) { return *silent; } - const auto &settings = defaultNotifySettings(peer); + const auto &settings = notifySettings().defaultNotifySettings(peer); if (const auto silent = settings.silentPosts()) { return *silent; } @@ -4013,7 +3817,7 @@ bool Session::notifySoundIsNone(not_null peer) const { if (const auto soundIsNone = peer->notifySoundIsNone()) { return *soundIsNone; } - const auto &settings = defaultNotifySettings(peer); + const auto &settings = notifySettings().defaultNotifySettings(peer); if (const auto soundIsNone = settings.soundIsNone()) { return *soundIsNone; } @@ -4026,7 +3830,7 @@ bool Session::notifyMuteUnknown(not_null peer) const { } else if (const auto nonDefault = peer->notifyMuteUntil()) { return false; } - return defaultNotifySettings(peer).settingsUnknown(); + return notifySettings().defaultNotifySettings(peer).settingsUnknown(); } bool Session::notifySilentPostsUnknown( @@ -4036,7 +3840,7 @@ bool Session::notifySilentPostsUnknown( } else if (const auto nonDefault = peer->notifySilentPosts()) { return false; } - return defaultNotifySettings(peer).settingsUnknown(); + return notifySettings().defaultNotifySettings(peer).settingsUnknown(); } bool Session::notifySoundIsNoneUnknown(not_null peer) const { @@ -4045,7 +3849,7 @@ bool Session::notifySoundIsNoneUnknown(not_null peer) const { } else if (const auto nonDefault = peer->notifySoundIsNone()) { return false; } - return defaultNotifySettings(peer).settingsUnknown(); + return notifySettings().defaultNotifySettings(peer).settingsUnknown(); } bool Session::notifySettingsUnknown(not_null peer) const { @@ -4054,27 +3858,6 @@ bool Session::notifySettingsUnknown(not_null peer) const { || notifySoundIsNoneUnknown(peer); } -rpl::producer<> Session::defaultUserNotifyUpdates() const { - return _defaultUserNotifyUpdates.events(); -} - -rpl::producer<> Session::defaultChatNotifyUpdates() const { - return _defaultChatNotifyUpdates.events(); -} - -rpl::producer<> Session::defaultBroadcastNotifyUpdates() const { - return _defaultBroadcastNotifyUpdates.events(); -} - -rpl::producer<> Session::defaultNotifyUpdates( - not_null peer) const { - return peer->isUser() - ? defaultUserNotifyUpdates() - : (peer->isChat() || peer->isMegagroup()) - ? defaultChatNotifyUpdates() - : defaultBroadcastNotifyUpdates(); -} - void Session::serviceNotification( const TextWithEntities &message, const MTPMessageMedia &media) { diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index bf71f425e1..058b282c4a 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -13,7 +13,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "dialogs/dialogs_main_list.h" #include "data/data_groups.h" #include "data/data_cloud_file.h" -#include "data/notify/data_peer_notify_settings.h" #include "history/history_location_manager.h" #include "base/timer.h" #include "base/flags.h" @@ -62,6 +61,7 @@ class DocumentMedia; class PhotoMedia; class Stickers; class GroupCall; +class NotifySettings; class Session final { public: @@ -117,6 +117,9 @@ public: [[nodiscard]] Reactions &reactions() const { return *_reactions; } + [[nodiscard]] NotifySettings ¬ifySettings() const { + return *_notifySettings; + } [[nodiscard]] MsgId nextNonHistoryEntryId() { return ++_nonHistoryEntryId; @@ -659,16 +662,6 @@ public: void dialogsRowReplaced(DialogsRowReplacement replacement); rpl::producer dialogsRowReplacements() const; - void requestNotifySettings(not_null peer); - void applyNotifySetting( - const MTPNotifyPeer ¬ifyPeer, - const MTPPeerNotifySettings &settings); - void updateNotifySettings( - not_null peer, - std::optional muteForSeconds, - std::optional silentPosts = std::nullopt, - std::optional soundIsNone = std::nullopt); - void resetNotifySettingsToDefault(not_null peer); bool notifyIsMuted(not_null peer) const; bool notifySilentPosts(not_null peer) const; bool notifySoundIsNone(not_null peer) const; @@ -676,11 +669,6 @@ public: bool notifySilentPostsUnknown(not_null peer) const; bool notifySoundIsNoneUnknown(not_null peer) const; bool notifySettingsUnknown(not_null peer) const; - rpl::producer<> defaultUserNotifyUpdates() const; - rpl::producer<> defaultChatNotifyUpdates() const; - rpl::producer<> defaultBroadcastNotifyUpdates() const; - rpl::producer<> defaultNotifyUpdates( - not_null peer) const; void serviceNotification( const TextWithEntities &message, @@ -712,10 +700,6 @@ public: private: using Messages = std::unordered_map>; - bool notifyIsMuted( - not_null peer, - crl::time *changesIn) const; - void suggestStartExport(); void setupMigrationViewer(); @@ -822,13 +806,6 @@ private: void setPinnedFromDialog(const Dialogs::Key &key, bool pinned); - PeerNotifySettings &defaultNotifySettings(not_null peer); - const PeerNotifySettings &defaultNotifySettings( - not_null peer) const; - void unmuteByFinished(); - void unmuteByFinishedDelayed(crl::time delay); - void updateNotifySettingsLocal(not_null peer); - template void enumerateItemViews( not_null item, @@ -976,15 +953,6 @@ private: History *_topPromoted = nullptr; - PeerNotifySettings _defaultUserNotifySettings; - PeerNotifySettings _defaultChatNotifySettings; - PeerNotifySettings _defaultBroadcastNotifySettings; - rpl::event_stream<> _defaultUserNotifyUpdates; - rpl::event_stream<> _defaultChatNotifyUpdates; - rpl::event_stream<> _defaultBroadcastNotifyUpdates; - std::unordered_set> _mutedPeers; - base::Timer _unmuteByFinishedTimer; - std::unordered_map> _peers; MessageIdsList _mimeForwardIds; @@ -1010,6 +978,7 @@ private: const std::unique_ptr _stickers; std::unique_ptr _sponsoredMessages; const std::unique_ptr _reactions; + const std::unique_ptr _notifySettings; MsgId _nonHistoryEntryId = ServerMaxMsgId.bare + ScheduledMsgIdsRange; diff --git a/Telegram/SourceFiles/data/notify/data_notify_settings.cpp b/Telegram/SourceFiles/data/notify/data_notify_settings.cpp new file mode 100644 index 0000000000..af1f61a2a0 --- /dev/null +++ b/Telegram/SourceFiles/data/notify/data_notify_settings.cpp @@ -0,0 +1,253 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "data/notify/data_notify_settings.h" + +#include "apiwrap.h" +#include "base/unixtime.h" +#include "core/application.h" +#include "data/data_changes.h" +#include "data/data_channel.h" +#include "data/data_chat.h" +#include "data/data_peer.h" +#include "data/data_session.h" +#include "data/data_user.h" +#include "history/history.h" +#include "main/main_session.h" +#include "window/notifications_manager.h" + +namespace Data { + +namespace { + +constexpr auto kMaxNotifyCheckDelay = 24 * 3600 * crl::time(1000); + +} // namespace + +NotifySettings::NotifySettings(not_null owner) +: _owner(owner) +, _unmuteByFinishedTimer([=] { unmuteByFinished(); }) { +} + +void NotifySettings::requestNotifySettings(not_null peer) { + if (peer->notifySettingsUnknown()) { + peer->session().api().requestNotifySettings( + MTP_inputNotifyPeer(peer->input)); + } + if (defaultNotifySettings(peer).settingsUnknown()) { + peer->session().api().requestNotifySettings(peer->isUser() + ? MTP_inputNotifyUsers() + : (peer->isChat() || peer->isMegagroup()) + ? MTP_inputNotifyChats() + : MTP_inputNotifyBroadcasts()); + } +} + +void NotifySettings::applyNotifySetting( + const MTPNotifyPeer ¬ifyPeer, + const MTPPeerNotifySettings &settings) { + const auto goodForUpdate = [&]( + not_null peer, + const PeerNotifySettings &settings) { + return !peer->notifySettingsUnknown() + && ((!peer->notifyMuteUntil() && settings.muteUntil()) + || (!peer->notifySilentPosts() && settings.silentPosts()) + || (!peer->notifySoundIsNone() && settings.soundIsNone())); + }; + + switch (notifyPeer.type()) { + case mtpc_notifyUsers: { + if (_defaultUserNotifySettings.change(settings)) { + _defaultUserNotifyUpdates.fire({}); + + _owner->enumerateUsers([&](not_null user) { + if (goodForUpdate(user, _defaultUserNotifySettings)) { + updateNotifySettingsLocal(user); + } + }); + } + } break; + case mtpc_notifyChats: { + if (_defaultChatNotifySettings.change(settings)) { + _defaultChatNotifyUpdates.fire({}); + + _owner->enumerateGroups([&](not_null peer) { + if (goodForUpdate(peer, _defaultChatNotifySettings)) { + updateNotifySettingsLocal(peer); + } + }); + } + } break; + case mtpc_notifyBroadcasts: { + if (_defaultBroadcastNotifySettings.change(settings)) { + _defaultBroadcastNotifyUpdates.fire({}); + + _owner->enumerateChannels([&](not_null channel) { + if (goodForUpdate(channel, _defaultBroadcastNotifySettings)) { + updateNotifySettingsLocal(channel); + } + }); + } + } break; + case mtpc_notifyPeer: { + const auto &data = notifyPeer.c_notifyPeer(); + if (const auto peer = _owner->peerLoaded(peerFromMTP(data.vpeer()))) { + if (peer->notifyChange(settings)) { + updateNotifySettingsLocal(peer); + } + } + } break; + } +} + +void NotifySettings::updateNotifySettings( + not_null peer, + std::optional muteForSeconds, + std::optional silentPosts, + std::optional soundIsNone) { + if (peer->notifyChange(muteForSeconds, silentPosts, soundIsNone)) { + updateNotifySettingsLocal(peer); + peer->session().api().updateNotifySettingsDelayed(peer); + } +} + +void NotifySettings::resetNotifySettingsToDefault(not_null peer) { + const auto empty = MTP_peerNotifySettings( + MTP_flags(0), + MTPBool(), + MTPBool(), + MTPint(), + MTPNotificationSound(), + MTPNotificationSound(), + MTPNotificationSound()); + if (peer->notifyChange(empty)) { + updateNotifySettingsLocal(peer); + peer->session().api().updateNotifySettingsDelayed(peer); + } +} + + +PeerNotifySettings &NotifySettings::defaultNotifySettings( + not_null peer) { + return peer->isUser() + ? _defaultUserNotifySettings + : (peer->isChat() || peer->isMegagroup()) + ? _defaultChatNotifySettings + : _defaultBroadcastNotifySettings; +} + +const PeerNotifySettings &NotifySettings::defaultNotifySettings( + not_null peer) const { + return peer->isUser() + ? _defaultUserNotifySettings + : (peer->isChat() || peer->isMegagroup()) + ? _defaultChatNotifySettings + : _defaultBroadcastNotifySettings; +} + +void NotifySettings::updateNotifySettingsLocal(not_null peer) { + const auto history = _owner->historyLoaded(peer->id); + auto changesIn = crl::time(0); + const auto muted = notifyIsMuted(peer, &changesIn); + if (history && history->changeMute(muted)) { + // Notification already sent. + } else { + peer->session().changes().peerUpdated( + peer, + PeerUpdate::Flag::Notifications); + } + + if (muted) { + _mutedPeers.emplace(peer); + unmuteByFinishedDelayed(changesIn); + if (history) { + Core::App().notifications().clearIncomingFromHistory(history); + } + } else { + _mutedPeers.erase(peer); + } +} + +void NotifySettings::unmuteByFinishedDelayed(crl::time delay) { + accumulate_min(delay, kMaxNotifyCheckDelay); + if (!_unmuteByFinishedTimer.isActive() + || _unmuteByFinishedTimer.remainingTime() > delay) { + _unmuteByFinishedTimer.callOnce(delay); + } +} + +void NotifySettings::unmuteByFinished() { + auto changesInMin = crl::time(0); + for (auto i = begin(_mutedPeers); i != end(_mutedPeers);) { + const auto history = _owner->historyLoaded((*i)->id); + auto changesIn = crl::time(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); + } +} + +bool NotifySettings::notifyIsMuted( + not_null peer, + crl::time *changesIn) const { + const auto resultFromUntil = [&](TimeId until) { + const auto now = base::unixtime::now(); + const auto result = (until > now) ? (until - now) : 0; + if (changesIn) { + *changesIn = (result > 0) + ? std::min(result * crl::time(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 true; +} + +rpl::producer<> NotifySettings::defaultUserNotifyUpdates() const { + return _defaultUserNotifyUpdates.events(); +} + +rpl::producer<> NotifySettings::defaultChatNotifyUpdates() const { + return _defaultChatNotifyUpdates.events(); +} + +rpl::producer<> NotifySettings::defaultBroadcastNotifyUpdates() const { + return _defaultBroadcastNotifyUpdates.events(); +} + +rpl::producer<> NotifySettings::defaultNotifyUpdates( + not_null peer) const { + return peer->isUser() + ? defaultUserNotifyUpdates() + : (peer->isChat() || peer->isMegagroup()) + ? defaultChatNotifyUpdates() + : defaultBroadcastNotifyUpdates(); +} + +} // namespace Data diff --git a/Telegram/SourceFiles/data/notify/data_notify_settings.h b/Telegram/SourceFiles/data/notify/data_notify_settings.h new file mode 100644 index 0000000000..88f70f53ae --- /dev/null +++ b/Telegram/SourceFiles/data/notify/data_notify_settings.h @@ -0,0 +1,67 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +#include "data/notify/data_peer_notify_settings.h" + +#include "base/timer.h" + +class PeerData; + +namespace Data { + +class Session; + +class NotifySettings final { +public: + NotifySettings(not_null owner); + + void requestNotifySettings(not_null peer); + void applyNotifySetting( + const MTPNotifyPeer ¬ifyPeer, + const MTPPeerNotifySettings &settings); + void updateNotifySettings( + not_null peer, + std::optional muteForSeconds, + std::optional silentPosts = std::nullopt, + std::optional soundIsNone = std::nullopt); + void resetNotifySettingsToDefault(not_null peer); + + [[nodiscard]] rpl::producer<> defaultUserNotifyUpdates() const; + [[nodiscard]] rpl::producer<> defaultChatNotifyUpdates() const; + [[nodiscard]] rpl::producer<> defaultBroadcastNotifyUpdates() const; + [[nodiscard]] rpl::producer<> defaultNotifyUpdates( + not_null peer) const; + + [[nodiscard]] bool notifyIsMuted( + not_null peer, + crl::time *changesIn) const; + + [[nodiscard]] PeerNotifySettings &defaultNotifySettings( + not_null peer); + [[nodiscard]] const PeerNotifySettings &defaultNotifySettings( + not_null peer) const; +private: + void unmuteByFinished(); + void unmuteByFinishedDelayed(crl::time delay); + void updateNotifySettingsLocal(not_null peer); + + const not_null _owner; + + PeerNotifySettings _defaultUserNotifySettings; + PeerNotifySettings _defaultChatNotifySettings; + PeerNotifySettings _defaultBroadcastNotifySettings; + rpl::event_stream<> _defaultUserNotifyUpdates; + rpl::event_stream<> _defaultChatNotifyUpdates; + rpl::event_stream<> _defaultBroadcastNotifyUpdates; + std::unordered_set> _mutedPeers; + base::Timer _unmuteByFinishedTimer; + +}; + +} // namespace Data diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index 70dbef59d8..f0b0466225 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_inner_widget.h" #include "history/history_unread_things.h" #include "dialogs/dialogs_indexed_list.h" +#include "data/notify/data_notify_settings.h" #include "data/stickers/data_stickers.h" #include "data/data_drafts.h" #include "data/data_session.h" @@ -2553,7 +2554,7 @@ void History::applyDialog( } } } - owner().applyNotifySetting( + owner().notifySettings().applyNotifySetting( MTP_notifyPeer(data.vpeer()), data.vnotify_settings()); diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 2dd0142ce0..d033af39e6 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -52,6 +52,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/qt/qt_key_modifiers.h" #include "base/unixtime.h" #include "base/call_delayed.h" +#include "data/notify/data_notify_settings.h" #include "data/data_changes.h" #include "data/data_drafts.h" #include "data/data_session.h" @@ -789,9 +790,9 @@ HistoryWidget::HistoryWidget( }, lifetime()); rpl::merge( - session().data().defaultUserNotifyUpdates(), - session().data().defaultChatNotifyUpdates(), - session().data().defaultBroadcastNotifyUpdates() + session().data().notifySettings().defaultUserNotifyUpdates(), + session().data().notifySettings().defaultChatNotifyUpdates(), + session().data().notifySettings().defaultBroadcastNotifyUpdates() ) | rpl::start_with_next([=] { updateNotifyControls(); }, lifetime()); @@ -2237,7 +2238,7 @@ void HistoryWidget::showHistory( if (_peer->isChannel()) { updateNotifyControls(); - session().data().requestNotifySettings(_peer); + session().data().notifySettings().requestNotifySettings(_peer); refreshSilentToggle(); } else if (_peer->isRepliesChat()) { updateNotifyControls(); @@ -3850,7 +3851,9 @@ void HistoryWidget::toggleMuteUnmute() { const auto muteForSeconds = _history->mute() ? 0 : Data::PeerNotifySettings::kDefaultMutePeriod; - session().data().updateNotifySettings(_peer, muteForSeconds); + session().data().notifySettings().updateNotifySettings( + _peer, + muteForSeconds); } void HistoryWidget::reportSelectedMessages() { diff --git a/Telegram/SourceFiles/history/view/history_view_contact_status.cpp b/Telegram/SourceFiles/history/view/history_view_contact_status.cpp index 8f44c2b25a..be71445663 100644 --- a/Telegram/SourceFiles/history/view/history_view_contact_status.cpp +++ b/Telegram/SourceFiles/history/view/history_view_contact_status.cpp @@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/text/text_utilities.h" #include "ui/boxes/confirm_box.h" #include "ui/layers/generic_box.h" +#include "data/notify/data_notify_settings.h" #include "data/data_peer.h" #include "data/data_user.h" #include "data/data_chat.h" @@ -473,7 +474,7 @@ void ContactStatus::setupUnarchiveHandler(not_null peer) { _bar.entity()->unarchiveClicks( ) | rpl::start_with_next([=] { Window::ToggleHistoryArchived(peer->owner().history(peer), false); - peer->owner().resetNotifySettingsToDefault(peer); + peer->owner().notifySettings().resetNotifySettingsToDefault(peer); if (const auto settings = peer->settings()) { const auto flags = PeerSetting::AutoArchived | PeerSetting::BlockContact diff --git a/Telegram/SourceFiles/info/profile/info_profile_values.cpp b/Telegram/SourceFiles/info/profile/info_profile_values.cpp index 1a431f6bce..b0b9bcc56a 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_values.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_values.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/text/format_values.h" // Ui::FormatPhone #include "ui/text/text_utilities.h" #include "lang/lang_keys.h" +#include "data/notify/data_notify_settings.h" #include "data/data_peer_values.h" #include "data/data_shared_media.h" #include "data/data_message_reactions.h" @@ -171,7 +172,7 @@ rpl::producer NotificationsEnabledValue(not_null peer) { peer, UpdateFlag::Notifications ) | rpl::to_empty, - peer->owner().defaultNotifyUpdates(peer) + peer->owner().notifySettings().defaultNotifyUpdates(peer) ) | rpl::map([=] { return !peer->owner().notifyIsMuted(peer); }) | rpl::distinct_until_changed(); diff --git a/Telegram/SourceFiles/menu/menu_mute.cpp b/Telegram/SourceFiles/menu/menu_mute.cpp index 617a5eefd5..c0c416eb05 100644 --- a/Telegram/SourceFiles/menu/menu_mute.cpp +++ b/Telegram/SourceFiles/menu/menu_mute.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "menu/menu_mute.h" +#include "data/notify/data_notify_settings.h" #include "data/data_peer.h" #include "data/data_session.h" #include "info/profile/info_profile_values.h" @@ -77,7 +78,7 @@ MuteItem::MuteItem( }, lifetime()); setClickedCallback([=] { - peer->owner().updateNotifySettings( + peer->owner().notifySettings().updateNotifySettings( peer, _isMuted ? 0 : Data::PeerNotifySettings::kDefaultMutePeriod); }); @@ -119,7 +120,9 @@ void MuteBox(not_null box, not_null peer) { : tr::lng_mute_menu_mute(); }) | rpl::flatten_latest(); const auto confirm = box->addButton(std::move(confirmText), [=] { - peer->owner().updateNotifySettings(peer, state->lastSeconds); + peer->owner().notifySettings().updateNotifySettings( + peer, + state->lastSeconds); box->closeBox(); }); box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); @@ -139,7 +142,8 @@ void FillMuteMenu( : tr::lng_mute_menu_sound_off(tr::now), [=] { const auto soundIsNone = peer->owner().notifySoundIsNone(peer); - peer->owner().updateNotifySettings(peer, {}, {}, !soundIsNone); + auto ¬ifySettings = peer->owner().notifySettings(); + notifySettings.updateNotifySettings(peer, {}, {}, !soundIsNone); }, soundIsNone ? &st::menuIconSoundOn : &st::menuIconSoundOff); diff --git a/Telegram/SourceFiles/ui/special_buttons.cpp b/Telegram/SourceFiles/ui/special_buttons.cpp index fa78838f20..542427561d 100644 --- a/Telegram/SourceFiles/ui/special_buttons.cpp +++ b/Telegram/SourceFiles/ui/special_buttons.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/image/image_prepare.h" #include "ui/empty_userpic.h" #include "ui/ui_utility.h" +#include "data/notify/data_notify_settings.h" #include "data/data_photo.h" #include "data/data_session.h" #include "data/data_folder.h" @@ -864,7 +865,7 @@ void SilentToggle::mouseReleaseEvent(QMouseEvent *e) { setChecked(!_checked); RippleButton::mouseReleaseEvent(e); Ui::Tooltip::Show(0, this); - _channel->owner().updateNotifySettings( + _channel->owner().notifySettings().updateNotifySettings( _channel, std::nullopt, _checked); diff --git a/Telegram/SourceFiles/window/notifications_manager.cpp b/Telegram/SourceFiles/window/notifications_manager.cpp index 9f64e0ca7a..d71b6c6e76 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.h" #include "history/history_item_components.h" #include "lang/lang_keys.h" +#include "data/notify/data_notify_settings.h" #include "data/data_session.h" #include "data/data_channel.h" #include "data/data_user.h" @@ -196,12 +197,13 @@ System::SkipState System::computeSkipState( } if (messageNotification) { - history->owner().requestNotifySettings(history->peer); + history->owner().notifySettings().requestNotifySettings( + history->peer); } else if (notifyBy->blockStatus() == PeerData::BlockStatus::Unknown) { notifyBy->updateFull(); } if (notifyBy) { - history->owner().requestNotifySettings(notifyBy); + history->owner().notifySettings().requestNotifySettings(notifyBy); } if (messageNotification diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 8f5c34cbab..e8802f581d 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -52,6 +52,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/info_memento.h" #include "info/info_controller.h" #include "info/profile/info_profile_values.h" +#include "data/notify/data_notify_settings.h" #include "data/data_changes.h" #include "data/data_session.h" #include "data/data_folder.h" @@ -130,7 +131,7 @@ void PeerMenuAddMuteSubmenuAction( not_null controller, not_null peer, const PeerMenuCallback &addAction) { - peer->owner().requestNotifySettings(peer); + peer->owner().notifySettings().requestNotifySettings(peer); const auto isMuted = peer->owner().notifyIsMuted(peer); if (isMuted) { const auto text = tr::lng_context_unmute(tr::now) @@ -138,7 +139,7 @@ void PeerMenuAddMuteSubmenuAction( + Ui::FormatMuteForTiny(peer->notifyMuteUntil().value_or(0) - base::unixtime::now()); addAction(text, [=] { - peer->owner().updateNotifySettings(peer, 0); + peer->owner().notifySettings().updateNotifySettings(peer, 0); }, &st::menuIconUnmute); } else { const auto show = std::make_shared(controller); @@ -1422,7 +1423,7 @@ void PeerMenuAddMuteAction( not_null peer, const PeerMenuCallback &addAction) { // There is no async to make weak from controller. - peer->owner().requestNotifySettings(peer); + peer->owner().notifySettings().requestNotifySettings(peer); const auto muteText = [](bool isUnmuted) { return isUnmuted ? tr::lng_context_mute(tr::now) @@ -1434,7 +1435,7 @@ void PeerMenuAddMuteAction( Box(peer), Ui::LayerOption::CloseOther); } else { - peer->owner().updateNotifySettings(peer, 0); + peer->owner().notifySettings().updateNotifySettings(peer, 0); } }, (peer->owner().notifyIsMuted(peer) ? &st::menuIconUnmute