mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Move notification closing to NotificationData destruction
This commit is contained in:
parent
b962309498
commit
345b2cb835
1 changed files with 38 additions and 110 deletions
|
@ -158,25 +158,21 @@ public:
|
||||||
void clearNotification(NotificationId id);
|
void clearNotification(NotificationId id);
|
||||||
void invokeIfNotInhibited(Fn<void()> callback);
|
void invokeIfNotInhibited(Fn<void()> callback);
|
||||||
|
|
||||||
~Private();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct NotificationData : public base::has_weak_ptr {
|
struct NotificationData : public base::has_weak_ptr {
|
||||||
uint id = 0;
|
std::variant<v::null_t, uint, std::string> id;
|
||||||
|
rpl::lifetime lifetime;
|
||||||
};
|
};
|
||||||
using Notification = std::unique_ptr<NotificationData>;
|
using Notification = std::unique_ptr<NotificationData>;
|
||||||
|
|
||||||
const not_null<Manager*> _manager;
|
const not_null<Manager*> _manager;
|
||||||
|
|
||||||
base::flat_map<
|
|
||||||
ContextId,
|
|
||||||
base::flat_map<MsgId,
|
|
||||||
std::variant<Notification, std::string>>> _notifications;
|
|
||||||
|
|
||||||
Gio::Application _application;
|
Gio::Application _application;
|
||||||
XdgNotifications::NotificationsProxy _proxy;
|
XdgNotifications::NotificationsProxy _proxy;
|
||||||
XdgNotifications::Notifications _interface;
|
XdgNotifications::Notifications _interface;
|
||||||
Media::Audio::LocalDiskCache _sounds;
|
Media::Audio::LocalDiskCache _sounds;
|
||||||
|
base::flat_map<
|
||||||
|
ContextId,
|
||||||
|
base::flat_map<MsgId, Notification>> _notifications;
|
||||||
rpl::lifetime _lifetime;
|
rpl::lifetime _lifetime;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -427,7 +423,7 @@ void Manager::Private::init(XdgNotifications::NotificationsProxy proxy) {
|
||||||
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
||||||
for (const auto &[key, notifications] : _notifications) {
|
for (const auto &[key, notifications] : _notifications) {
|
||||||
for (const auto &[msgId, notification] : notifications) {
|
for (const auto &[msgId, notification] : notifications) {
|
||||||
if (id == v::get<Notification>(notification)->id) {
|
if (id == v::get<uint>(notification->id)) {
|
||||||
if (actionName == "default") {
|
if (actionName == "default") {
|
||||||
_manager->notificationActivated({ key, msgId });
|
_manager->notificationActivated({ key, msgId });
|
||||||
} else if (actionName == "mail-mark-read") {
|
} else if (actionName == "mail-mark-read") {
|
||||||
|
@ -451,7 +447,7 @@ void Manager::Private::init(XdgNotifications::NotificationsProxy proxy) {
|
||||||
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
||||||
for (const auto &[key, notifications] : _notifications) {
|
for (const auto &[key, notifications] : _notifications) {
|
||||||
for (const auto &[msgId, notification] : notifications) {
|
for (const auto &[msgId, notification] : notifications) {
|
||||||
if (id == v::get<Notification>(notification)->id) {
|
if (id == v::get<uint>(notification->id)) {
|
||||||
_manager->notificationReplied(
|
_manager->notificationReplied(
|
||||||
{ key, msgId },
|
{ key, msgId },
|
||||||
{ QString::fromStdString(text), {} });
|
{ QString::fromStdString(text), {} });
|
||||||
|
@ -472,7 +468,7 @@ void Manager::Private::init(XdgNotifications::NotificationsProxy proxy) {
|
||||||
std::string token) {
|
std::string token) {
|
||||||
for (const auto &[key, notifications] : _notifications) {
|
for (const auto &[key, notifications] : _notifications) {
|
||||||
for (const auto &[msgId, notification] : notifications) {
|
for (const auto &[msgId, notification] : notifications) {
|
||||||
if (id == v::get<Notification>(notification)->id) {
|
if (id == v::get<uint>(notification->id)) {
|
||||||
GLib::setenv("XDG_ACTIVATION_TOKEN", token, true);
|
GLib::setenv("XDG_ACTIVATION_TOKEN", token, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -505,8 +501,7 @@ void Manager::Private::init(XdgNotifications::NotificationsProxy proxy) {
|
||||||
* In all other cases we keep the notification reference so that we may clear the notification later from history,
|
* In all other cases we keep the notification reference so that we may clear the notification later from history,
|
||||||
* if the message for that notification is read (e.g. chat is opened or read from another device).
|
* if the message for that notification is read (e.g. chat is opened or read from another device).
|
||||||
*/
|
*/
|
||||||
if (id == v::get<Notification>(notification)->id
|
if (id == v::get<uint>(notification->id) && reason == 2) {
|
||||||
&& reason == 2) {
|
|
||||||
clearNotification({ key, msgId });
|
clearNotification({ key, msgId });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -535,18 +530,16 @@ void Manager::Private::showNotification(
|
||||||
.msgId = info.itemId,
|
.msgId = info.itemId,
|
||||||
};
|
};
|
||||||
auto notification = _application
|
auto notification = _application
|
||||||
? std::variant<Notification, Gio::Notification>(
|
? Gio::Notification::new_(
|
||||||
Gio::Notification::new_(
|
info.subtitle.isEmpty()
|
||||||
info.subtitle.isEmpty()
|
? info.title.toStdString()
|
||||||
? info.title.toStdString()
|
: info.subtitle.toStdString()
|
||||||
: info.subtitle.toStdString()
|
+ " (" + info.title.toStdString() + ')')
|
||||||
+ " (" + info.title.toStdString() + ')'))
|
: Gio::Notification();
|
||||||
: std::variant<Notification, Gio::Notification>(
|
|
||||||
std::make_unique<NotificationData>());
|
|
||||||
|
|
||||||
std::vector<gi::cstring> actions;
|
std::vector<gi::cstring> actions;
|
||||||
auto hints = GLib::VariantDict::new_();
|
auto hints = GLib::VariantDict::new_();
|
||||||
v::match(notification, [&](Gio::Notification ¬ification) {
|
if (notification) {
|
||||||
notification.set_body(info.message.toStdString());
|
notification.set_body(info.message.toStdString());
|
||||||
|
|
||||||
notification.set_icon(
|
notification.set_icon(
|
||||||
|
@ -601,7 +594,7 @@ void Manager::Private::showNotification(
|
||||||
"app.notification-mark-as-read",
|
"app.notification-mark-as-read",
|
||||||
notificationVariant);
|
notificationVariant);
|
||||||
}
|
}
|
||||||
}, [&](const Notification ¬ification) {
|
} else {
|
||||||
if (HasCapability("actions")) {
|
if (HasCapability("actions")) {
|
||||||
actions.push_back("default");
|
actions.push_back("default");
|
||||||
actions.push_back(tr::lng_open_link(tr::now).toStdString());
|
actions.push_back(tr::lng_open_link(tr::now).toStdString());
|
||||||
|
@ -661,11 +654,11 @@ void Manager::Private::showNotification(
|
||||||
|
|
||||||
hints.insert_value("desktop-entry", GLib::Variant::new_string(
|
hints.insert_value("desktop-entry", GLib::Variant::new_string(
|
||||||
QGuiApplication::desktopFileName().toStdString()));
|
QGuiApplication::desktopFileName().toStdString()));
|
||||||
});
|
}
|
||||||
|
|
||||||
const auto imageKey = GetImageKey();
|
const auto imageKey = GetImageKey();
|
||||||
if (!options.hideNameAndPhoto) {
|
if (!options.hideNameAndPhoto) {
|
||||||
v::match(notification, [&](Gio::Notification ¬ification) {
|
if (notification) {
|
||||||
QByteArray imageData;
|
QByteArray imageData;
|
||||||
QBuffer buffer(&imageData);
|
QBuffer buffer(&imageData);
|
||||||
buffer.open(QIODevice::WriteOnly);
|
buffer.open(QIODevice::WriteOnly);
|
||||||
|
@ -679,11 +672,7 @@ void Manager::Private::showNotification(
|
||||||
reinterpret_cast<const uchar*>(imageData.constData()),
|
reinterpret_cast<const uchar*>(imageData.constData()),
|
||||||
imageData.size(),
|
imageData.size(),
|
||||||
[imageData] {})));
|
[imageData] {})));
|
||||||
}, [&](const Notification ¬ification) {
|
} else if (!imageKey.empty()) {
|
||||||
if (imageKey.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto image = Window::Notifications::GenerateUserpic(
|
const auto image = Window::Notifications::GenerateUserpic(
|
||||||
peer,
|
peer,
|
||||||
userpicView
|
userpicView
|
||||||
|
@ -703,43 +692,27 @@ void Manager::Private::showNotification(
|
||||||
true,
|
true,
|
||||||
[image] {}),
|
[image] {}),
|
||||||
}));
|
}));
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
auto i = _notifications.find(key);
|
|
||||||
if (i != end(_notifications)) {
|
|
||||||
auto j = i->second.find(info.itemId);
|
|
||||||
if (j != end(i->second)) {
|
|
||||||
auto oldNotification = std::move(j->second);
|
|
||||||
i->second.erase(j);
|
|
||||||
v::match(oldNotification, [&](
|
|
||||||
const std::string &oldNotification) {
|
|
||||||
_application.withdraw_notification(oldNotification);
|
|
||||||
}, [&](const Notification &oldNotification) {
|
|
||||||
_interface.call_close_notification(
|
|
||||||
oldNotification->id,
|
|
||||||
nullptr);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
i = _notifications.emplace(key).first;
|
|
||||||
}
|
}
|
||||||
v::match(notification, [&](Gio::Notification ¬ification) {
|
|
||||||
const auto j = i->second.emplace(
|
|
||||||
info.itemId,
|
|
||||||
Gio::dbus_generate_guid()).first;
|
|
||||||
_application.send_notification(
|
|
||||||
v::get<std::string>(j->second),
|
|
||||||
notification);
|
|
||||||
}, [&](Notification ¬ification) {
|
|
||||||
const auto j = i->second.emplace(
|
|
||||||
info.itemId,
|
|
||||||
std::move(notification)).first;
|
|
||||||
|
|
||||||
const auto weak = base::make_weak(
|
const auto &data
|
||||||
v::get<Notification>(j->second).get());
|
= _notifications[key][info.itemId]
|
||||||
|
= std::make_unique<NotificationData>();
|
||||||
|
data->lifetime.add([=, notification = data.get()] {
|
||||||
|
v::match(notification->id, [&](const std::string &id) {
|
||||||
|
_application.withdraw_notification(id);
|
||||||
|
}, [&](uint id) {
|
||||||
|
_interface.call_close_notification(id, nullptr);
|
||||||
|
}, [](v::null_t) {});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (notification) {
|
||||||
|
const auto id = Gio::dbus_generate_guid();
|
||||||
|
data->id = id;
|
||||||
|
_application.send_notification(id, notification);
|
||||||
|
} else {
|
||||||
// work around snap's activation restriction
|
// work around snap's activation restriction
|
||||||
|
const auto weak = base::make_weak(data);
|
||||||
StartServiceAsync(
|
StartServiceAsync(
|
||||||
_proxy.get_connection(),
|
_proxy.get_connection(),
|
||||||
crl::guard(weak, [=]() mutable {
|
crl::guard(weak, [=]() mutable {
|
||||||
|
@ -808,19 +781,11 @@ void Manager::Private::showNotification(
|
||||||
&callbackWrap->wrapper,
|
&callbackWrap->wrapper,
|
||||||
callbackWrap);
|
callbackWrap);
|
||||||
}));
|
}));
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::Private::clearAll() {
|
void Manager::Private::clearAll() {
|
||||||
for (const auto &[key, notifications] : base::take(_notifications)) {
|
_notifications.clear();
|
||||||
for (const auto &[msgId, notification] : notifications) {
|
|
||||||
v::match(notification, [&](const std::string ¬ification) {
|
|
||||||
_application.withdraw_notification(notification);
|
|
||||||
}, [&](const Notification ¬ification) {
|
|
||||||
_interface.call_close_notification(notification->id, nullptr);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::Private::clearFromItem(not_null<HistoryItem*> item) {
|
void Manager::Private::clearFromItem(not_null<HistoryItem*> item) {
|
||||||
|
@ -837,16 +802,10 @@ void Manager::Private::clearFromItem(not_null<HistoryItem*> item) {
|
||||||
if (j == i->second.end()) {
|
if (j == i->second.end()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto taken = base::take(j->second);
|
|
||||||
i->second.erase(j);
|
i->second.erase(j);
|
||||||
if (i->second.empty()) {
|
if (i->second.empty()) {
|
||||||
_notifications.erase(i);
|
_notifications.erase(i);
|
||||||
}
|
}
|
||||||
v::match(taken, [&](const std::string &taken) {
|
|
||||||
_application.withdraw_notification(taken);
|
|
||||||
}, [&](const Notification &taken) {
|
|
||||||
_interface.call_close_notification(taken->id, nullptr);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::Private::clearFromTopic(not_null<Data::ForumTopic*> topic) {
|
void Manager::Private::clearFromTopic(not_null<Data::ForumTopic*> topic) {
|
||||||
|
@ -856,16 +815,7 @@ void Manager::Private::clearFromTopic(not_null<Data::ForumTopic*> topic) {
|
||||||
};
|
};
|
||||||
const auto i = _notifications.find(key);
|
const auto i = _notifications.find(key);
|
||||||
if (i != _notifications.cend()) {
|
if (i != _notifications.cend()) {
|
||||||
const auto temp = base::take(i->second);
|
|
||||||
_notifications.erase(i);
|
_notifications.erase(i);
|
||||||
|
|
||||||
for (const auto &[msgId, notification] : temp) {
|
|
||||||
v::match(notification, [&](const std::string ¬ification) {
|
|
||||||
_application.withdraw_notification(notification);
|
|
||||||
}, [&](const Notification ¬ification) {
|
|
||||||
_interface.call_close_notification(notification->id, nullptr);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -879,16 +829,7 @@ void Manager::Private::clearFromHistory(not_null<History*> history) {
|
||||||
while (i != _notifications.cend()
|
while (i != _notifications.cend()
|
||||||
&& i->first.sessionId == sessionId
|
&& i->first.sessionId == sessionId
|
||||||
&& i->first.peerId == peerId) {
|
&& i->first.peerId == peerId) {
|
||||||
const auto temp = base::take(i->second);
|
|
||||||
i = _notifications.erase(i);
|
i = _notifications.erase(i);
|
||||||
|
|
||||||
for (const auto &[msgId, notification] : temp) {
|
|
||||||
v::match(notification, [&](const std::string ¬ification) {
|
|
||||||
_application.withdraw_notification(notification);
|
|
||||||
}, [&](const Notification ¬ification) {
|
|
||||||
_interface.call_close_notification(notification->id, nullptr);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -898,16 +839,7 @@ void Manager::Private::clearFromSession(not_null<Main::Session*> session) {
|
||||||
.sessionId = sessionId,
|
.sessionId = sessionId,
|
||||||
});
|
});
|
||||||
while (i != _notifications.cend() && i->first.sessionId == sessionId) {
|
while (i != _notifications.cend() && i->first.sessionId == sessionId) {
|
||||||
const auto temp = base::take(i->second);
|
|
||||||
i = _notifications.erase(i);
|
i = _notifications.erase(i);
|
||||||
|
|
||||||
for (const auto &[msgId, notification] : temp) {
|
|
||||||
v::match(notification, [&](const std::string ¬ification) {
|
|
||||||
_application.withdraw_notification(notification);
|
|
||||||
}, [&](const Notification ¬ification) {
|
|
||||||
_interface.call_close_notification(notification->id, nullptr);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -926,10 +858,6 @@ void Manager::Private::invokeIfNotInhibited(Fn<void()> callback) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager::Private::~Private() {
|
|
||||||
clearAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
Manager::Manager(not_null<Window::Notifications::System*> system)
|
Manager::Manager(not_null<Window::Notifications::System*> system)
|
||||||
: NativeManager(system)
|
: NativeManager(system)
|
||||||
, _private(std::make_unique<Private>(this)) {
|
, _private(std::make_unique<Private>(this)) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue