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