mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Make notification manager creation async
This commit is contained in:
parent
a0a71687e7
commit
e8edbb16ae
10 changed files with 152 additions and 82 deletions
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
#include "main/main_domain.h"
|
#include "main/main_domain.h"
|
||||||
#include "window/notifications_manager.h"
|
#include "window/notifications_manager.h"
|
||||||
|
#include "platform/linux/specific_linux.h"
|
||||||
|
|
||||||
#include <QtDBus/QDBusConnection>
|
#include <QtDBus/QDBusConnection>
|
||||||
|
|
||||||
|
@ -22,10 +23,16 @@ NotificationServiceWatcher::NotificationServiceWatcher()
|
||||||
QDBusConnection::sessionBus(),
|
QDBusConnection::sessionBus(),
|
||||||
QDBusServiceWatcher::WatchForOwnerChange) {
|
QDBusServiceWatcher::WatchForOwnerChange) {
|
||||||
const auto signal = &QDBusServiceWatcher::serviceOwnerChanged;
|
const auto signal = &QDBusServiceWatcher::serviceOwnerChanged;
|
||||||
QObject::connect(&_dbusWatcher, signal, [=] {
|
QObject::connect(&_dbusWatcher, signal, [=](
|
||||||
|
const QString &service,
|
||||||
|
const QString &oldOwner,
|
||||||
|
const QString &newOwner) {
|
||||||
crl::on_main([=] {
|
crl::on_main([=] {
|
||||||
if (!Core::App().domain().started()) {
|
if (!Core::App().domain().started()) {
|
||||||
return;
|
return;
|
||||||
|
} else if (IsNotificationServiceActivatable()
|
||||||
|
&& newOwner.isEmpty()) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::App().notifications().createManager();
|
Core::App().notifications().createManager();
|
||||||
|
|
|
@ -21,6 +21,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include <QtDBus/QDBusConnection>
|
#include <QtDBus/QDBusConnection>
|
||||||
#include <QtDBus/QDBusConnectionInterface>
|
#include <QtDBus/QDBusConnectionInterface>
|
||||||
#include <QtDBus/QDBusMessage>
|
#include <QtDBus/QDBusMessage>
|
||||||
|
#include <QtDBus/QDBusPendingCall>
|
||||||
|
#include <QtDBus/QDBusPendingCallWatcher>
|
||||||
#include <QtDBus/QDBusPendingReply>
|
#include <QtDBus/QDBusPendingReply>
|
||||||
#include <QtDBus/QDBusReply>
|
#include <QtDBus/QDBusReply>
|
||||||
#include <QtDBus/QDBusError>
|
#include <QtDBus/QDBusError>
|
||||||
|
@ -64,7 +66,7 @@ bool GetServiceRegistered() {
|
||||||
: activatable;
|
: activatable;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ServerInformation> GetServerInformation() {
|
void GetServerInformation(Fn<void(std::optional<ServerInformation>)> callback) {
|
||||||
using ServerInformationReply = QDBusPendingReply<
|
using ServerInformationReply = QDBusPendingReply<
|
||||||
QString,
|
QString,
|
||||||
QString,
|
QString,
|
||||||
|
@ -77,59 +79,63 @@ std::optional<ServerInformation> GetServerInformation() {
|
||||||
kInterface.utf16(),
|
kInterface.utf16(),
|
||||||
qsl("GetServerInformation"));
|
qsl("GetServerInformation"));
|
||||||
|
|
||||||
// We may be launched earlier than notification daemon
|
const auto async = QDBusConnection::sessionBus().asyncCall(message);
|
||||||
while (true) {
|
auto watcher = new QDBusPendingCallWatcher(async);
|
||||||
ServerInformationReply reply = QDBusConnection::sessionBus()
|
|
||||||
.asyncCall(message);
|
|
||||||
|
|
||||||
reply.waitForFinished();
|
const auto finished = [=](QDBusPendingCallWatcher *call) {
|
||||||
|
const ServerInformationReply reply = *call;
|
||||||
|
|
||||||
if (reply.isValid()) {
|
if (reply.isValid()) {
|
||||||
return {
|
crl::on_main([=] {
|
||||||
reply.argumentAt<0>(),
|
callback(ServerInformation{
|
||||||
reply.argumentAt<1>(),
|
reply.argumentAt<0>(),
|
||||||
QVersionNumber::fromString(reply.argumentAt<2>()),
|
reply.argumentAt<1>(),
|
||||||
QVersionNumber::fromString(reply.argumentAt<3>()),
|
QVersionNumber::fromString(reply.argumentAt<2>()),
|
||||||
};
|
QVersionNumber::fromString(reply.argumentAt<3>()),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
LOG(("Native notification error: %1").arg(
|
||||||
|
reply.error().message()));
|
||||||
|
|
||||||
|
crl::on_main([=] { callback(std::nullopt); });
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(("Native notification error: %1").arg(reply.error().message()));
|
call->deleteLater();
|
||||||
|
};
|
||||||
|
|
||||||
if (reply.error().type() != QDBusError::NoReply) {
|
QObject::connect(watcher, &QDBusPendingCallWatcher::finished, finished);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList GetCapabilities() {
|
void GetCapabilities(Fn<void(QStringList)> callback) {
|
||||||
const auto message = QDBusMessage::createMethodCall(
|
const auto message = QDBusMessage::createMethodCall(
|
||||||
kService.utf16(),
|
kService.utf16(),
|
||||||
kObjectPath.utf16(),
|
kObjectPath.utf16(),
|
||||||
kInterface.utf16(),
|
kInterface.utf16(),
|
||||||
qsl("GetCapabilities"));
|
qsl("GetCapabilities"));
|
||||||
|
|
||||||
// We may be launched earlier than notification daemon
|
const auto async = QDBusConnection::sessionBus().asyncCall(message);
|
||||||
while (true) {
|
auto watcher = new QDBusPendingCallWatcher(async);
|
||||||
const QDBusReply<QStringList> reply = QDBusConnection::sessionBus()
|
|
||||||
.call(message);
|
const auto finished = [=](QDBusPendingCallWatcher *call) {
|
||||||
|
const QDBusPendingReply<QStringList> reply = *call;
|
||||||
|
|
||||||
if (reply.isValid()) {
|
if (reply.isValid()) {
|
||||||
return reply.value();
|
crl::on_main([=] { callback(reply.value()); });
|
||||||
|
} else {
|
||||||
|
LOG(("Native notification error: %1").arg(
|
||||||
|
reply.error().message()));
|
||||||
|
|
||||||
|
crl::on_main([=] { callback({}); });
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(("Native notification error: %1").arg(reply.error().message()));
|
call->deleteLater();
|
||||||
|
};
|
||||||
|
|
||||||
if (reply.error().type() != QDBusError::NoReply) {
|
QObject::connect(watcher, &QDBusPendingCallWatcher::finished, finished);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetInhibitionSupported() {
|
void GetInhibitionSupported(Fn<void(bool)> callback) {
|
||||||
auto message = QDBusMessage::createMethodCall(
|
auto message = QDBusMessage::createMethodCall(
|
||||||
kService.utf16(),
|
kService.utf16(),
|
||||||
kObjectPath.utf16(),
|
kObjectPath.utf16(),
|
||||||
|
@ -141,24 +147,21 @@ bool GetInhibitionSupported() {
|
||||||
qsl("Inhibited")
|
qsl("Inhibited")
|
||||||
});
|
});
|
||||||
|
|
||||||
// We may be launched earlier than notification daemon
|
const auto async = QDBusConnection::sessionBus().asyncCall(message);
|
||||||
while (true) {
|
auto watcher = new QDBusPendingCallWatcher(async);
|
||||||
const QDBusError error = QDBusConnection::sessionBus().call(message);
|
|
||||||
|
|
||||||
if (!error.isValid()) {
|
const auto finished = [=](QDBusPendingCallWatcher *call) {
|
||||||
return true;
|
const auto error = QDBusPendingReply<QVariant>(*call).error();
|
||||||
} else if (error.type() == QDBusError::InvalidArgs) {
|
|
||||||
break;
|
if (error.isValid() && error.type() != QDBusError::InvalidArgs) {
|
||||||
|
LOG(("Native notification error: %1").arg(error.message()));
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(("Native notification error: %1").arg(error.message()));
|
crl::on_main([=] { callback(!error.isValid()); });
|
||||||
|
call->deleteLater();
|
||||||
|
};
|
||||||
|
|
||||||
if (error.type() != QDBusError::NoReply) {
|
QObject::connect(watcher, &QDBusPendingCallWatcher::finished, finished);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Inhibited() {
|
bool Inhibited() {
|
||||||
|
@ -681,26 +684,56 @@ bool Enforced() {
|
||||||
return IsQualifiedDaemon() || IsWayland();
|
return IsQualifiedDaemon() || IsWayland();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Window::Notifications::Manager> Create(
|
void Create(Window::Notifications::System *system) {
|
||||||
Window::Notifications::System *system) {
|
|
||||||
ServiceRegistered = GetServiceRegistered();
|
ServiceRegistered = GetServiceRegistered();
|
||||||
|
|
||||||
if (Supported()) {
|
const auto managerSetter = [=] {
|
||||||
CurrentServerInformation = GetServerInformation();
|
using ManagerType = Window::Notifications::ManagerType;
|
||||||
CurrentCapabilities = GetCapabilities();
|
if ((Core::App().settings().nativeNotifications() && Supported())
|
||||||
InhibitionSupported = GetInhibitionSupported();
|
|| Enforced()) {
|
||||||
|
if (*system->managerType() != ManagerType::Native) {
|
||||||
|
system->setManager(std::make_unique<Manager>(system));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (*system->managerType() != ManagerType::Default) {
|
||||||
|
system->setManager(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!system->managerType().has_value()) {
|
||||||
|
using DummyManager = Window::Notifications::DummyManager;
|
||||||
|
system->setManager(std::make_unique<DummyManager>(system));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ServiceRegistered) {
|
||||||
|
const auto counter = std::make_shared<int>(3);
|
||||||
|
const auto oneReady = [=] {
|
||||||
|
if (!--*counter) {
|
||||||
|
managerSetter();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
GetServerInformation([=](std::optional<ServerInformation> result) {
|
||||||
|
CurrentServerInformation = result;
|
||||||
|
oneReady();
|
||||||
|
});
|
||||||
|
|
||||||
|
GetCapabilities([=](QStringList result) {
|
||||||
|
CurrentCapabilities = result;
|
||||||
|
oneReady();
|
||||||
|
});
|
||||||
|
|
||||||
|
GetInhibitionSupported([=](bool result) {
|
||||||
|
InhibitionSupported = result;
|
||||||
|
oneReady();
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
CurrentServerInformation = std::nullopt;
|
CurrentServerInformation = std::nullopt;
|
||||||
CurrentCapabilities = QStringList{};
|
CurrentCapabilities = QStringList{};
|
||||||
InhibitionSupported = false;
|
InhibitionSupported = false;
|
||||||
|
managerSetter();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((Core::App().settings().nativeNotifications() && Supported())
|
|
||||||
|| Enforced()) {
|
|
||||||
return std::make_unique<Manager>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Manager::Private {
|
class Manager::Private {
|
||||||
|
|
|
@ -33,13 +33,13 @@ bool Enforced() {
|
||||||
return IsWayland();
|
return IsWayland();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Window::Notifications::Manager> Create(
|
void Create(Window::Notifications::System *system) {
|
||||||
Window::Notifications::System *system) {
|
|
||||||
if (Enforced()) {
|
if (Enforced()) {
|
||||||
return std::make_unique<Window::Notifications::DummyManager>(system);
|
using DummyManager = Window::Notifications::DummyManager;
|
||||||
|
system->setManager(std::make_unique<DummyManager>(system));
|
||||||
|
} else {
|
||||||
|
system->setManager(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Notifications
|
} // namespace Notifications
|
||||||
|
|
|
@ -1247,18 +1247,13 @@ void start() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||||
if (!IsNotificationServiceActivatable()) {
|
NSWInstance = std::make_unique<internal::NotificationServiceWatcher>();
|
||||||
NSWInstance = std::make_unique<
|
|
||||||
internal::NotificationServiceWatcher>();
|
|
||||||
}
|
|
||||||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||||
}
|
}
|
||||||
|
|
||||||
void finish() {
|
void finish() {
|
||||||
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||||
if (NSWInstance) {
|
NSWInstance = nullptr;
|
||||||
NSWInstance = nullptr;
|
|
||||||
}
|
|
||||||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -166,11 +166,12 @@ bool Enforced() {
|
||||||
return Supported();
|
return Supported();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Window::Notifications::Manager> Create(Window::Notifications::System *system) {
|
void Create(Window::Notifications::System *system) {
|
||||||
if (Supported()) {
|
if (Supported()) {
|
||||||
return std::make_unique<Manager>(system);
|
system->setManager(std::make_unique<Manager>(system));
|
||||||
|
} else {
|
||||||
|
system->setManager(nullptr);
|
||||||
}
|
}
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Manager::Private : public QObject, private base::Subscriber {
|
class Manager::Private : public QObject, private base::Subscriber {
|
||||||
|
|
|
@ -18,8 +18,7 @@ namespace Notifications {
|
||||||
|
|
||||||
[[nodiscard]] bool Supported();
|
[[nodiscard]] bool Supported();
|
||||||
[[nodiscard]] bool Enforced();
|
[[nodiscard]] bool Enforced();
|
||||||
[[nodiscard]] std::unique_ptr<Window::Notifications::Manager> Create(
|
void Create(Window::Notifications::System *system);
|
||||||
Window::Notifications::System *system);
|
|
||||||
|
|
||||||
} // namespace Notifications
|
} // namespace Notifications
|
||||||
} // namespace Platform
|
} // namespace Platform
|
||||||
|
|
|
@ -329,16 +329,17 @@ bool Enforced() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Window::Notifications::Manager> Create(Window::Notifications::System *system) {
|
void Create(Window::Notifications::System *system) {
|
||||||
#ifndef __MINGW32__
|
#ifndef __MINGW32__
|
||||||
if (Core::App().settings().nativeNotifications() && Supported()) {
|
if (Core::App().settings().nativeNotifications() && Supported()) {
|
||||||
auto result = std::make_unique<Manager>(system);
|
auto result = std::make_unique<Manager>(system);
|
||||||
if (result->init()) {
|
if (result->init()) {
|
||||||
return std::move(result);
|
system->setManager(std::move(result));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // !__MINGW32__
|
#endif // !__MINGW32__
|
||||||
return nullptr;
|
system->setManager(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __MINGW32__
|
#ifndef __MINGW32__
|
||||||
|
|
|
@ -66,12 +66,23 @@ System::System()
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::createManager() {
|
void System::createManager() {
|
||||||
_manager = Platform::Notifications::Create(this);
|
Platform::Notifications::Create(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void System::setManager(std::unique_ptr<Manager> manager) {
|
||||||
|
_manager = std::move(manager);
|
||||||
if (!_manager) {
|
if (!_manager) {
|
||||||
_manager = std::make_unique<Default::Manager>(this);
|
_manager = std::make_unique<Default::Manager>(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<ManagerType> System::managerType() const {
|
||||||
|
if (_manager) {
|
||||||
|
return _manager->type();
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
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()) {
|
||||||
|
|
|
@ -34,6 +34,12 @@ class Track;
|
||||||
namespace Window {
|
namespace Window {
|
||||||
namespace Notifications {
|
namespace Notifications {
|
||||||
|
|
||||||
|
enum class ManagerType {
|
||||||
|
Dummy,
|
||||||
|
Default,
|
||||||
|
Native,
|
||||||
|
};
|
||||||
|
|
||||||
enum class ChangeType {
|
enum class ChangeType {
|
||||||
SoundEnabled,
|
SoundEnabled,
|
||||||
FlashBounceEnabled,
|
FlashBounceEnabled,
|
||||||
|
@ -70,6 +76,8 @@ public:
|
||||||
[[nodiscard]] Main::Session *findSession(uint64 sessionId) const;
|
[[nodiscard]] Main::Session *findSession(uint64 sessionId) const;
|
||||||
|
|
||||||
void createManager();
|
void createManager();
|
||||||
|
void setManager(std::unique_ptr<Manager> manager);
|
||||||
|
[[nodiscard]] std::optional<ManagerType> managerType() const;
|
||||||
|
|
||||||
void checkDelayed();
|
void checkDelayed();
|
||||||
void schedule(not_null<HistoryItem*> item);
|
void schedule(not_null<HistoryItem*> item);
|
||||||
|
@ -189,6 +197,8 @@ public:
|
||||||
const QString &title,
|
const QString &title,
|
||||||
not_null<Main::Session*> session);
|
not_null<Main::Session*> session);
|
||||||
|
|
||||||
|
[[nodiscard]] virtual ManagerType type() const = 0;
|
||||||
|
|
||||||
virtual ~Manager() = default;
|
virtual ~Manager() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -221,6 +231,11 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
class NativeManager : public Manager {
|
class NativeManager : public Manager {
|
||||||
|
public:
|
||||||
|
[[nodiscard]] ManagerType type() const override {
|
||||||
|
return ManagerType::Native;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
using Manager::Manager;
|
using Manager::Manager;
|
||||||
|
|
||||||
|
@ -252,6 +267,10 @@ class DummyManager : public NativeManager {
|
||||||
public:
|
public:
|
||||||
using NativeManager::NativeManager;
|
using NativeManager::NativeManager;
|
||||||
|
|
||||||
|
[[nodiscard]] ManagerType type() const override {
|
||||||
|
return ManagerType::Dummy;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void doShowNativeNotification(
|
void doShowNativeNotification(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
|
|
|
@ -43,6 +43,10 @@ public:
|
||||||
Manager(System *system);
|
Manager(System *system);
|
||||||
~Manager();
|
~Manager();
|
||||||
|
|
||||||
|
[[nodiscard]] ManagerType type() const override {
|
||||||
|
return ManagerType::Default;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Method>
|
template <typename Method>
|
||||||
void enumerateNotifications(Method method) {
|
void enumerateNotifications(Method method) {
|
||||||
for (const auto ¬ification : _notifications) {
|
for (const auto ¬ification : _notifications) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue