Skip to content

Commit

Permalink
Simplify GNotification actions
Browse files Browse the repository at this point in the history
  • Loading branch information
ilya-fedin committed Feb 18, 2025
1 parent 4950b52 commit de98f81
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 119 deletions.
54 changes: 1 addition & 53 deletions Telegram/SourceFiles/platform/linux/integration_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ For license and copyright information please follow this link:
#include "platform/platform_integration.h"
#include "base/platform/base_platform_info.h"
#include "base/platform/linux/base_linux_xdp_utilities.h"
#include "window/notifications_manager.h"
#include "core/sandbox.h"
#include "core/application.h"
#include "core/core_settings.h"
#include "base/random.h"

#include <QtCore/QAbstractEventDispatcher>
Expand All @@ -27,32 +25,6 @@ namespace {
using namespace gi::repository;
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 {
public:
Application();
Expand Down Expand Up @@ -125,42 +97,18 @@ Application::Application()
});
actionMap.add_action(quitAction);

using Window::Notifications::Manager;
using NotificationId = Manager::NotificationId;

const auto notificationIdVariantType = GLib::VariantType::new_("av");
const auto notificationIdVariantType = GLib::VariantType::new_("a{sv}");

auto notificationActivateAction = Gio::SimpleAction::new_(
"notification-activate",
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);

auto notificationMarkAsReadAction = Gio::SimpleAction::new_(
"notification-mark-as-read",
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);
}

Expand Down
108 changes: 79 additions & 29 deletions Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,32 +139,6 @@ bool UseGNotification() {
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 {
public:
using NotificationId = Window::Notifications::Manager::NotificationId;
Expand Down Expand Up @@ -212,6 +186,8 @@ class NotificationData final : public base::has_weak_ptr {
ulong _notificationRepliedSignalId = 0;
ulong _notificationClosedSignalId = 0;

rpl::lifetime _lifetime;

};

using Notification = std::unique_ptr<NotificationData>;
Expand All @@ -238,6 +214,57 @@ bool NotificationData::init(const Info &info) {
const auto &subtitle = info.subtitle;

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_(
subtitle.isEmpty()
? title.toStdString()
Expand All @@ -264,17 +291,40 @@ bool NotificationData::init(const Info &info) {
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(
"app.notification-activate",
idVariant);
notificationVariant);

if (!info.options.hideMarkAsRead) {
_notification.add_button_with_target(
tr::lng_context_mark_read(tr::now).toStdString(),
"app.notification-mark-as-read",
idVariant);
notificationVariant);
}

return true;
Expand Down
5 changes: 0 additions & 5 deletions Telegram/SourceFiles/window/notifications_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
for (const auto &[index, account] : Core::App().domain().accounts()) {
if (const auto session = account->maybeSession()) {
Expand Down
32 changes: 0 additions & 32 deletions Telegram/SourceFiles/window/notifications_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ class System final {

void createManager();
void setManager(Fn<std::unique_ptr<Manager>()> create);
[[nodiscard]] Manager &manager() const;

void checkDelayed();
void schedule(Data::ItemNotification notification);
Expand Down Expand Up @@ -237,22 +236,6 @@ class Manager {
friend inline auto operator<=>(
const ContextId&,
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 {
ContextId contextId;
Expand All @@ -261,21 +244,6 @@ class Manager {
friend inline auto operator<=>(
const NotificationId&,
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 {
not_null<HistoryItem*> item;
Expand Down

0 comments on commit de98f81

Please sign in to comment.