Support new NotificationSound.

This commit is contained in:
levlam 2022-04-11 20:01:44 +03:00
parent bb8c4ca42c
commit 7a2b3abe18
13 changed files with 515 additions and 98 deletions

View File

@ -393,6 +393,7 @@ set(TDLIB_SOURCE
td/telegram/NotificationManager.cpp
td/telegram/NotificationSettings.cpp
td/telegram/NotificationSettingsManager.cpp
td/telegram/NotificationSound.cpp
td/telegram/NotificationType.cpp
td/telegram/OptionManager.cpp
td/telegram/Payments.cpp
@ -620,6 +621,8 @@ set(TDLIB_SOURCE
td/telegram/NotificationManager.h
td/telegram/NotificationSettings.h
td/telegram/NotificationSettingsManager.h
td/telegram/NotificationSound.h
td/telegram/NotificationSoundType.h
td/telegram/NotificationType.h
td/telegram/OptionManager.h
td/telegram/PasswordManager.h

View File

@ -925,19 +925,19 @@ notificationSettingsScopeChannelChats = NotificationSettingsScope;
//@description Contains information about notification settings for a chat
//@use_default_mute_for If true, mute_for is ignored and the value for the relevant type of chat is used instead @mute_for Time left before notifications will be unmuted, in seconds
//@use_default_sound If true, sound is ignored and the value for the relevant type of chat is used instead @sound The name of an audio file to be used for notification sounds; only applies to iOS applications
//@use_default_sound If true, the value for the relevant type of chat is used instead of ringtone_id @ringtone_id Identifier of the ringtone to be played for notifications; 0 if sound is disabled
//@use_default_show_preview If true, show_preview is ignored and the value for the relevant type of chat is used instead @show_preview True, if message content must be displayed in notifications
//@use_default_disable_pinned_message_notifications If true, disable_pinned_message_notifications is ignored and the value for the relevant type of chat is used instead @disable_pinned_message_notifications If true, notifications for incoming pinned messages will be created as for an ordinary unread message
//@use_default_disable_mention_notifications If true, disable_mention_notifications is ignored and the value for the relevant type of chat is used instead @disable_mention_notifications If true, notifications for messages with mentions will be created as for an ordinary unread message
chatNotificationSettings use_default_mute_for:Bool mute_for:int32 use_default_sound:Bool sound:string use_default_show_preview:Bool show_preview:Bool use_default_disable_pinned_message_notifications:Bool disable_pinned_message_notifications:Bool use_default_disable_mention_notifications:Bool disable_mention_notifications:Bool = ChatNotificationSettings;
chatNotificationSettings use_default_mute_for:Bool mute_for:int32 use_default_sound:Bool ringtone_id:int64 use_default_show_preview:Bool show_preview:Bool use_default_disable_pinned_message_notifications:Bool disable_pinned_message_notifications:Bool use_default_disable_mention_notifications:Bool disable_mention_notifications:Bool = ChatNotificationSettings;
//@description Contains information about notification settings for several chats
//@mute_for Time left before notifications will be unmuted, in seconds
//@sound The name of an audio file to be used for notification sounds; only applies to iOS applications
//@ringtone_id Identifier of the ringtone to be played for notifications; 0 if sound is disabled
//@show_preview True, if message content must be displayed in notifications
//@disable_pinned_message_notifications True, if notifications for incoming pinned messages will be created as for an ordinary unread message
//@disable_mention_notifications True, if notifications for messages with mentions will be created as for an ordinary unread message
scopeNotificationSettings mute_for:int32 sound:string show_preview:Bool disable_pinned_message_notifications:Bool disable_mention_notifications:Bool = ScopeNotificationSettings;
scopeNotificationSettings mute_for:int32 ringtone_id:int64 show_preview:Bool disable_pinned_message_notifications:Bool disable_mention_notifications:Bool = ScopeNotificationSettings;
//@description Contains information about a message draft
@ -5174,7 +5174,7 @@ getScopeNotificationSettings scope:NotificationSettingsScope = ScopeNotification
//@description Changes notification settings for chats of a given type @scope Types of chats for which to change the notification settings @notification_settings The new notification settings for the given scope
setScopeNotificationSettings scope:NotificationSettingsScope notification_settings:scopeNotificationSettings = Ok;
//@description Resets all notification settings to their default values. By default, all chats are unmuted, the sound is set to "default" and message previews are shown
//@description Resets all notification settings to their default values. By default, all chats are unmuted and message previews are shown
resetAllNotificationSettings = Ok;

View File

@ -48,6 +48,7 @@
#include "td/telegram/NotificationManager.h"
#include "td/telegram/NotificationSettings.hpp"
#include "td/telegram/NotificationSettingsManager.h"
#include "td/telegram/NotificationSound.h"
#include "td/telegram/NotificationType.h"
#include "td/telegram/PublicDialogType.h"
#include "td/telegram/ReplyMarkup.h"
@ -7825,17 +7826,16 @@ void MessagesManager::on_message_edited(FullMessageId full_message_id, int32 pts
bool MessagesManager::update_dialog_notification_settings(DialogId dialog_id,
DialogNotificationSettings *current_settings,
const DialogNotificationSettings &new_settings) {
DialogNotificationSettings &&new_settings) {
if (td_->auth_manager_->is_bot()) {
// just in case
return false;
}
bool need_update_server = current_settings->mute_until != new_settings.mute_until ||
current_settings->sound != new_settings.sound ||
!are_equivalent_notification_sounds(current_settings->sound, new_settings.sound) ||
current_settings->show_preview != new_settings.show_preview ||
current_settings->use_default_mute_until != new_settings.use_default_mute_until ||
current_settings->use_default_sound != new_settings.use_default_sound ||
current_settings->use_default_show_preview != new_settings.use_default_show_preview;
bool need_update_local =
current_settings->use_default_disable_pinned_message_notifications !=
@ -7847,7 +7847,8 @@ bool MessagesManager::update_dialog_notification_settings(DialogId dialog_id,
bool is_changed = need_update_server || need_update_local ||
current_settings->is_synchronized != new_settings.is_synchronized ||
current_settings->is_use_default_fixed != new_settings.is_use_default_fixed;
current_settings->is_use_default_fixed != new_settings.is_use_default_fixed ||
are_different_equivalent_notification_sounds(current_settings->sound, new_settings.sound);
if (is_changed) {
Dialog *d = get_dialog(dialog_id);
@ -7860,7 +7861,7 @@ bool MessagesManager::update_dialog_notification_settings(DialogId dialog_id,
update_dialog_unmute_timeout(d, current_settings->use_default_mute_until, current_settings->mute_until,
new_settings.use_default_mute_until, new_settings.mute_until);
*current_settings = new_settings;
*current_settings = std::move(new_settings);
on_dialog_updated(dialog_id, "update_dialog_notification_settings");
if (is_dialog_muted(d)) {
@ -8063,7 +8064,7 @@ void MessagesManager::on_update_dialog_notify_settings(
return;
}
const DialogNotificationSettings notification_settings = ::td::get_dialog_notification_settings(
DialogNotificationSettings notification_settings = ::td::get_dialog_notification_settings(
std::move(peer_notify_settings), current_settings->use_default_disable_pinned_message_notifications,
current_settings->disable_pinned_message_notifications,
current_settings->use_default_disable_mention_notifications, current_settings->disable_mention_notifications);
@ -8071,7 +8072,7 @@ void MessagesManager::on_update_dialog_notify_settings(
return;
}
update_dialog_notification_settings(dialog_id, current_settings, notification_settings);
update_dialog_notification_settings(dialog_id, current_settings, std::move(notification_settings));
}
void MessagesManager::on_update_dialog_available_reactions(DialogId dialog_id, vector<string> &&available_reactions) {
@ -21270,7 +21271,10 @@ Status MessagesManager::set_dialog_notification_settings(
TRY_RESULT(new_settings, ::td::get_dialog_notification_settings(std::move(notification_settings),
current_settings->silent_send_message));
if (update_dialog_notification_settings(dialog_id, current_settings, new_settings)) {
if (is_notification_sound_default(current_settings->sound) && is_notification_sound_default(new_settings.sound)) {
new_settings.sound = dup_notification_sound(current_settings->sound);
}
if (update_dialog_notification_settings(dialog_id, current_settings, std::move(new_settings))) {
update_dialog_notification_settings_on_server(dialog_id, false);
}
return Status::OK();
@ -21279,11 +21283,11 @@ Status MessagesManager::set_dialog_notification_settings(
void MessagesManager::reset_all_notification_settings() {
CHECK(!td_->auth_manager_->is_bot());
DialogNotificationSettings new_dialog_settings;
new_dialog_settings.is_synchronized = true;
for (auto &dialog : dialogs_) {
DialogNotificationSettings new_dialog_settings;
new_dialog_settings.is_synchronized = true;
Dialog *d = dialog.second.get();
update_dialog_notification_settings(d->dialog_id, &d->notification_settings, new_dialog_settings);
update_dialog_notification_settings(d->dialog_id, &d->notification_settings, std::move(new_dialog_settings));
}
td_->notification_settings_manager_->reset_scope_notification_settings();
@ -35721,11 +35725,14 @@ void MessagesManager::force_create_dialog(DialogId dialog_id, const char *source
Dialog *user_d = get_dialog_force(DialogId(user_id), source);
if (user_d != nullptr && user_d->notification_settings.is_synchronized) {
VLOG(notifications) << "Copy notification settings from " << user_d->dialog_id << " to " << dialog_id;
auto new_notification_settings = user_d->notification_settings;
new_notification_settings.use_default_show_preview = true;
new_notification_settings.show_preview = false;
auto user_settings = &user_d->notification_settings;
auto new_notification_settings = DialogNotificationSettings(
user_settings->use_default_mute_until, user_settings->mute_until,
dup_notification_sound(user_settings->sound), true /*use_default_show_preview*/, false /*show_preview*/,
user_settings->silent_send_message, true, false, true, false);
new_notification_settings.is_secret_chat_show_preview_fixed = true;
update_dialog_notification_settings(dialog_id, &d->notification_settings, new_notification_settings);
update_dialog_notification_settings(dialog_id, &d->notification_settings,
std::move(new_notification_settings));
} else {
d->notification_settings.is_synchronized = true;
}

View File

@ -2604,7 +2604,7 @@ class MessagesManager final : public Actor {
NotificationId last_notification_id, const char *source);
bool update_dialog_notification_settings(DialogId dialog_id, DialogNotificationSettings *current_settings,
const DialogNotificationSettings &new_settings);
DialogNotificationSettings &&new_settings);
void schedule_dialog_unmute(DialogId dialog_id, bool use_default, int32 mute_until);

View File

@ -7,7 +7,6 @@
#include "td/telegram/NotificationSettings.h"
#include "td/telegram/Global.h"
#include "td/telegram/misc.h"
#include "td/utils/common.h"
@ -21,7 +20,6 @@ StringBuilder &operator<<(StringBuilder &string_builder, const DialogNotificatio
<< ", " << notification_settings.disable_pinned_message_notifications << ", "
<< notification_settings.disable_mention_notifications << ", "
<< notification_settings.use_default_mute_until << ", "
<< notification_settings.use_default_sound << ", "
<< notification_settings.use_default_show_preview << ", "
<< notification_settings.use_default_disable_pinned_message_notifications << ", "
<< notification_settings.use_default_disable_mention_notifications << ", "
@ -69,9 +67,9 @@ td_api::object_ptr<td_api::chatNotificationSettings> get_chat_notification_setti
CHECK(notification_settings != nullptr);
return td_api::make_object<td_api::chatNotificationSettings>(
notification_settings->use_default_mute_until, max(0, notification_settings->mute_until - G()->unix_time()),
notification_settings->use_default_sound, notification_settings->sound,
notification_settings->use_default_show_preview, notification_settings->show_preview,
notification_settings->use_default_disable_pinned_message_notifications,
is_notification_sound_default(notification_settings->sound),
get_notification_sound_ringtone_id(notification_settings->sound), notification_settings->use_default_show_preview,
notification_settings->show_preview, notification_settings->use_default_disable_pinned_message_notifications,
notification_settings->disable_pinned_message_notifications,
notification_settings->use_default_disable_mention_notifications,
notification_settings->disable_mention_notifications);
@ -81,8 +79,9 @@ td_api::object_ptr<td_api::scopeNotificationSettings> get_scope_notification_set
const ScopeNotificationSettings *notification_settings) {
CHECK(notification_settings != nullptr);
return td_api::make_object<td_api::scopeNotificationSettings>(
max(0, notification_settings->mute_until - G()->unix_time()), notification_settings->sound,
notification_settings->show_preview, notification_settings->disable_pinned_message_notifications,
max(0, notification_settings->mute_until - G()->unix_time()),
get_notification_sound_ringtone_id(notification_settings->sound), notification_settings->show_preview,
notification_settings->disable_pinned_message_notifications,
notification_settings->disable_mention_notifications);
}
@ -133,23 +132,17 @@ Result<DialogNotificationSettings> get_dialog_notification_settings(
if (notification_settings == nullptr) {
return Status::Error(400, "New notification settings must be non-empty");
}
if (!clean_input_string(notification_settings->sound_)) {
return Status::Error(400, "Notification settings sound must be encoded in UTF-8");
}
if (notification_settings->sound_.empty()) {
notification_settings->sound_ = "default";
}
int32 mute_until =
notification_settings->use_default_mute_for_ ? 0 : get_mute_until(notification_settings->mute_for_);
return DialogNotificationSettings(notification_settings->use_default_mute_for_, mute_until,
notification_settings->use_default_sound_, std::move(notification_settings->sound_),
notification_settings->use_default_show_preview_,
notification_settings->show_preview_, old_silent_send_message,
notification_settings->use_default_disable_pinned_message_notifications_,
notification_settings->disable_pinned_message_notifications_,
notification_settings->use_default_disable_mention_notifications_,
notification_settings->disable_mention_notifications_);
return DialogNotificationSettings(
notification_settings->use_default_mute_for_, mute_until,
get_notification_sound(notification_settings->use_default_sound_, notification_settings->ringtone_id_),
notification_settings->use_default_show_preview_, notification_settings->show_preview_, old_silent_send_message,
notification_settings->use_default_disable_pinned_message_notifications_,
notification_settings->disable_pinned_message_notifications_,
notification_settings->use_default_disable_mention_notifications_,
notification_settings->disable_mention_notifications_);
}
Result<ScopeNotificationSettings> get_scope_notification_settings(
@ -157,20 +150,27 @@ Result<ScopeNotificationSettings> get_scope_notification_settings(
if (notification_settings == nullptr) {
return Status::Error(400, "New notification settings must be non-empty");
}
if (!clean_input_string(notification_settings->sound_)) {
return Status::Error(400, "Notification settings sound must be encoded in UTF-8");
}
if (notification_settings->sound_.empty()) {
notification_settings->sound_ = "default";
}
auto mute_until = get_mute_until(notification_settings->mute_for_);
return ScopeNotificationSettings(mute_until, std::move(notification_settings->sound_),
return ScopeNotificationSettings(mute_until, get_notification_sound(false, notification_settings->ringtone_id_),
notification_settings->show_preview_,
notification_settings->disable_pinned_message_notifications_,
notification_settings->disable_mention_notifications_);
}
static unique_ptr<NotificationSound> get_peer_notification_sound(
tl_object_ptr<telegram_api::peerNotifySettings> &settings) {
telegram_api::NotificationSound *sound =
#if TD_ANDROID
settings->android_sound_.get();
#elif TD_DARWIN_IOS || TD_DARWIN_TV_OS || TD_DARWIN_WATCH_OS
settings->ios_sound_.get();
#else
settings->other_sound_.get();
#endif
return get_notification_sound(sound);
}
DialogNotificationSettings get_dialog_notification_settings(tl_object_ptr<telegram_api::peerNotifySettings> &&settings,
bool old_use_default_disable_pinned_message_notifications,
bool old_disable_pinned_message_notifications,
@ -180,16 +180,13 @@ DialogNotificationSettings get_dialog_notification_settings(tl_object_ptr<telegr
return DialogNotificationSettings();
}
bool use_default_mute_until = (settings->flags_ & telegram_api::peerNotifySettings::MUTE_UNTIL_MASK) == 0;
bool use_default_sound = settings->other_sound_ == nullptr;
bool use_default_show_preview = (settings->flags_ & telegram_api::peerNotifySettings::SHOW_PREVIEWS_MASK) == 0;
auto mute_until = use_default_mute_until || settings->mute_until_ <= G()->unix_time() ? 0 : settings->mute_until_;
string sound = "default";
bool silent_send_message =
(settings->flags_ & telegram_api::peerNotifySettings::SILENT_MASK) == 0 ? false : settings->silent_;
return {use_default_mute_until,
mute_until,
use_default_sound,
std::move(sound),
get_peer_notification_sound(settings),
use_default_show_preview,
settings->show_previews_,
silent_send_message,
@ -209,15 +206,14 @@ ScopeNotificationSettings get_scope_notification_settings(tl_object_ptr<telegram
settings->mute_until_ <= G()->unix_time()
? 0
: settings->mute_until_;
string sound = "default";
auto show_preview =
(settings->flags_ & telegram_api::peerNotifySettings::SHOW_PREVIEWS_MASK) == 0 ? false : settings->show_previews_;
return {mute_until, std::move(sound), show_preview, old_disable_pinned_message_notifications,
return {mute_until, get_peer_notification_sound(settings), show_preview, old_disable_pinned_message_notifications,
old_disable_mention_notifications};
}
bool are_default_dialog_notification_settings(const DialogNotificationSettings &settings, bool compare_sound) {
return settings.use_default_mute_until && (!compare_sound || settings.use_default_sound) &&
return settings.use_default_mute_until && (!compare_sound || is_notification_sound_default(settings.sound)) &&
settings.use_default_show_preview && settings.use_default_disable_pinned_message_notifications &&
settings.use_default_disable_mention_notifications;
}

View File

@ -6,6 +6,7 @@
//
#pragma once
#include "td/telegram/NotificationSound.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
@ -18,11 +19,10 @@ namespace td {
class DialogNotificationSettings {
public:
int32 mute_until = 0;
string sound = "default";
unique_ptr<NotificationSound> sound;
bool show_preview = true;
bool silent_send_message = false;
bool use_default_mute_until = true;
bool use_default_sound = true;
bool use_default_show_preview = true;
bool is_use_default_fixed = true;
bool is_secret_chat_show_preview_fixed = false;
@ -36,7 +36,7 @@ class DialogNotificationSettings {
DialogNotificationSettings() = default;
DialogNotificationSettings(bool use_default_mute_until, int32 mute_until, bool use_default_sound, string sound,
DialogNotificationSettings(bool use_default_mute_until, int32 mute_until, unique_ptr<NotificationSound> &&sound,
bool use_default_show_preview, bool show_preview, bool silent_send_message,
bool use_default_disable_pinned_message_notifications,
bool disable_pinned_message_notifications, bool use_default_disable_mention_notifications,
@ -46,7 +46,6 @@ class DialogNotificationSettings {
, show_preview(show_preview)
, silent_send_message(silent_send_message)
, use_default_mute_until(use_default_mute_until)
, use_default_sound(use_default_sound)
, use_default_show_preview(use_default_show_preview)
, is_synchronized(true)
, use_default_disable_pinned_message_notifications(use_default_disable_pinned_message_notifications)
@ -61,7 +60,7 @@ enum class NotificationSettingsScope : int32 { Private, Group, Channel };
class ScopeNotificationSettings {
public:
int32 mute_until = 0;
string sound = "default";
unique_ptr<NotificationSound> sound;
bool show_preview = true;
bool is_synchronized = false;
@ -71,7 +70,7 @@ class ScopeNotificationSettings {
ScopeNotificationSettings() = default;
ScopeNotificationSettings(int32 mute_until, string sound, bool show_preview,
ScopeNotificationSettings(int32 mute_until, unique_ptr<NotificationSound> &&sound, bool show_preview,
bool disable_pinned_message_notifications, bool disable_mention_notifications)
: mute_until(mute_until)
, sound(std::move(sound))

View File

@ -8,6 +8,7 @@
#include "td/telegram/Global.h"
#include "td/telegram/NotificationSettings.h"
#include "td/telegram/NotificationSound.h"
#include "td/utils/tl_helpers.h"
@ -17,7 +18,8 @@ template <class StorerT>
void store(const DialogNotificationSettings &notification_settings, StorerT &storer) {
bool is_muted = !notification_settings.use_default_mute_until && notification_settings.mute_until != 0 &&
notification_settings.mute_until > G()->unix_time();
bool has_sound = !notification_settings.use_default_sound && notification_settings.sound != "default";
bool has_sound = notification_settings.sound != nullptr;
bool has_ringtone_support = true;
BEGIN_STORE_FLAGS();
STORE_FLAG(is_muted);
STORE_FLAG(has_sound);
@ -25,7 +27,7 @@ void store(const DialogNotificationSettings &notification_settings, StorerT &sto
STORE_FLAG(notification_settings.silent_send_message);
STORE_FLAG(notification_settings.is_synchronized);
STORE_FLAG(notification_settings.use_default_mute_until);
STORE_FLAG(notification_settings.use_default_sound);
STORE_FLAG(false); // use_default_sound
STORE_FLAG(notification_settings.use_default_show_preview);
STORE_FLAG(notification_settings.is_use_default_fixed);
STORE_FLAG(!notification_settings.use_default_disable_pinned_message_notifications);
@ -33,6 +35,7 @@ void store(const DialogNotificationSettings &notification_settings, StorerT &sto
STORE_FLAG(!notification_settings.use_default_disable_mention_notifications);
STORE_FLAG(notification_settings.disable_mention_notifications);
STORE_FLAG(notification_settings.is_secret_chat_show_preview_fixed);
STORE_FLAG(has_ringtone_support);
END_STORE_FLAGS();
if (is_muted) {
store(notification_settings.mute_until, storer);
@ -46,8 +49,10 @@ template <class ParserT>
void parse(DialogNotificationSettings &notification_settings, ParserT &parser) {
bool is_muted;
bool has_sound;
bool use_default_sound;
bool use_disable_pinned_message_notifications;
bool use_disable_mention_notifications;
bool has_ringtone_support;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(is_muted);
PARSE_FLAG(has_sound);
@ -55,7 +60,7 @@ void parse(DialogNotificationSettings &notification_settings, ParserT &parser) {
PARSE_FLAG(notification_settings.silent_send_message);
PARSE_FLAG(notification_settings.is_synchronized);
PARSE_FLAG(notification_settings.use_default_mute_until);
PARSE_FLAG(notification_settings.use_default_sound);
PARSE_FLAG(use_default_sound);
PARSE_FLAG(notification_settings.use_default_show_preview);
PARSE_FLAG(notification_settings.is_use_default_fixed);
PARSE_FLAG(use_disable_pinned_message_notifications);
@ -63,6 +68,7 @@ void parse(DialogNotificationSettings &notification_settings, ParserT &parser) {
PARSE_FLAG(use_disable_mention_notifications);
PARSE_FLAG(notification_settings.disable_mention_notifications);
PARSE_FLAG(notification_settings.is_secret_chat_show_preview_fixed);
PARSE_FLAG(has_ringtone_support);
END_PARSE_FLAGS();
notification_settings.use_default_disable_pinned_message_notifications = !use_disable_pinned_message_notifications;
notification_settings.use_default_disable_mention_notifications = !use_disable_mention_notifications;
@ -70,14 +76,21 @@ void parse(DialogNotificationSettings &notification_settings, ParserT &parser) {
parse(notification_settings.mute_until, parser);
}
if (has_sound) {
parse(notification_settings.sound, parser);
if (has_ringtone_support) {
parse_notification_sound(notification_settings.sound, parser);
} else {
string sound;
parse(sound, parser);
notification_settings.sound = use_default_sound ? nullptr : get_legacy_notification_sound(sound);
}
}
}
template <class StorerT>
void store(const ScopeNotificationSettings &notification_settings, StorerT &storer) {
bool is_muted = notification_settings.mute_until != 0 && notification_settings.mute_until > G()->unix_time();
bool has_sound = notification_settings.sound != "default";
bool has_sound = notification_settings.sound != nullptr;
bool has_ringtone_support = true;
BEGIN_STORE_FLAGS();
STORE_FLAG(is_muted);
STORE_FLAG(has_sound);
@ -86,6 +99,7 @@ void store(const ScopeNotificationSettings &notification_settings, StorerT &stor
STORE_FLAG(notification_settings.is_synchronized);
STORE_FLAG(notification_settings.disable_pinned_message_notifications);
STORE_FLAG(notification_settings.disable_mention_notifications);
STORE_FLAG(has_ringtone_support);
END_STORE_FLAGS();
if (is_muted) {
store(notification_settings.mute_until, storer);
@ -100,6 +114,7 @@ void parse(ScopeNotificationSettings &notification_settings, ParserT &parser) {
bool is_muted;
bool has_sound;
bool silent_send_message_ignored;
bool has_ringtone_support;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(is_muted);
PARSE_FLAG(has_sound);
@ -108,13 +123,20 @@ void parse(ScopeNotificationSettings &notification_settings, ParserT &parser) {
PARSE_FLAG(notification_settings.is_synchronized);
PARSE_FLAG(notification_settings.disable_pinned_message_notifications);
PARSE_FLAG(notification_settings.disable_mention_notifications);
PARSE_FLAG(has_ringtone_support);
END_PARSE_FLAGS();
(void)silent_send_message_ignored;
if (is_muted) {
parse(notification_settings.mute_until, parser);
}
if (has_sound) {
parse(notification_settings.sound, parser);
if (has_ringtone_support) {
parse_notification_sound(notification_settings.sound, parser);
} else {
string sound;
parse(sound, parser);
notification_settings.sound = get_legacy_notification_sound(sound);
}
}
}

View File

@ -15,6 +15,7 @@
#include "td/telegram/MessagesManager.h"
#include "td/telegram/NotificationManager.h"
#include "td/telegram/NotificationSettings.hpp"
#include "td/telegram/NotificationSound.h"
#include "td/telegram/Td.h"
#include "td/telegram/TdDb.h"
#include "td/telegram/telegram_api.h"
@ -174,7 +175,7 @@ class UpdateDialogNotifySettingsQuery final : public Td::ResultHandler {
if (!new_settings.use_default_mute_until) {
flags |= telegram_api::inputPeerNotifySettings::MUTE_UNTIL_MASK;
}
if (!new_settings.use_default_sound) {
if (new_settings.sound != nullptr) {
flags |= telegram_api::inputPeerNotifySettings::SOUND_MASK;
}
if (!new_settings.use_default_show_preview) {
@ -184,10 +185,9 @@ class UpdateDialogNotifySettingsQuery final : public Td::ResultHandler {
flags |= telegram_api::inputPeerNotifySettings::SILENT_MASK;
}
send_query(G()->net_query_creator().create(telegram_api::account_updateNotifySettings(
std::move(input_notify_peer),
make_tl_object<telegram_api::inputPeerNotifySettings>(
flags, new_settings.show_preview, new_settings.silent_send_message, new_settings.mute_until,
make_tl_object<telegram_api::notificationSoundDefault>()))));
std::move(input_notify_peer), make_tl_object<telegram_api::inputPeerNotifySettings>(
flags, new_settings.show_preview, new_settings.silent_send_message,
new_settings.mute_until, get_input_notification_sound(new_settings.sound)))));
}
void on_result(BufferSlice packet) final {
@ -231,12 +231,14 @@ class UpdateScopeNotifySettingsQuery final : public Td::ResultHandler {
auto input_notify_peer = get_input_notify_peer(scope);
CHECK(input_notify_peer != nullptr);
int32 flags = telegram_api::inputPeerNotifySettings::MUTE_UNTIL_MASK |
telegram_api::inputPeerNotifySettings::SOUND_MASK |
telegram_api::inputPeerNotifySettings::SHOW_PREVIEWS_MASK;
if (new_settings.sound != nullptr) {
flags |= telegram_api::inputPeerNotifySettings::SOUND_MASK;
}
send_query(G()->net_query_creator().create(telegram_api::account_updateNotifySettings(
std::move(input_notify_peer), make_tl_object<telegram_api::inputPeerNotifySettings>(
flags, new_settings.show_preview, false, new_settings.mute_until,
make_tl_object<telegram_api::notificationSoundDefault>()))));
get_input_notification_sound(new_settings.sound)))));
scope_ = scope;
}
@ -341,9 +343,9 @@ void NotificationSettingsManager::init() {
}
}
if (!channels_notification_settings_.is_synchronized && is_authorized) {
channels_notification_settings_ = chats_notification_settings_;
channels_notification_settings_.disable_pinned_message_notifications = false;
channels_notification_settings_.disable_mention_notifications = false;
channels_notification_settings_ = ScopeNotificationSettings(
chats_notification_settings_.mute_until, dup_notification_sound(chats_notification_settings_.sound),
chats_notification_settings_.show_preview, false, false);
channels_notification_settings_.is_synchronized = false;
send_get_scope_notification_settings_query(NotificationSettingsScope::Channel, Promise<>());
}
@ -483,26 +485,26 @@ void NotificationSettingsManager::on_update_scope_notify_settings(
auto old_notification_settings = get_scope_notification_settings(scope);
CHECK(old_notification_settings != nullptr);
const ScopeNotificationSettings notification_settings = ::td::get_scope_notification_settings(
ScopeNotificationSettings notification_settings = ::td::get_scope_notification_settings(
std::move(peer_notify_settings), old_notification_settings->disable_pinned_message_notifications,
old_notification_settings->disable_mention_notifications);
if (!notification_settings.is_synchronized) {
return;
}
update_scope_notification_settings(scope, old_notification_settings, notification_settings);
update_scope_notification_settings(scope, old_notification_settings, std::move(notification_settings));
}
bool NotificationSettingsManager::update_scope_notification_settings(NotificationSettingsScope scope,
ScopeNotificationSettings *current_settings,
const ScopeNotificationSettings &new_settings) {
ScopeNotificationSettings &&new_settings) {
if (td_->auth_manager_->is_bot()) {
// just in case
return false;
}
bool need_update_server = current_settings->mute_until != new_settings.mute_until ||
current_settings->sound != new_settings.sound ||
!are_equivalent_notification_sounds(current_settings->sound, new_settings.sound) ||
current_settings->show_preview != new_settings.show_preview;
bool need_update_local =
current_settings->disable_pinned_message_notifications != new_settings.disable_pinned_message_notifications ||
@ -512,7 +514,8 @@ bool NotificationSettingsManager::update_scope_notification_settings(Notificatio
if (was_inited && !is_inited) {
return false; // just in case
}
bool is_changed = need_update_server || need_update_local || was_inited != is_inited;
bool is_changed = need_update_server || need_update_local || was_inited != is_inited ||
are_different_equivalent_notification_sounds(current_settings->sound, new_settings.sound);
if (is_changed) {
save_scope_notification_settings(scope, new_settings);
@ -528,7 +531,7 @@ bool NotificationSettingsManager::update_scope_notification_settings(Notificatio
td_->messages_manager_->on_update_scope_mention_notifications(scope, new_settings.disable_mention_notifications);
}
*current_settings = new_settings;
*current_settings = std::move(new_settings);
send_closure(G()->td(), &Td::send_update, get_update_scope_notification_settings_object(scope));
}
@ -571,15 +574,15 @@ void NotificationSettingsManager::update_scope_unmute_timeout(NotificationSettin
void NotificationSettingsManager::reset_scope_notification_settings() {
CHECK(!td_->auth_manager_->is_bot());
ScopeNotificationSettings new_scope_settings;
new_scope_settings.is_synchronized = true;
update_scope_notification_settings(NotificationSettingsScope::Private, &users_notification_settings_,
new_scope_settings);
update_scope_notification_settings(NotificationSettingsScope::Group, &chats_notification_settings_,
new_scope_settings);
update_scope_notification_settings(NotificationSettingsScope::Channel, &channels_notification_settings_,
new_scope_settings);
for (auto scope :
{NotificationSettingsScope::Private, NotificationSettingsScope::Group, NotificationSettingsScope::Channel}) {
auto current_settings = get_scope_notification_settings(scope);
CHECK(current_settings != nullptr);
ScopeNotificationSettings new_scope_settings;
new_scope_settings.is_synchronized = true;
update_scope_notification_settings(scope, current_settings, std::move(new_scope_settings));
}
}
void NotificationSettingsManager::send_get_dialog_notification_settings_query(DialogId dialog_id,
@ -653,8 +656,13 @@ void NotificationSettingsManager::update_dialog_notify_settings(DialogId dialog_
Status NotificationSettingsManager::set_scope_notification_settings(
NotificationSettingsScope scope, td_api::object_ptr<td_api::scopeNotificationSettings> &&notification_settings) {
CHECK(!td_->auth_manager_->is_bot());
auto *current_settings = get_scope_notification_settings(scope);
CHECK(current_settings != nullptr);
TRY_RESULT(new_settings, ::td::get_scope_notification_settings(std::move(notification_settings)));
if (update_scope_notification_settings(scope, get_scope_notification_settings(scope), new_settings)) {
if (is_notification_sound_default(current_settings->sound) && is_notification_sound_default(new_settings.sound)) {
new_settings.sound = dup_notification_sound(current_settings->sound);
}
if (update_scope_notification_settings(scope, current_settings, std::move(new_settings))) {
update_scope_notification_settings_on_server(scope, 0);
}
return Status::OK();

View File

@ -99,7 +99,7 @@ class NotificationSettingsManager final : public Actor {
const ScopeNotificationSettings &new_settings);
bool update_scope_notification_settings(NotificationSettingsScope scope, ScopeNotificationSettings *current_settings,
const ScopeNotificationSettings &new_settings);
ScopeNotificationSettings &&new_settings);
static uint64 save_update_scope_notification_settings_on_server_log_event(NotificationSettingsScope scope);

View File

@ -0,0 +1,299 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "td/telegram/NotificationSound.h"
#include "td/utils/tl_helpers.h"
namespace td {
class NotificationSoundNone final : public NotificationSound {
public:
NotificationSoundNone() = default;
NotificationSoundType get_type() const final {
return NotificationSoundType::None;
}
};
class NotificationSoundLocal final : public NotificationSound {
public:
string title_;
string data_;
NotificationSoundLocal() = default;
NotificationSoundLocal(string title, string data) : title_(std::move(title)), data_(std::move(data)) {
}
NotificationSoundType get_type() const final {
return NotificationSoundType::Local;
}
};
class NotificationSoundRingtone final : public NotificationSound {
public:
int64 ringtone_id_;
NotificationSoundRingtone() = default;
explicit NotificationSoundRingtone(int64 ringtone_id) : ringtone_id_(ringtone_id) {
}
NotificationSoundType get_type() const final {
return NotificationSoundType::Ringtone;
}
};
template <class StorerT>
static void store(const NotificationSound *notification_sound, StorerT &storer) {
CHECK(notification_sound != nullptr);
auto sound_type = notification_sound->get_type();
store(sound_type, storer);
switch (sound_type) {
case NotificationSoundType::None:
break;
case NotificationSoundType::Local: {
const auto *sound = static_cast<const NotificationSoundLocal *>(notification_sound);
store(sound->title_, storer);
store(sound->data_, storer);
break;
}
case NotificationSoundType::Ringtone: {
const auto *sound = static_cast<const NotificationSoundRingtone *>(notification_sound);
store(sound->ringtone_id_, storer);
break;
}
default:
UNREACHABLE();
}
}
template <class ParserT>
static void parse(unique_ptr<NotificationSound> &notification_sound, ParserT &parser) {
NotificationSoundType sound_type;
parse(sound_type, parser);
switch (sound_type) {
case NotificationSoundType::None:
notification_sound = make_unique<NotificationSoundNone>();
break;
case NotificationSoundType::Local: {
auto sound = make_unique<NotificationSoundLocal>();
parse(sound->title_, parser);
parse(sound->data_, parser);
notification_sound = std::move(sound);
break;
}
case NotificationSoundType::Ringtone: {
auto sound = make_unique<NotificationSoundRingtone>();
parse(sound->ringtone_id_, parser);
notification_sound = std::move(sound);
break;
}
default:
LOG(FATAL) << "Have unknown notification sound type " << static_cast<int32>(sound_type);
}
}
void store_notification_sound(const NotificationSound *notification_sound, LogEventStorerCalcLength &storer) {
store(notification_sound, storer);
}
void store_notification_sound(const NotificationSound *notification_sound, LogEventStorerUnsafe &storer) {
store(notification_sound, storer);
}
void parse_notification_sound(unique_ptr<NotificationSound> &notification_sound, LogEventParser &parser) {
parse(notification_sound, parser);
}
StringBuilder &operator<<(StringBuilder &string_builder, const unique_ptr<NotificationSound> &notification_sound) {
if (notification_sound == nullptr) {
return string_builder << "DefaultSound";
}
switch (notification_sound->get_type()) {
case NotificationSoundType::None:
return string_builder << "NoSound";
case NotificationSoundType::Local: {
const auto *sound = static_cast<const NotificationSoundLocal *>(notification_sound.get());
return string_builder << "LocalSound[" << sound->title_ << '|' << sound->data_ << ']';
}
case NotificationSoundType::Ringtone: {
const auto *sound = static_cast<const NotificationSoundRingtone *>(notification_sound.get());
return string_builder << "Ringtone[" << sound->ringtone_id_ << ']';
}
default:
UNREACHABLE();
return string_builder;
}
}
bool is_notification_sound_default(const unique_ptr<NotificationSound> &notification_sound) {
if (notification_sound == nullptr) {
return true;
}
return notification_sound->get_type() == NotificationSoundType::Local;
}
bool are_equivalent_notification_sounds(const unique_ptr<NotificationSound> &lhs,
const unique_ptr<NotificationSound> &rhs) {
if (is_notification_sound_default(lhs)) {
return is_notification_sound_default(rhs);
}
if (is_notification_sound_default(rhs)) {
return false;
}
auto sound_type = lhs->get_type();
if (sound_type != rhs->get_type()) {
return false;
}
switch (sound_type) {
case NotificationSoundType::None:
return true;
case NotificationSoundType::Ringtone:
return static_cast<const NotificationSoundRingtone *>(lhs.get())->ringtone_id_ ==
static_cast<const NotificationSoundRingtone *>(rhs.get())->ringtone_id_;
case NotificationSoundType::Local:
default:
UNREACHABLE();
break;
}
return false;
}
bool are_different_equivalent_notification_sounds(const unique_ptr<NotificationSound> &lhs,
const unique_ptr<NotificationSound> &rhs) {
if (lhs == nullptr) {
return rhs != nullptr && rhs->get_type() == NotificationSoundType::Local;
}
if (rhs == nullptr) {
return lhs->get_type() == NotificationSoundType::Local;
}
if (lhs->get_type() != NotificationSoundType::Local || rhs->get_type() != NotificationSoundType::Local) {
return false;
}
const auto *lhs_local = static_cast<const NotificationSoundLocal *>(lhs.get());
const auto *rhs_local = static_cast<const NotificationSoundLocal *>(rhs.get());
return lhs_local->title_ != rhs_local->title_ || lhs_local->data_ != rhs_local->data_;
}
int64 get_notification_sound_ringtone_id(const unique_ptr<NotificationSound> &notification_sound) {
if (notification_sound == nullptr) {
return -1;
}
switch (notification_sound->get_type()) {
case NotificationSoundType::None:
return 0;
case NotificationSoundType::Local:
return -1;
case NotificationSoundType::Ringtone: {
return static_cast<const NotificationSoundRingtone *>(notification_sound.get())->ringtone_id_;
default:
UNREACHABLE();
return -1;
}
}
}
unique_ptr<NotificationSound> get_legacy_notification_sound(const string &sound) {
if (sound == "default") {
return nullptr;
}
if (sound.empty()) {
return make_unique<NotificationSoundNone>();
}
return td::make_unique<NotificationSoundLocal>(sound, sound);
}
unique_ptr<NotificationSound> get_notification_sound(bool use_default_sound, int64 ringtone_id) {
if (use_default_sound || ringtone_id == -1) {
return nullptr;
}
if (ringtone_id == 0) {
return make_unique<NotificationSoundNone>();
}
return td::make_unique<NotificationSoundRingtone>(ringtone_id);
}
unique_ptr<NotificationSound> get_notification_sound(telegram_api::NotificationSound *notification_sound) {
if (notification_sound == nullptr) {
return nullptr;
}
switch (notification_sound->get_id()) {
case telegram_api::notificationSoundDefault::ID:
return nullptr;
case telegram_api::notificationSoundNone::ID:
return make_unique<NotificationSoundNone>();
case telegram_api::notificationSoundLocal::ID: {
const auto *sound = static_cast<telegram_api::notificationSoundLocal *>(notification_sound);
return td::make_unique<NotificationSoundLocal>(std::move(sound->title_), std::move(sound->data_));
}
case telegram_api::notificationSoundRingtone::ID: {
const auto *sound = static_cast<telegram_api::notificationSoundRingtone *>(notification_sound);
if (sound->id_ == 0 || sound->id_ == -1) {
LOG(ERROR) << "Receive ringtone with id = " << sound->id_;
return make_unique<NotificationSoundNone>();
}
return td::make_unique<NotificationSoundRingtone>(sound->id_);
}
default:
UNREACHABLE();
return nullptr;
}
}
telegram_api::object_ptr<telegram_api::NotificationSound> get_input_notification_sound(
const unique_ptr<NotificationSound> &notification_sound) {
if (notification_sound == nullptr) {
return nullptr;
}
// must not return nullptr if notification_sound != nullptr
switch (notification_sound->get_type()) {
case NotificationSoundType::None:
return telegram_api::make_object<telegram_api::notificationSoundNone>();
case NotificationSoundType::Local: {
const auto *sound = static_cast<const NotificationSoundLocal *>(notification_sound.get());
return telegram_api::make_object<telegram_api::notificationSoundLocal>(sound->title_, sound->data_);
}
case NotificationSoundType::Ringtone: {
const auto *sound = static_cast<const NotificationSoundRingtone *>(notification_sound.get());
return telegram_api::make_object<telegram_api::notificationSoundRingtone>(sound->ringtone_id_);
}
default:
UNREACHABLE();
return nullptr;
}
}
unique_ptr<NotificationSound> dup_notification_sound(const unique_ptr<NotificationSound> &notification_sound) {
if (notification_sound == nullptr) {
return nullptr;
}
switch (notification_sound->get_type()) {
case NotificationSoundType::None:
return make_unique<NotificationSoundNone>();
case NotificationSoundType::Local: {
const auto *sound = static_cast<const NotificationSoundLocal *>(notification_sound.get());
return td::make_unique<NotificationSoundLocal>(sound->title_, sound->data_);
}
case NotificationSoundType::Ringtone: {
const auto *sound = static_cast<const NotificationSoundRingtone *>(notification_sound.get());
return td::make_unique<NotificationSoundRingtone>(sound->ringtone_id_);
}
default:
UNREACHABLE();
return nullptr;
}
}
} // namespace td

View File

@ -0,0 +1,68 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/logevent/LogEvent.h"
#include "td/telegram/NotificationSoundType.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h"
#include "td/utils/StringBuilder.h"
namespace td {
class NotificationSound {
public:
NotificationSound() = default;
NotificationSound(const NotificationSound &) = delete;
NotificationSound &operator=(const NotificationSound &) = delete;
NotificationSound(NotificationSound &&) = delete;
NotificationSound &operator=(NotificationSound &&) = delete;
virtual NotificationSoundType get_type() const = 0;
virtual ~NotificationSound() = default;
template <class StorerT>
void store(StorerT &storer) const;
};
StringBuilder &operator<<(StringBuilder &string_builder, const unique_ptr<NotificationSound> &notification_sound);
void store_notification_sound(const NotificationSound *notification_sound, LogEventStorerCalcLength &storer);
void store_notification_sound(const NotificationSound *notification_sound, LogEventStorerUnsafe &storer);
template <class StorerT>
void NotificationSound::store(StorerT &storer) const {
store_notification_sound(this, storer);
}
void parse_notification_sound(unique_ptr<NotificationSound> &notification_sound, LogEventParser &parser);
bool is_notification_sound_default(const unique_ptr<NotificationSound> &notification_sound);
bool are_equivalent_notification_sounds(const unique_ptr<NotificationSound> &lhs,
const unique_ptr<NotificationSound> &rhs);
bool are_different_equivalent_notification_sounds(const unique_ptr<NotificationSound> &lhs,
const unique_ptr<NotificationSound> &rhs);
int64 get_notification_sound_ringtone_id(const unique_ptr<NotificationSound> &notification_sound);
unique_ptr<NotificationSound> get_legacy_notification_sound(const string &sound);
unique_ptr<NotificationSound> get_notification_sound(bool use_default_sound, int64 ringtone_id);
unique_ptr<NotificationSound> get_notification_sound(telegram_api::NotificationSound *notification_sound);
telegram_api::object_ptr<telegram_api::NotificationSound> get_input_notification_sound(
const unique_ptr<NotificationSound> &notification_sound);
unique_ptr<NotificationSound> dup_notification_sound(const unique_ptr<NotificationSound> &notification_sound);
} // namespace td

View File

@ -0,0 +1,15 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/utils/common.h"
namespace td {
enum class NotificationSoundType : int32 { None, Local, Ringtone };
} // namespace td

View File

@ -4498,17 +4498,17 @@ class CliClient final : public Actor {
} else if (op == "scns" || op == "ssns") {
string chat_id_or_scope;
string mute_for;
string sound;
int64 ringtone_id;
string show_preview;
string disable_pinned_message_notifications;
string disable_mention_notifications;
get_args(args, chat_id_or_scope, mute_for, sound, show_preview, disable_pinned_message_notifications,
get_args(args, chat_id_or_scope, mute_for, ringtone_id, show_preview, disable_pinned_message_notifications,
disable_mention_notifications);
if (op == "scns") {
send_request(td_api::make_object<td_api::setChatNotificationSettings>(
as_chat_id(chat_id_or_scope),
td_api::make_object<td_api::chatNotificationSettings>(
mute_for.empty(), to_integer<int32>(mute_for), sound.empty(), sound, show_preview.empty(),
mute_for.empty(), to_integer<int32>(mute_for), ringtone_id == -1, ringtone_id, show_preview.empty(),
as_bool(show_preview), disable_pinned_message_notifications.empty(),
as_bool(disable_pinned_message_notifications), disable_mention_notifications.empty(),
as_bool(disable_mention_notifications))));
@ -4516,7 +4516,7 @@ class CliClient final : public Actor {
send_request(td_api::make_object<td_api::setScopeNotificationSettings>(
get_notification_settings_scope(chat_id_or_scope),
td_api::make_object<td_api::scopeNotificationSettings>(
to_integer<int32>(mute_for), sound, as_bool(show_preview),
to_integer<int32>(mute_for), ringtone_id, as_bool(show_preview),
as_bool(disable_pinned_message_notifications), as_bool(disable_mention_notifications))));
}
} else if (op == "rans") {