mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Simplify GNotification actions
This commit is contained in:
parent
2ab9587f5f
commit
cf61dedc79
4 changed files with 80 additions and 119 deletions
|
@ -10,10 +10,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "platform/platform_integration.h"
|
#include "platform/platform_integration.h"
|
||||||
#include "base/platform/base_platform_info.h"
|
#include "base/platform/base_platform_info.h"
|
||||||
#include "base/platform/linux/base_linux_xdp_utilities.h"
|
#include "base/platform/linux/base_linux_xdp_utilities.h"
|
||||||
#include "window/notifications_manager.h"
|
|
||||||
#include "core/sandbox.h"
|
#include "core/sandbox.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
#include "core/core_settings.h"
|
|
||||||
#include "base/random.h"
|
#include "base/random.h"
|
||||||
|
|
||||||
#include <QtCore/QAbstractEventDispatcher>
|
#include <QtCore/QAbstractEventDispatcher>
|
||||||
|
@ -27,32 +25,6 @@ namespace {
|
||||||
using namespace gi::repository;
|
using namespace gi::repository;
|
||||||
namespace GObject = gi::repository::GObject;
|
namespace GObject = gi::repository::GObject;
|
||||||
|
|
||||||
std::vector<std::any> AnyVectorFromVariant(GLib::Variant value) {
|
|
||||||
std::vector<std::any> result;
|
|
||||||
|
|
||||||
GLib::VariantIter iter;
|
|
||||||
iter.allocate_();
|
|
||||||
iter.init(value);
|
|
||||||
|
|
||||||
const auto uint64Type = GLib::VariantType::new_("t");
|
|
||||||
const auto int64Type = GLib::VariantType::new_("x");
|
|
||||||
|
|
||||||
while (auto value = iter.next_value()) {
|
|
||||||
value = value.get_variant();
|
|
||||||
if (value.is_of_type(uint64Type)) {
|
|
||||||
result.push_back(std::make_any<uint64>(value.get_uint64()));
|
|
||||||
} else if (value.is_of_type(int64Type)) {
|
|
||||||
result.push_back(std::make_any<int64>(value.get_int64()));
|
|
||||||
} else if (value.is_container()) {
|
|
||||||
result.push_back(
|
|
||||||
std::make_any<std::vector<std::any>>(
|
|
||||||
AnyVectorFromVariant(value)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Application : public Gio::impl::ApplicationImpl {
|
class Application : public Gio::impl::ApplicationImpl {
|
||||||
public:
|
public:
|
||||||
Application();
|
Application();
|
||||||
|
@ -125,42 +97,18 @@ Application::Application()
|
||||||
});
|
});
|
||||||
actionMap.add_action(quitAction);
|
actionMap.add_action(quitAction);
|
||||||
|
|
||||||
using Window::Notifications::Manager;
|
const auto notificationIdVariantType = GLib::VariantType::new_("a{sv}");
|
||||||
using NotificationId = Manager::NotificationId;
|
|
||||||
|
|
||||||
const auto notificationIdVariantType = GLib::VariantType::new_("av");
|
|
||||||
|
|
||||||
auto notificationActivateAction = Gio::SimpleAction::new_(
|
auto notificationActivateAction = Gio::SimpleAction::new_(
|
||||||
"notification-activate",
|
"notification-activate",
|
||||||
notificationIdVariantType);
|
notificationIdVariantType);
|
||||||
|
|
||||||
notificationActivateAction.signal_activate().connect([](
|
|
||||||
Gio::SimpleAction,
|
|
||||||
GLib::Variant parameter) {
|
|
||||||
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
|
||||||
Core::App().notifications().manager().notificationActivated(
|
|
||||||
NotificationId::FromAnyVector(
|
|
||||||
AnyVectorFromVariant(parameter)));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
actionMap.add_action(notificationActivateAction);
|
actionMap.add_action(notificationActivateAction);
|
||||||
|
|
||||||
auto notificationMarkAsReadAction = Gio::SimpleAction::new_(
|
auto notificationMarkAsReadAction = Gio::SimpleAction::new_(
|
||||||
"notification-mark-as-read",
|
"notification-mark-as-read",
|
||||||
notificationIdVariantType);
|
notificationIdVariantType);
|
||||||
|
|
||||||
notificationMarkAsReadAction.signal_activate().connect([](
|
|
||||||
Gio::SimpleAction,
|
|
||||||
GLib::Variant parameter) {
|
|
||||||
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
|
||||||
Core::App().notifications().manager().notificationReplied(
|
|
||||||
NotificationId::FromAnyVector(
|
|
||||||
AnyVectorFromVariant(parameter)),
|
|
||||||
{});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
actionMap.add_action(notificationMarkAsReadAction);
|
actionMap.add_action(notificationMarkAsReadAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -139,32 +139,6 @@ bool UseGNotification() {
|
||||||
return KSandbox::isFlatpak() && !ServiceRegistered;
|
return KSandbox::isFlatpak() && !ServiceRegistered;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLib::Variant AnyVectorToVariant(const std::vector<std::any> &value) {
|
|
||||||
return GLib::Variant::new_array(
|
|
||||||
value | ranges::views::transform([](const std::any &value) {
|
|
||||||
try {
|
|
||||||
return GLib::Variant::new_variant(
|
|
||||||
GLib::Variant::new_uint64(std::any_cast<uint64>(value)));
|
|
||||||
} catch (...) {
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return GLib::Variant::new_variant(
|
|
||||||
GLib::Variant::new_int64(std::any_cast<int64>(value)));
|
|
||||||
} catch (...) {
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return GLib::Variant::new_variant(
|
|
||||||
AnyVectorToVariant(
|
|
||||||
std::any_cast<std::vector<std::any>>(value)));
|
|
||||||
} catch (...) {
|
|
||||||
}
|
|
||||||
|
|
||||||
return GLib::Variant(nullptr);
|
|
||||||
}) | ranges::to_vector);
|
|
||||||
}
|
|
||||||
|
|
||||||
class NotificationData final : public base::has_weak_ptr {
|
class NotificationData final : public base::has_weak_ptr {
|
||||||
public:
|
public:
|
||||||
using NotificationId = Window::Notifications::Manager::NotificationId;
|
using NotificationId = Window::Notifications::Manager::NotificationId;
|
||||||
|
@ -212,6 +186,8 @@ private:
|
||||||
ulong _notificationRepliedSignalId = 0;
|
ulong _notificationRepliedSignalId = 0;
|
||||||
ulong _notificationClosedSignalId = 0;
|
ulong _notificationClosedSignalId = 0;
|
||||||
|
|
||||||
|
rpl::lifetime _lifetime;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using Notification = std::unique_ptr<NotificationData>;
|
using Notification = std::unique_ptr<NotificationData>;
|
||||||
|
@ -238,6 +214,57 @@ bool NotificationData::init(const Info &info) {
|
||||||
const auto &subtitle = info.subtitle;
|
const auto &subtitle = info.subtitle;
|
||||||
|
|
||||||
if (_application) {
|
if (_application) {
|
||||||
|
auto actionMap = Gio::ActionMap(_application);
|
||||||
|
|
||||||
|
const auto dictToNotificationId = [](GLib::VariantDict dict) {
|
||||||
|
using ContextId = Window::Notifications::Manager::ContextId;
|
||||||
|
return NotificationId{
|
||||||
|
.contextId = ContextId{
|
||||||
|
.sessionId = dict.lookup_value("session").get_uint64(),
|
||||||
|
.peerId = PeerId(dict.lookup_value("peer").get_uint64()),
|
||||||
|
.topicRootId = dict.lookup_value("topic").get_int64(),
|
||||||
|
},
|
||||||
|
.msgId = dict.lookup_value("msgid").get_int64(),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
auto activate = gi::wrap(
|
||||||
|
G_SIMPLE_ACTION(
|
||||||
|
actionMap.lookup_action("notification-activate").gobj_()),
|
||||||
|
gi::transfer_none);
|
||||||
|
|
||||||
|
const auto activateSig = activate.signal_activate().connect([=](
|
||||||
|
Gio::SimpleAction,
|
||||||
|
GLib::Variant parameter) {
|
||||||
|
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
||||||
|
_manager->notificationActivated(
|
||||||
|
dictToNotificationId(GLib::VariantDict::new_(parameter)));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
_lifetime.add([=]() mutable {
|
||||||
|
activate.disconnect(activateSig);
|
||||||
|
});
|
||||||
|
|
||||||
|
auto markAsRead = gi::wrap(
|
||||||
|
G_SIMPLE_ACTION(
|
||||||
|
actionMap.lookup_action("notification-mark-as-read").gobj_()),
|
||||||
|
gi::transfer_none);
|
||||||
|
|
||||||
|
const auto markAsReadSig = markAsRead.signal_activate().connect([=](
|
||||||
|
Gio::SimpleAction,
|
||||||
|
GLib::Variant parameter) {
|
||||||
|
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
|
||||||
|
_manager->notificationReplied(
|
||||||
|
dictToNotificationId(GLib::VariantDict::new_(parameter)),
|
||||||
|
{});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
_lifetime.add([=]() mutable {
|
||||||
|
markAsRead.disconnect(markAsReadSig);
|
||||||
|
});
|
||||||
|
|
||||||
_notification = Gio::Notification::new_(
|
_notification = Gio::Notification::new_(
|
||||||
subtitle.isEmpty()
|
subtitle.isEmpty()
|
||||||
? title.toStdString()
|
? title.toStdString()
|
||||||
|
@ -264,17 +291,40 @@ bool NotificationData::init(const Info &info) {
|
||||||
set_category(_notification.gobj_(), "im.received");
|
set_category(_notification.gobj_(), "im.received");
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto idVariant = AnyVectorToVariant(_id.toAnyVector());
|
const auto peer = info.peer;
|
||||||
|
|
||||||
|
const auto notificationVariant = GLib::Variant::new_array({
|
||||||
|
GLib::Variant::new_dict_entry(
|
||||||
|
GLib::Variant::new_string("session"),
|
||||||
|
GLib::Variant::new_variant(
|
||||||
|
GLib::Variant::new_uint64(peer->session().uniqueId()))),
|
||||||
|
GLib::Variant::new_dict_entry(
|
||||||
|
GLib::Variant::new_string("peer"),
|
||||||
|
GLib::Variant::new_variant(
|
||||||
|
GLib::Variant::new_uint64(peer->id.value))),
|
||||||
|
GLib::Variant::new_dict_entry(
|
||||||
|
GLib::Variant::new_string("peer"),
|
||||||
|
GLib::Variant::new_variant(
|
||||||
|
GLib::Variant::new_uint64(peer->id.value))),
|
||||||
|
GLib::Variant::new_dict_entry(
|
||||||
|
GLib::Variant::new_string("topic"),
|
||||||
|
GLib::Variant::new_variant(
|
||||||
|
GLib::Variant::new_int64(info.topicRootId.bare))),
|
||||||
|
GLib::Variant::new_dict_entry(
|
||||||
|
GLib::Variant::new_string("msgid"),
|
||||||
|
GLib::Variant::new_variant(
|
||||||
|
GLib::Variant::new_int64(info.itemId.bare))),
|
||||||
|
});
|
||||||
|
|
||||||
_notification.set_default_action_and_target(
|
_notification.set_default_action_and_target(
|
||||||
"app.notification-activate",
|
"app.notification-activate",
|
||||||
idVariant);
|
notificationVariant);
|
||||||
|
|
||||||
if (!info.options.hideMarkAsRead) {
|
if (!info.options.hideMarkAsRead) {
|
||||||
_notification.add_button_with_target(
|
_notification.add_button_with_target(
|
||||||
tr::lng_context_mark_read(tr::now).toStdString(),
|
tr::lng_context_mark_read(tr::now).toStdString(),
|
||||||
"app.notification-mark-as-read",
|
"app.notification-mark-as-read",
|
||||||
idVariant);
|
notificationVariant);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -212,11 +212,6 @@ void System::setManager(Fn<std::unique_ptr<Manager>()> create) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager &System::manager() const {
|
|
||||||
Expects(_manager != nullptr);
|
|
||||||
return *_manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
Main::Session *System::findSession(uint64 sessionId) const {
|
Main::Session *System::findSession(uint64 sessionId) const {
|
||||||
for (const auto &[index, account] : Core::App().domain().accounts()) {
|
for (const auto &[index, account] : Core::App().domain().accounts()) {
|
||||||
if (const auto session = account->maybeSession()) {
|
if (const auto session = account->maybeSession()) {
|
||||||
|
|
|
@ -100,7 +100,6 @@ public:
|
||||||
|
|
||||||
void createManager();
|
void createManager();
|
||||||
void setManager(Fn<std::unique_ptr<Manager>()> create);
|
void setManager(Fn<std::unique_ptr<Manager>()> create);
|
||||||
[[nodiscard]] Manager &manager() const;
|
|
||||||
|
|
||||||
void checkDelayed();
|
void checkDelayed();
|
||||||
void schedule(Data::ItemNotification notification);
|
void schedule(Data::ItemNotification notification);
|
||||||
|
@ -237,22 +236,6 @@ public:
|
||||||
friend inline auto operator<=>(
|
friend inline auto operator<=>(
|
||||||
const ContextId&,
|
const ContextId&,
|
||||||
const ContextId&) = default;
|
const ContextId&) = default;
|
||||||
|
|
||||||
[[nodiscard]] auto toAnyVector() const {
|
|
||||||
return std::vector<std::any>{
|
|
||||||
std::make_any<uint64>(sessionId),
|
|
||||||
std::make_any<uint64>(peerId.value),
|
|
||||||
std::make_any<int64>(topicRootId.bare),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] static auto FromAnyVector(const auto &vector) {
|
|
||||||
return ContextId{
|
|
||||||
std::any_cast<uint64>(vector[0]),
|
|
||||||
PeerIdHelper(std::any_cast<uint64>(vector[1])),
|
|
||||||
std::any_cast<int64>(vector[2]),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
struct NotificationId {
|
struct NotificationId {
|
||||||
ContextId contextId;
|
ContextId contextId;
|
||||||
|
@ -261,21 +244,6 @@ public:
|
||||||
friend inline auto operator<=>(
|
friend inline auto operator<=>(
|
||||||
const NotificationId&,
|
const NotificationId&,
|
||||||
const NotificationId&) = default;
|
const NotificationId&) = default;
|
||||||
|
|
||||||
[[nodiscard]] auto toAnyVector() const {
|
|
||||||
return std::vector<std::any>{
|
|
||||||
std::make_any<std::vector<std::any>>(contextId.toAnyVector()),
|
|
||||||
std::make_any<int64>(msgId.bare),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] static auto FromAnyVector(const auto &vector) {
|
|
||||||
return NotificationId{
|
|
||||||
ContextId::FromAnyVector(
|
|
||||||
std::any_cast<std::vector<std::any>>(vector[0])),
|
|
||||||
std::any_cast<int64>(vector[1]),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
struct NotificationFields {
|
struct NotificationFields {
|
||||||
not_null<HistoryItem*> item;
|
not_null<HistoryItem*> item;
|
||||||
|
|
Loading…
Add table
Reference in a new issue