mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-14 05:07:10 +02:00
Use sound in native notifications on macOS.
This commit is contained in:
parent
37c7b0c6d1
commit
aa0c56876c
6 changed files with 70 additions and 35 deletions
|
@ -314,30 +314,20 @@ LocalCache::~LocalCache() {
|
|||
}
|
||||
}
|
||||
|
||||
QString LocalCache::path(
|
||||
LocalSound LocalCache::sound(
|
||||
DocumentId id,
|
||||
Fn<QByteArray()> resolveBytes,
|
||||
Fn<QByteArray()> fallbackBytes) {
|
||||
Fn<QByteArray()> resolveOriginalBytes,
|
||||
Fn<QByteArray()> fallbackOriginalBytes) {
|
||||
auto &result = _cache[id];
|
||||
if (!result.isEmpty()) {
|
||||
return result;
|
||||
return { id, result };
|
||||
}
|
||||
const auto bytes = resolveBytes();
|
||||
if (bytes.isEmpty()) {
|
||||
return fallbackBytes ? path(0, fallbackBytes, nullptr) : QString();
|
||||
}
|
||||
const auto prefix = cWorkingDir() + u"tdata/audio_cache"_q;
|
||||
QDir().mkpath(prefix);
|
||||
|
||||
const auto name = QString::number(id, 16).toUpper();
|
||||
result = u"%1/%2.wav"_q.arg(prefix, name);
|
||||
auto file = QFile(result);
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
return fallbackBytes ? path(0, fallbackBytes, nullptr) : QString();
|
||||
}
|
||||
file.write(ConvertAndCut(bytes));
|
||||
file.close();
|
||||
return result;
|
||||
result = resolveOriginalBytes();
|
||||
return !result.isEmpty()
|
||||
? LocalSound{ id, result }
|
||||
: fallbackOriginalBytes
|
||||
? sound(0, fallbackOriginalBytes, nullptr)
|
||||
: LocalSound();
|
||||
}
|
||||
|
||||
} // namespace Media::Audio
|
||||
|
|
|
@ -9,18 +9,27 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
namespace Media::Audio {
|
||||
|
||||
struct LocalSound {
|
||||
DocumentId id = 0;
|
||||
QByteArray wav;
|
||||
|
||||
explicit operator bool() const {
|
||||
return !wav.isEmpty();
|
||||
}
|
||||
};
|
||||
|
||||
class LocalCache final {
|
||||
public:
|
||||
LocalCache() = default;
|
||||
~LocalCache();
|
||||
|
||||
[[nodiscard]] QString path(
|
||||
[[nodiscard]] LocalSound sound(
|
||||
DocumentId id,
|
||||
Fn<QByteArray()> resolveBytes,
|
||||
Fn<QByteArray()> fallbackBytes);
|
||||
Fn<QByteArray()> resolveOriginalBytes,
|
||||
Fn<QByteArray()> fallbackOriginalBytes);
|
||||
|
||||
private:
|
||||
base::flat_map<DocumentId, QString> _cache;
|
||||
base::flat_map<DocumentId, QByteArray> _cache;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -232,7 +232,7 @@ NotificationData::NotificationData(
|
|||
bool NotificationData::init(const Info &info) {
|
||||
const auto &title = info.title;
|
||||
const auto &subtitle = info.subtitle;
|
||||
//const auto sound = info.soundPath ? info.soundPath() : QString();
|
||||
//const auto sound = info.sound ? info.sound() : QString();
|
||||
if (_application) {
|
||||
_notification = Gio::Notification::new_(
|
||||
subtitle.isEmpty()
|
||||
|
|
|
@ -229,6 +229,8 @@ private:
|
|||
void clearingThreadLoop();
|
||||
void checkFocusState();
|
||||
|
||||
[[nodiscard]] QString cacheSound(const Media::Audio::LocalSound &sound);
|
||||
|
||||
const uint64 _managerId = 0;
|
||||
QString _managerIdString;
|
||||
|
||||
|
@ -266,6 +268,7 @@ private:
|
|||
QProcess _dnd;
|
||||
QProcess _focus;
|
||||
std::vector<Fn<void()>> _focusedCallbacks;
|
||||
base::flat_map<DocumentId, QString> _cachedSounds;
|
||||
bool _waitingDnd = false;
|
||||
bool _waitingFocus = false;
|
||||
bool _focused = false;
|
||||
|
@ -289,6 +292,37 @@ Manager::Private::Private(Manager *manager)
|
|||
}, _lifetime);
|
||||
}
|
||||
|
||||
QString Manager::Private::cacheSound(const Media::Audio::LocalSound &sound) {
|
||||
const auto i = _cachedSounds.find(sound.id);
|
||||
if (i != end(_cachedSounds)) {
|
||||
return i->second;
|
||||
}
|
||||
|
||||
auto result = u"TDesktop-%1"_q.arg(sound.id
|
||||
? QString::number(sound.id, 16).toUpper()
|
||||
: u"Default"_q);
|
||||
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(
|
||||
NSLibraryDirectory,
|
||||
NSUserDomainMask,
|
||||
YES);
|
||||
NSString *library = [paths firstObject];
|
||||
NSString *sounds = [library stringByAppendingPathComponent:@"Sounds"];
|
||||
const auto folder = NS2QString(sounds);
|
||||
|
||||
const auto path = folder + u"/%1.wav"_q.arg(result);
|
||||
QDir().mkpath(folder);
|
||||
|
||||
auto f = QFile(path);
|
||||
if (f.open(QIODevice::WriteOnly)) {
|
||||
f.write(sound.wav);
|
||||
f.close();
|
||||
}
|
||||
|
||||
_cachedSounds.emplace(sound.id, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Manager::Private::showNotification(
|
||||
NotificationInfo &&info,
|
||||
Ui::PeerUserpicView &userpicView) {
|
||||
|
@ -334,9 +368,9 @@ void Manager::Private::showNotification(
|
|||
[notification setHasReplyButton:YES];
|
||||
}
|
||||
|
||||
const auto sound = info.soundPath ? info.soundPath() : QString();
|
||||
if (!sound.isEmpty()) {
|
||||
[notification setSoundName:Q2NSString(sound)];
|
||||
const auto sound = info.sound ? info.sound() : Media::Audio::LocalSound();
|
||||
if (sound) {
|
||||
[notification setSoundName:Q2NSString(cacheSound(sound))];
|
||||
} else {
|
||||
[notification setSoundName:nil];
|
||||
}
|
||||
|
|
|
@ -118,8 +118,9 @@ constexpr auto kSystemAlertDuration = crl::time(0);
|
|||
|| notifySettings->muteUnknown(from));
|
||||
const auto fromAlert = !fromUnknown
|
||||
&& !notifySettings->isMuted(from);
|
||||
return (threadAlert || fromAlert)
|
||||
? notifySettings->sound(thread).id
|
||||
const auto &sound = notifySettings->sound(thread);
|
||||
return ((threadAlert || fromAlert) && !sound.none)
|
||||
? sound.id
|
||||
: std::optional<DocumentId>();
|
||||
}
|
||||
|
||||
|
@ -1252,13 +1253,13 @@ void NativeManager::doShowNotification(NotificationFields &&fields) {
|
|||
// #TODO optimize
|
||||
auto userpicView = item->history()->peer->createUserpicView();
|
||||
const auto owner = &item->history()->owner();
|
||||
const auto soundPath = fields.soundId ? [=, id = *fields.soundId] {
|
||||
return _localSoundCache.path(id, [=] {
|
||||
const auto sound = fields.soundId ? [=, id = *fields.soundId] {
|
||||
return _localSoundCache.sound(id, [=] {
|
||||
return Core::App().notifications().lookupSoundBytes(owner, id);
|
||||
}, [=] {
|
||||
return Core::App().notifications().lookupSoundBytes(owner, 0);
|
||||
});
|
||||
} : Fn<QString()>();
|
||||
} : Fn<NotificationSound()>();
|
||||
doShowNativeNotification({
|
||||
.peer = item->history()->peer,
|
||||
.topicRootId = item->topicRootId(),
|
||||
|
@ -1266,7 +1267,7 @@ void NativeManager::doShowNotification(NotificationFields &&fields) {
|
|||
.title = scheduled ? WrapFromScheduled(fullTitle) : fullTitle,
|
||||
.subtitle = subtitle,
|
||||
.message = text,
|
||||
.soundPath = soundPath,
|
||||
.sound = sound,
|
||||
.options = options,
|
||||
}, userpicView);
|
||||
}
|
||||
|
|
|
@ -399,6 +399,7 @@ public:
|
|||
return ManagerType::Native;
|
||||
}
|
||||
|
||||
using NotificationSound = Media::Audio::LocalSound;
|
||||
struct NotificationInfo {
|
||||
not_null<PeerData*> peer;
|
||||
MsgId topicRootId = 0;
|
||||
|
@ -406,7 +407,7 @@ public:
|
|||
QString title;
|
||||
QString subtitle;
|
||||
QString message;
|
||||
Fn<QString()> soundPath;
|
||||
Fn<NotificationSound()> sound;
|
||||
DisplayOptions options;
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue