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.accessHash)),
MTP_long(0)));
}, [&](Data::FileOriginRingtones data) {
fail();
}, [&](v::null_t) {
fail();
});

View file

@ -96,6 +96,12 @@ struct FileOriginTheme {
}
};
struct FileOriginRingtones {
inline bool operator<(const FileOriginRingtones &) const {
return false;
}
};
struct FileOrigin {
using Variant = std::variant<
v::null_t,
@ -105,7 +111,8 @@ struct FileOrigin {
FileOriginStickerSet,
FileOriginSavedGifs,
FileOriginWallpaper,
FileOriginTheme>;
FileOriginTheme,
FileOriginRingtones>;
FileOrigin() = default;
FileOrigin(FileOriginMessage data) : data(data) {
@ -122,6 +129,8 @@ struct FileOrigin {
}
FileOrigin(FileOriginTheme data) : data(data) {
}
FileOrigin(FileOriginRingtones data) : data(data) {
}
explicit operator bool() const {
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 "apiwrap.h"
#include "api/api_ringtones.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_document.h"
#include "data/data_file_origin.h"
#include "data/data_peer.h"
#include "data/data_session.h"
#include "data/data_user.h"
#include "main/main_session.h"
#include "history/history.h"
#include "main/main_session.h"
#include "window/notifications_manager.h"
@ -160,6 +164,42 @@ void NotifySettings::updateLocal(not_null<PeerData*> peer) {
} else {
_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) {

View file

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

View file

@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_item_components.h"
#include "lang/lang_keys.h"
#include "data/notify/data_notify_settings.h"
#include "data/data_document_media.h"
#include "data/data_session.h"
#include "data/data_channel.h"
#include "data/data_user.h"
@ -467,7 +468,8 @@ void System::showNext() {
};
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();) {
while (!i->second.empty() && i->second.begin()->first <= ms) {
const auto peer = i->first->peer;
@ -475,6 +477,9 @@ void System::showNext() {
const auto peerUnknown = notifySettings.muteUnknown(peer);
const auto peerAlert = !peerUnknown
&& !notifySettings.isMuted(peer);
const auto peerSoundId = !notifySettings.soundUnknown(peer)
? notifySettings.sound(peer).id
: 0;
const auto from = i->second.begin()->second;
const auto fromUnknown = (!from
|| notifySettings.muteUnknown(from));
@ -482,6 +487,9 @@ void System::showNext() {
&& !notifySettings.isMuted(from);
if (peerAlert || fromAlert) {
alert = true;
if (peerSoundId) {
customSound = notifySettings.lookupRingtone(peerSoundId);
}
}
while (!i->second.empty()
&& i->second.begin()->first <= ms + kMinimalAlertDelay) {
@ -508,9 +516,18 @@ void System::showNext() {
}
}
if (settings.soundNotify() && !_manager->skipAudio()) {
ensureSoundCreated();
_soundTrack->playOnce();
Media::Player::mixer()->suppressAll(_soundTrack->getLengthMs());
const auto custom = customSound
&& !customSound->bytes().isEmpty();
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();
}
}

View file

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