Added initial support of custom sound to notifications.

This commit is contained in:
23rd 2022-04-05 15:26:18 +03:00
parent 9950452e57
commit b1e3b9688e
6 changed files with 85 additions and 5 deletions

View file

@ -2417,6 +2417,8 @@ void ApiWrap::refreshFileReference(
MTP_long(data.themeId), MTP_long(data.themeId),
MTP_long(data.accessHash)), MTP_long(data.accessHash)),
MTP_long(0))); MTP_long(0)));
}, [&](Data::FileOriginRingtones data) {
fail();
}, [&](v::null_t) { }, [&](v::null_t) {
fail(); fail();
}); });

View file

@ -96,6 +96,12 @@ struct FileOriginTheme {
} }
}; };
struct FileOriginRingtones {
inline bool operator<(const FileOriginRingtones &) const {
return false;
}
};
struct FileOrigin { struct FileOrigin {
using Variant = std::variant< using Variant = std::variant<
v::null_t, v::null_t,
@ -105,7 +111,8 @@ struct FileOrigin {
FileOriginStickerSet, FileOriginStickerSet,
FileOriginSavedGifs, FileOriginSavedGifs,
FileOriginWallpaper, FileOriginWallpaper,
FileOriginTheme>; FileOriginTheme,
FileOriginRingtones>;
FileOrigin() = default; FileOrigin() = default;
FileOrigin(FileOriginMessage data) : data(data) { FileOrigin(FileOriginMessage data) : data(data) {
@ -122,6 +129,8 @@ struct FileOrigin {
} }
FileOrigin(FileOriginTheme data) : data(data) { FileOrigin(FileOriginTheme data) : data(data) {
} }
FileOrigin(FileOriginRingtones data) : data(data) {
}
explicit operator bool() const { explicit operator bool() const {
return !v::is_null(data); return !v::is_null(data);

View file

@ -8,14 +8,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/notify/data_notify_settings.h" #include "data/notify/data_notify_settings.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "api/api_ringtones.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "core/application.h" #include "core/application.h"
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_chat.h" #include "data/data_chat.h"
#include "data/data_document.h"
#include "data/data_file_origin.h"
#include "data/data_peer.h" #include "data/data_peer.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "main/main_session.h"
#include "history/history.h" #include "history/history.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "window/notifications_manager.h" #include "window/notifications_manager.h"
@ -160,6 +164,42 @@ void NotifySettings::updateLocal(not_null<PeerData*> peer) {
} else { } else {
_mutedPeers.erase(peer); _mutedPeers.erase(peer);
} }
if (const auto sound = peer->notifySound(); sound && sound->id) {
const auto cache = [=](DocumentId id) {
if (const auto document = _owner->document(id)) {
const auto view = document->createMediaView();
_ringtones.views.emplace(id, view);
document->forceToCache(true);
document->save(Data::FileOriginRingtones(), QString());
}
};
if (const auto doc = _owner->document(sound->id); !doc->isNull()) {
cache(sound->id);
} else {
_ringtones.pendingIds.push_back(sound->id);
if (!_ringtones.pendingLifetime) {
// Not requested yet.
_owner->session().api().ringtones().listUpdates(
) | rpl::start_with_next([=] {
for (const auto &id : base::take(_ringtones.pendingIds)) {
cache(id);
}
_ringtones.pendingLifetime.destroy();
}, _ringtones.pendingLifetime);
_owner->session().api().ringtones().requestList();
}
}
}
}
std::shared_ptr<DocumentMedia> NotifySettings::lookupRingtone(
DocumentId id) const {
if (!id) {
return nullptr;
}
const auto it = _ringtones.views.find(id);
return (it == end(_ringtones.views)) ? nullptr : it->second;
} }
void NotifySettings::unmuteByFinishedDelayed(crl::time delay) { void NotifySettings::unmuteByFinishedDelayed(crl::time delay) {

View file

@ -15,6 +15,7 @@ class PeerData;
namespace Data { namespace Data {
class DocumentMedia;
class Session; class Session;
class NotifySettings final { class NotifySettings final {
@ -32,6 +33,8 @@ public:
std::optional<NotifySound> sound = std::nullopt); std::optional<NotifySound> sound = std::nullopt);
void resetToDefault(not_null<PeerData*> peer); void resetToDefault(not_null<PeerData*> peer);
std::shared_ptr<DocumentMedia> lookupRingtone(DocumentId id) const;
[[nodiscard]] rpl::producer<> defaultUserNotifyUpdates() const; [[nodiscard]] rpl::producer<> defaultUserNotifyUpdates() const;
[[nodiscard]] rpl::producer<> defaultChatNotifyUpdates() const; [[nodiscard]] rpl::producer<> defaultChatNotifyUpdates() const;
[[nodiscard]] rpl::producer<> defaultBroadcastNotifyUpdates() const; [[nodiscard]] rpl::producer<> defaultBroadcastNotifyUpdates() const;
@ -70,6 +73,14 @@ private:
std::unordered_set<not_null<const PeerData*>> _mutedPeers; std::unordered_set<not_null<const PeerData*>> _mutedPeers;
base::Timer _unmuteByFinishedTimer; base::Timer _unmuteByFinishedTimer;
struct {
base::flat_map<
DocumentId,
std::shared_ptr<DocumentMedia>> views;
std::vector<DocumentId> pendingIds;
rpl::lifetime pendingLifetime;
} _ringtones;
}; };
} // namespace Data } // namespace Data

View file

@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_item_components.h" #include "history/history_item_components.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "data/notify/data_notify_settings.h" #include "data/notify/data_notify_settings.h"
#include "data/data_document_media.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_user.h" #include "data/data_user.h"
@ -467,7 +468,8 @@ void System::showNext() {
}; };
auto ms = crl::now(), nextAlert = crl::time(0); auto ms = crl::now(), nextAlert = crl::time(0);
bool alert = false; auto alert = false;
std::shared_ptr<Data::DocumentMedia> customSound = nullptr;
for (auto i = _whenAlerts.begin(); i != _whenAlerts.end();) { for (auto i = _whenAlerts.begin(); i != _whenAlerts.end();) {
while (!i->second.empty() && i->second.begin()->first <= ms) { while (!i->second.empty() && i->second.begin()->first <= ms) {
const auto peer = i->first->peer; const auto peer = i->first->peer;
@ -475,6 +477,9 @@ void System::showNext() {
const auto peerUnknown = notifySettings.muteUnknown(peer); const auto peerUnknown = notifySettings.muteUnknown(peer);
const auto peerAlert = !peerUnknown const auto peerAlert = !peerUnknown
&& !notifySettings.isMuted(peer); && !notifySettings.isMuted(peer);
const auto peerSoundId = !notifySettings.soundUnknown(peer)
? notifySettings.sound(peer).id
: 0;
const auto from = i->second.begin()->second; const auto from = i->second.begin()->second;
const auto fromUnknown = (!from const auto fromUnknown = (!from
|| notifySettings.muteUnknown(from)); || notifySettings.muteUnknown(from));
@ -482,6 +487,9 @@ void System::showNext() {
&& !notifySettings.isMuted(from); && !notifySettings.isMuted(from);
if (peerAlert || fromAlert) { if (peerAlert || fromAlert) {
alert = true; alert = true;
if (peerSoundId) {
customSound = notifySettings.lookupRingtone(peerSoundId);
}
} }
while (!i->second.empty() while (!i->second.empty()
&& i->second.begin()->first <= ms + kMinimalAlertDelay) { && i->second.begin()->first <= ms + kMinimalAlertDelay) {
@ -508,9 +516,18 @@ void System::showNext() {
} }
} }
if (settings.soundNotify() && !_manager->skipAudio()) { if (settings.soundNotify() && !_manager->skipAudio()) {
ensureSoundCreated(); const auto custom = customSound
_soundTrack->playOnce(); && !customSound->bytes().isEmpty();
Media::Player::mixer()->suppressAll(_soundTrack->getLengthMs()); if (custom) {
const auto bytes = customSound->bytes();
_customSoundTrack = Media::Audio::Current().createTrack();
_customSoundTrack->fillFromData(bytes::make_vector(bytes));
} else {
ensureSoundCreated();
}
const auto &track = custom ? _customSoundTrack : _soundTrack;
track->playOnce();
Media::Player::mixer()->suppressAll(track->getLengthMs());
Media::Player::mixer()->faderOnTimer(); Media::Player::mixer()->faderOnTimer();
} }
} }

View file

@ -181,6 +181,7 @@ private:
rpl::event_stream<ChangeType> _settingsChanged; rpl::event_stream<ChangeType> _settingsChanged;
std::unique_ptr<Media::Audio::Track> _soundTrack; std::unique_ptr<Media::Audio::Track> _soundTrack;
std::unique_ptr<Media::Audio::Track> _customSoundTrack;
int _lastForwardedCount = 0; int _lastForwardedCount = 0;
uint64 _lastHistorySessionId = 0; uint64 _lastHistorySessionId = 0;