Allow editing general notification sound.

This commit is contained in:
John Preston 2022-04-06 19:23:41 +04:00
parent c71ba2b8e7
commit 0615f21deb
11 changed files with 210 additions and 102 deletions

View file

@ -354,6 +354,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_notifications_position" = "Location on the screen"; "lng_settings_notifications_position" = "Location on the screen";
"lng_settings_notifications_count" = "Notifications count"; "lng_settings_notifications_count" = "Notifications count";
"lng_settings_sound_notify" = "Play sound"; "lng_settings_sound_notify" = "Play sound";
"lng_settings_sound_notify_off" = "Off";
"lng_settings_alert_windows" = "Flash the taskbar icon"; "lng_settings_alert_windows" = "Flash the taskbar icon";
"lng_settings_alert_mac" = "Bounce the dock icon"; "lng_settings_alert_mac" = "Bounce the dock icon";
"lng_settings_alert_linux" = "Draw attention to the window"; "lng_settings_alert_linux" = "Draw attention to the window";

View file

@ -1763,6 +1763,11 @@ void ApiWrap::updateNotifySettingsDelayed(not_null<const PeerData*> peer) {
_updateNotifySettingsTimer.callOnce(kNotifySettingSaveTimeout); _updateNotifySettingsTimer.callOnce(kNotifySettingSaveTimeout);
} }
void ApiWrap::updateDefaultNotifySettingsDelayed(Data::DefaultNotify type) {
_updateNotifySettingsDefaults.emplace(type);
_updateNotifySettingsTimer.callOnce(kNotifySettingSaveTimeout);
}
void ApiWrap::sendNotifySettingsUpdates() { void ApiWrap::sendNotifySettingsUpdates() {
while (!_updateNotifySettingsPeers.empty()) { while (!_updateNotifySettingsPeers.empty()) {
const auto peer = *_updateNotifySettingsPeers.begin(); const auto peer = *_updateNotifySettingsPeers.begin();
@ -1772,6 +1777,25 @@ void ApiWrap::sendNotifySettingsUpdates() {
peer->notifySerialize() peer->notifySerialize()
)).afterDelay(_updateNotifySettingsPeers.empty() ? 0 : 10).send(); )).afterDelay(_updateNotifySettingsPeers.empty() ? 0 : 10).send();
} }
const auto &settings = session().data().notifySettings();
while (!_updateNotifySettingsDefaults.empty()) {
const auto type = *_updateNotifySettingsDefaults.begin();
_updateNotifySettingsDefaults.erase(
_updateNotifySettingsDefaults.begin());
const auto input = [&] {
switch (type) {
case Data::DefaultNotify::User: return MTP_inputNotifyUsers();
case Data::DefaultNotify::Group: return MTP_inputNotifyChats();
case Data::DefaultNotify::Broadcast:
return MTP_inputNotifyBroadcasts();
}
Unexpected("Default notify type in sendNotifySettingsUpdates");
}();
request(MTPaccount_UpdateNotifySettings(
input,
settings.defaultSettings(type).serialize()
)).afterDelay(_updateNotifySettingsDefaults.empty() ? 0 : 10).send();
}
} }
void ApiWrap::saveDraftToCloudDelayed(not_null<History*> history) { void ApiWrap::saveDraftToCloudDelayed(not_null<History*> history) {

View file

@ -30,6 +30,7 @@ namespace Data {
struct UpdatedFileReferences; struct UpdatedFileReferences;
class WallPaper; class WallPaper;
struct ResolvedForwardDraft; struct ResolvedForwardDraft;
enum class DefaultNotify;
} // namespace Data } // namespace Data
namespace InlineBots { namespace InlineBots {
@ -239,6 +240,7 @@ public:
void requestNotifySettings(const MTPInputNotifyPeer &peer); void requestNotifySettings(const MTPInputNotifyPeer &peer);
void updateNotifySettingsDelayed(not_null<const PeerData*> peer); void updateNotifySettingsDelayed(not_null<const PeerData*> peer);
void updateDefaultNotifySettingsDelayed(Data::DefaultNotify type);
void saveDraftToCloudDelayed(not_null<History*> history); void saveDraftToCloudDelayed(not_null<History*> history);
static int OnlineTillFromStatus( static int OnlineTillFromStatus(
@ -595,6 +597,7 @@ private:
base::Timer _topPromotionTimer; base::Timer _topPromotionTimer;
base::flat_set<not_null<const PeerData*>> _updateNotifySettingsPeers; base::flat_set<not_null<const PeerData*>> _updateNotifySettingsPeers;
base::flat_set<Data::DefaultNotify> _updateNotifySettingsDefaults;
base::Timer _updateNotifySettingsTimer; base::Timer _updateNotifySettingsTimer;
std::map< std::map<

View file

@ -951,7 +951,7 @@ void Session::enumerateGroups(Fn<void(not_null<PeerData*>)> action) const {
} }
} }
void Session::enumerateChannels( void Session::enumerateBroadcasts(
Fn<void(not_null<ChannelData*>)> action) const { Fn<void(not_null<ChannelData*>)> action) const {
for (const auto &[peerId, peer] : _peers) { for (const auto &[peerId, peer] : _peers) {
if (const auto channel = peer->asChannel()) { if (const auto channel = peer->asChannel()) {

View file

@ -192,7 +192,7 @@ public:
void enumerateUsers(Fn<void(not_null<UserData*>)> action) const; void enumerateUsers(Fn<void(not_null<UserData*>)> action) const;
void enumerateGroups(Fn<void(not_null<PeerData*>)> action) const; void enumerateGroups(Fn<void(not_null<PeerData*>)> action) const;
void enumerateChannels(Fn<void(not_null<ChannelData*>)> action) const; void enumerateBroadcasts(Fn<void(not_null<ChannelData*>)> action) const;
[[nodiscard]] UserData *userByPhone(const QString &phone) const; [[nodiscard]] UserData *userByPhone(const QString &phone) const;
[[nodiscard]] PeerData *peerByUsername(const QString &username) const; [[nodiscard]] PeerData *peerByUsername(const QString &username) const;

View file

@ -33,8 +33,8 @@ constexpr auto kMaxNotifyCheckDelay = 24 * 3600 * crl::time(1000);
} // namespace } // namespace
NotifySettings::NotifySettings(not_null<Session*> owner) NotifySettings::NotifySettings(not_null<Session*> owner)
: _owner(owner) : _owner(owner)
, _unmuteByFinishedTimer([=] { unmuteByFinished(); }) { , _unmuteByFinishedTimer([=] { unmuteByFinished(); }) {
} }
void NotifySettings::request(not_null<PeerData*> peer) { void NotifySettings::request(not_null<PeerData*> peer) {
@ -42,7 +42,7 @@ void NotifySettings::request(not_null<PeerData*> peer) {
peer->session().api().requestNotifySettings( peer->session().api().requestNotifySettings(
MTP_inputNotifyPeer(peer->input)); MTP_inputNotifyPeer(peer->input));
} }
if (defaultNotifySettings(peer).settingsUnknown()) { if (defaultSettings(peer).settingsUnknown()) {
peer->session().api().requestNotifySettings(peer->isUser() peer->session().api().requestNotifySettings(peer->isUser()
? MTP_inputNotifyUsers() ? MTP_inputNotifyUsers()
: (peer->isChat() || peer->isMegagroup()) : (peer->isChat() || peer->isMegagroup())
@ -54,49 +54,15 @@ void NotifySettings::request(not_null<PeerData*> peer) {
void NotifySettings::apply( void NotifySettings::apply(
const MTPNotifyPeer &notifyPeer, const MTPNotifyPeer &notifyPeer,
const MTPPeerNotifySettings &settings) { const MTPPeerNotifySettings &settings) {
const auto goodForUpdate = [&]( const auto set = [&](DefaultNotify type) {
not_null<const PeerData*> peer, if (defaultValue(type).settings.change(settings)) {
const PeerNotifySettings &settings) { updateLocal(type);
return !peer->notifySettingsUnknown() }
&& ((!peer->notifyMuteUntil() && settings.muteUntil())
|| (!peer->notifySilentPosts() && settings.silentPosts())
|| (!peer->notifySound() && settings.sound()));
}; };
switch (notifyPeer.type()) { switch (notifyPeer.type()) {
case mtpc_notifyUsers: { case mtpc_notifyUsers: set(DefaultNotify::User); break;
if (_defaultUser.change(settings)) { case mtpc_notifyChats: set(DefaultNotify::Group); break;
_defaultUserUpdates.fire({}); case mtpc_notifyBroadcasts: set(DefaultNotify::Broadcast); break;
_owner->enumerateUsers([&](not_null<UserData*> user) {
if (goodForUpdate(user, _defaultUser)) {
updateLocal(user);
}
});
}
} break;
case mtpc_notifyChats: {
if (_defaultChat.change(settings)) {
_defaultChatUpdates.fire({});
_owner->enumerateGroups([&](not_null<PeerData*> peer) {
if (goodForUpdate(peer, _defaultChat)) {
updateLocal(peer);
}
});
}
} break;
case mtpc_notifyBroadcasts: {
if (_defaultBroadcast.change(settings)) {
_defaultBroadcastUpdates.fire({});
_owner->enumerateChannels([&](not_null<ChannelData*> channel) {
if (goodForUpdate(channel, _defaultBroadcast)) {
updateLocal(channel);
}
});
}
} break;
case mtpc_notifyPeer: { case mtpc_notifyPeer: {
const auto &data = notifyPeer.c_notifyPeer(); const auto &data = notifyPeer.c_notifyPeer();
if (const auto peer = _owner->peerLoaded(peerFromMTP(data.vpeer()))) { if (const auto peer = _owner->peerLoaded(peerFromMTP(data.vpeer()))) {
@ -134,13 +100,44 @@ void NotifySettings::resetToDefault(not_null<PeerData*> peer) {
} }
} }
const PeerNotifySettings &NotifySettings::defaultNotifySettings( auto NotifySettings::defaultValue(DefaultNotify type)
-> DefaultValue & {
const auto index = static_cast<int>(type);
Assert(index >= 0 && index < base::array_size(_defaultValues));
return _defaultValues[index];
}
auto NotifySettings::defaultValue(DefaultNotify type) const
-> const DefaultValue & {
const auto index = static_cast<int>(type);
Assert(index >= 0 && index < base::array_size(_defaultValues));
return _defaultValues[index];
}
const PeerNotifySettings &NotifySettings::defaultSettings(
not_null<const PeerData*> peer) const { not_null<const PeerData*> peer) const {
return peer->isUser() return defaultSettings(peer->isUser()
? _defaultUser ? DefaultNotify::User
: (peer->isChat() || peer->isMegagroup()) : (peer->isChat() || peer->isMegagroup())
? _defaultChat ? DefaultNotify::Group
: _defaultBroadcast; : DefaultNotify::Broadcast);
}
const PeerNotifySettings &NotifySettings::defaultSettings(
DefaultNotify type) const {
return defaultValue(type).settings;
}
void NotifySettings::defaultUpdate(
DefaultNotify type,
std::optional<int> muteForSeconds,
std::optional<bool> silentPosts,
std::optional<NotifySound> sound) {
auto &settings = defaultValue(type).settings;
if (settings.change(muteForSeconds, silentPosts, sound)) {
updateLocal(type);
_owner->session().api().updateDefaultNotifySettingsDelayed(type);
}
} }
void NotifySettings::updateLocal(not_null<PeerData*> peer) { void NotifySettings::updateLocal(not_null<PeerData*> peer) {
@ -193,6 +190,32 @@ void NotifySettings::updateLocal(not_null<PeerData*> peer) {
} }
} }
void NotifySettings::updateLocal(DefaultNotify type) {
defaultValue(type).updates.fire({});
const auto goodForUpdate = [&](
not_null<const PeerData*> peer,
const PeerNotifySettings &settings) {
return !peer->notifySettingsUnknown()
&& ((!peer->notifyMuteUntil() && settings.muteUntil())
|| (!peer->notifySilentPosts() && settings.silentPosts())
|| (!peer->notifySound() && settings.sound()));
};
const auto callback = [&](not_null<PeerData*> peer) {
if (goodForUpdate(peer, defaultSettings(type))) {
updateLocal(peer);
}
};
switch (type) {
case DefaultNotify::User: _owner->enumerateUsers(callback); break;
case DefaultNotify::Group: _owner->enumerateGroups(callback); break;
case DefaultNotify::Broadcast:
_owner->enumerateBroadcasts(callback);
break;
}
}
std::shared_ptr<DocumentMedia> NotifySettings::lookupRingtone( std::shared_ptr<DocumentMedia> NotifySettings::lookupRingtone(
DocumentId id) const { DocumentId id) const {
if (!id) { if (!id) {
@ -252,7 +275,7 @@ bool NotifySettings::isMuted(
if (const auto until = peer->notifyMuteUntil()) { if (const auto until = peer->notifyMuteUntil()) {
return resultFromUntil(*until); return resultFromUntil(*until);
} }
const auto &settings = defaultNotifySettings(peer); const auto &settings = defaultSettings(peer);
if (const auto until = settings.muteUntil()) { if (const auto until = settings.muteUntil()) {
return resultFromUntil(*until); return resultFromUntil(*until);
} }
@ -267,7 +290,7 @@ bool NotifySettings::silentPosts(not_null<const PeerData*> peer) const {
if (const auto silent = peer->notifySilentPosts()) { if (const auto silent = peer->notifySilentPosts()) {
return *silent; return *silent;
} }
const auto &settings = defaultNotifySettings(peer); const auto &settings = defaultSettings(peer);
if (const auto silent = settings.silentPosts()) { if (const auto silent = settings.silentPosts()) {
return *silent; return *silent;
} }
@ -278,7 +301,7 @@ NotifySound NotifySettings::sound(not_null<const PeerData*> peer) const {
if (const auto sound = peer->notifySound()) { if (const auto sound = peer->notifySound()) {
return *sound; return *sound;
} }
const auto &settings = defaultNotifySettings(peer); const auto &settings = defaultSettings(peer);
if (const auto sound = settings.sound()) { if (const auto sound = settings.sound()) {
return *sound; return *sound;
} }
@ -291,7 +314,7 @@ bool NotifySettings::muteUnknown(not_null<const PeerData*> peer) const {
} else if (const auto nonDefault = peer->notifyMuteUntil()) { } else if (const auto nonDefault = peer->notifyMuteUntil()) {
return false; return false;
} }
return defaultNotifySettings(peer).settingsUnknown(); return defaultSettings(peer).settingsUnknown();
} }
bool NotifySettings::silentPostsUnknown( bool NotifySettings::silentPostsUnknown(
@ -301,7 +324,7 @@ bool NotifySettings::silentPostsUnknown(
} else if (const auto nonDefault = peer->notifySilentPosts()) { } else if (const auto nonDefault = peer->notifySilentPosts()) {
return false; return false;
} }
return defaultNotifySettings(peer).settingsUnknown(); return defaultSettings(peer).settingsUnknown();
} }
bool NotifySettings::soundUnknown( bool NotifySettings::soundUnknown(
@ -311,7 +334,7 @@ bool NotifySettings::soundUnknown(
} else if (const auto nonDefault = peer->notifySound()) { } else if (const auto nonDefault = peer->notifySound()) {
return false; return false;
} }
return defaultNotifySettings(peer).settingsUnknown(); return defaultSettings(peer).settingsUnknown();
} }
bool NotifySettings::settingsUnknown(not_null<const PeerData*> peer) const { bool NotifySettings::settingsUnknown(not_null<const PeerData*> peer) const {
@ -320,25 +343,17 @@ bool NotifySettings::settingsUnknown(not_null<const PeerData*> peer) const {
|| soundUnknown(peer); || soundUnknown(peer);
} }
rpl::producer<> NotifySettings::defaultUserNotifyUpdates() const { rpl::producer<> NotifySettings::defaultUpdates(DefaultNotify type) const {
return _defaultUserUpdates.events(); return defaultValue(type).updates.events();
} }
rpl::producer<> NotifySettings::defaultChatNotifyUpdates() const { rpl::producer<> NotifySettings::defaultUpdates(
return _defaultChatUpdates.events();
}
rpl::producer<> NotifySettings::defaultBroadcastNotifyUpdates() const {
return _defaultBroadcastUpdates.events();
}
rpl::producer<> NotifySettings::defaultNotifyUpdates(
not_null<const PeerData*> peer) const { not_null<const PeerData*> peer) const {
return peer->isUser() return defaultUpdates(peer->isUser()
? defaultUserNotifyUpdates() ? DefaultNotify::User
: (peer->isChat() || peer->isMegagroup()) : (peer->isChat() || peer->isMegagroup())
? defaultChatNotifyUpdates() ? DefaultNotify::Group
: defaultBroadcastNotifyUpdates(); : DefaultNotify::Broadcast);
} }
} // namespace Data } // namespace Data

View file

@ -18,6 +18,12 @@ namespace Data {
class DocumentMedia; class DocumentMedia;
class Session; class Session;
enum class DefaultNotify {
User,
Group,
Broadcast,
};
class NotifySettings final { class NotifySettings final {
public: public:
NotifySettings(not_null<Session*> owner); NotifySettings(not_null<Session*> owner);
@ -35,12 +41,19 @@ public:
std::shared_ptr<DocumentMedia> lookupRingtone(DocumentId id) const; std::shared_ptr<DocumentMedia> lookupRingtone(DocumentId id) const;
[[nodiscard]] rpl::producer<> defaultUserNotifyUpdates() const; [[nodiscard]] rpl::producer<> defaultUpdates(DefaultNotify type) const;
[[nodiscard]] rpl::producer<> defaultChatNotifyUpdates() const; [[nodiscard]] rpl::producer<> defaultUpdates(
[[nodiscard]] rpl::producer<> defaultBroadcastNotifyUpdates() const;
[[nodiscard]] rpl::producer<> defaultNotifyUpdates(
not_null<const PeerData*> peer) const; not_null<const PeerData*> peer) const;
[[nodiscard]] const PeerNotifySettings &defaultSettings(
DefaultNotify type) const;
void defaultUpdate(
DefaultNotify type,
std::optional<int> muteForSeconds,
std::optional<bool> silentPosts = std::nullopt,
std::optional<NotifySound> sound = std::nullopt);
[[nodiscard]] bool isMuted(not_null<const PeerData*> peer) const; [[nodiscard]] bool isMuted(not_null<const PeerData*> peer) const;
[[nodiscard]] bool silentPosts(not_null<const PeerData*> peer) const; [[nodiscard]] bool silentPosts(not_null<const PeerData*> peer) const;
[[nodiscard]] NotifySound sound(not_null<const PeerData*> peer) const; [[nodiscard]] NotifySound sound(not_null<const PeerData*> peer) const;
@ -50,26 +63,29 @@ public:
[[nodiscard]] bool soundUnknown(not_null<const PeerData*> peer) const; [[nodiscard]] bool soundUnknown(not_null<const PeerData*> peer) const;
private: private:
struct DefaultValue {
PeerNotifySettings settings;
rpl::event_stream<> updates;
};
[[nodiscard]] bool isMuted( [[nodiscard]] bool isMuted(
not_null<const PeerData*> peer, not_null<const PeerData*> peer,
crl::time *changesIn) const; crl::time *changesIn) const;
[[nodiscard]] const PeerNotifySettings &defaultNotifySettings( [[nodiscard]] DefaultValue &defaultValue(DefaultNotify type);
[[nodiscard]] const DefaultValue &defaultValue(DefaultNotify type) const;
[[nodiscard]] const PeerNotifySettings &defaultSettings(
not_null<const PeerData*> peer) const; not_null<const PeerData*> peer) const;
[[nodiscard]] bool settingsUnknown(not_null<const PeerData*> peer) const; [[nodiscard]] bool settingsUnknown(not_null<const PeerData*> peer) const;
void unmuteByFinished(); void unmuteByFinished();
void unmuteByFinishedDelayed(crl::time delay); void unmuteByFinishedDelayed(crl::time delay);
void updateLocal(not_null<PeerData*> peer); void updateLocal(not_null<PeerData*> peer);
void updateLocal(DefaultNotify type);
const not_null<Session*> _owner; const not_null<Session*> _owner;
PeerNotifySettings _defaultUser; DefaultValue _defaultValues[3];
PeerNotifySettings _defaultChat;
PeerNotifySettings _defaultBroadcast;
rpl::event_stream<> _defaultUserUpdates;
rpl::event_stream<> _defaultChatUpdates;
rpl::event_stream<> _defaultBroadcastUpdates;
std::unordered_set<not_null<const PeerData*>> _mutedPeers; std::unordered_set<not_null<const PeerData*>> _mutedPeers;
base::Timer _unmuteByFinishedTimer; base::Timer _unmuteByFinishedTimer;

View file

@ -793,10 +793,11 @@ HistoryWidget::HistoryWidget(
} }
}, lifetime()); }, lifetime());
using Type = Data::DefaultNotify;
rpl::merge( rpl::merge(
session().data().notifySettings().defaultUserNotifyUpdates(), session().data().notifySettings().defaultUpdates(Type::User),
session().data().notifySettings().defaultChatNotifyUpdates(), session().data().notifySettings().defaultUpdates(Type::Group),
session().data().notifySettings().defaultBroadcastNotifyUpdates() session().data().notifySettings().defaultUpdates(Type::Broadcast)
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
updateNotifyControls(); updateNotifyControls();
}, lifetime()); }, lifetime());

View file

@ -172,7 +172,7 @@ rpl::producer<bool> NotificationsEnabledValue(not_null<PeerData*> peer) {
peer, peer,
UpdateFlag::Notifications UpdateFlag::Notifications
) | rpl::to_empty, ) | rpl::to_empty,
peer->owner().notifySettings().defaultNotifyUpdates(peer) peer->owner().notifySettings().defaultUpdates(peer)
) | rpl::map([=] { ) | rpl::map([=] {
return !peer->owner().notifySettings().isMuted(peer); return !peer->owner().notifySettings().isMuted(peer);
}) | rpl::distinct_until_changed(); }) | rpl::distinct_until_changed();

View file

@ -231,7 +231,9 @@ void FillMuteMenu(
menu->addAction( menu->addAction(
tr::lng_mute_menu_sound_select(tr::now), tr::lng_mute_menu_sound_select(tr::now),
[=, show = args.show] { show->showBox(Box(RingtonesBox, peer)); }, [=, show = args.show] {
show->showBox(Box(PeerRingtonesBox, peer));
},
&st::menuIconSoundSelect); &st::menuIconSoundSelect);
const auto soundIsNone = peer->owner().notifySettings().sound(peer).none; const auto soundIsNone = peer->owner().notifySettings().sound(peer).none;

View file

@ -30,6 +30,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_account.h" #include "main/main_account.h"
#include "main/main_domain.h" #include "main/main_domain.h"
#include "api/api_authorizations.h" #include "api/api_authorizations.h"
#include "api/api_ringtones.h"
#include "data/data_session.h"
#include "data/data_document.h"
#include "data/notify/data_notify_settings.h"
#include "boxes/ringtones_box.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "facades.h" #include "facades.h"
#include "styles/style_settings.h" #include "styles/style_settings.h"
@ -824,12 +829,6 @@ void SetupNotificationsContent(
{ &st::settingsIconNotifications, kIconRed }, { &st::settingsIconNotifications, kIconRed },
desktopToggles->events_starting_with(settings.desktopNotify())); desktopToggles->events_starting_with(settings.desktopNotify()));
const auto soundToggles = container->lifetime(
).make_state<rpl::event_stream<bool>>();
const auto sound = addCheckbox(
tr::lng_settings_sound_notify(),
{ &st::settingsIconSound, kIconLightBlue },
soundToggles->events_starting_with(settings.soundNotify()));
const auto flashbounceToggles = container->lifetime( const auto flashbounceToggles = container->lifetime(
).make_state<rpl::event_stream<bool>>(); ).make_state<rpl::event_stream<bool>>();
const auto flashbounce = addCheckbox( const auto flashbounce = addCheckbox(
@ -842,6 +841,42 @@ void SetupNotificationsContent(
flashbounceToggles->events_starting_with( flashbounceToggles->events_starting_with(
settings.flashBounceNotify())); settings.flashBounceNotify()));
const auto soundLabel = container->lifetime(
).make_state<rpl::event_stream<QString>>();
const auto soundValue = [=] {
const auto owner = &controller->session().data();
const auto &settings = owner->notifySettings().defaultSettings(
Data::DefaultNotify::User);
return !Core::App().settings().soundNotify()
? Data::NotifySound{ .none = true }
: settings.sound().value_or(Data::NotifySound());
};
const auto label = [=] {
const auto now = soundValue();
const auto owner = &controller->session().data();
return now.none
? tr::lng_settings_sound_notify_off(tr::now)
: !now.id
? tr::lng_ringtones_box_default(tr::now)
: ExtractRingtoneName(owner->document(now.id));
};
controller->session().data().notifySettings().defaultUpdates(
Data::DefaultNotify::User
) | rpl::start_with_next([=] {
soundLabel->fire(label());
}, container->lifetime());
controller->session().api().ringtones().listUpdates(
) | rpl::start_with_next([=] {
soundLabel->fire(label());
}, container->lifetime());
const auto sound = AddButtonWithLabel(
container,
tr::lng_settings_sound_notify(),
soundLabel->events_starting_with(label()),
st::settingsButton,
{ &st::settingsIconSound, kIconLightBlue });
AddSkip(container); AddSkip(container);
const auto checkboxes = SetupNotifyViewOptions( const auto checkboxes = SetupNotifyViewOptions(
@ -1012,13 +1047,24 @@ void SetupNotificationsContent(
changed(Change::ViewParams); changed(Change::ViewParams);
}, preview->lifetime()); }, preview->lifetime());
sound->toggledChanges( sound->setClickedCallback([=] {
) | rpl::filter([](bool checked) { controller->show(Box(RingtonesBox, session, soundValue(), [=](
return (checked != Core::App().settings().soundNotify()); Data::NotifySound sound) {
}) | rpl::start_with_next([=](bool checked) { Core::App().settings().setSoundNotify(!sound.none);
Core::App().settings().setSoundNotify(checked); if (!sound.none) {
changed(Change::SoundEnabled); using Type = Data::DefaultNotify;
}, sound->lifetime()); const auto owner = &controller->session().data();
auto &settings = owner->notifySettings();
const auto updateType = [&](Type type) {
settings.defaultUpdate(type, {}, {}, sound);
};
updateType(Type::User);
updateType(Type::Group);
updateType(Type::Broadcast);
}
changed(Change::SoundEnabled);
}));
});
flashbounce->toggledChanges( flashbounce->toggledChanges(
) | rpl::filter([](bool checked) { ) | rpl::filter([](bool checked) {
@ -1057,7 +1103,7 @@ void SetupNotificationsContent(
} else if (change == Change::ViewParams) { } else if (change == Change::ViewParams) {
// //
} else if (change == Change::SoundEnabled) { } else if (change == Change::SoundEnabled) {
soundToggles->fire(Core::App().settings().soundNotify()); soundLabel->fire(label());
} else if (change == Change::FlashBounceEnabled) { } else if (change == Change::FlashBounceEnabled) {
flashbounceToggles->fire( flashbounceToggles->fire(
Core::App().settings().flashBounceNotify()); Core::App().settings().flashBounceNotify());