diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index ecd15172c5..e35e753e87 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -268,7 +268,6 @@ void MainWindow::psSetupTrayIcon() { psUpdateCounter(); trayIcon->show(); - psUpdateDelegate(); } } @@ -430,9 +429,6 @@ void MainWindow::LibsLoaded() { #endif // TDESKTOP_DISABLE_UNITY_INTEGRATION } -void MainWindow::psUpdateDelegate() { -} - void MainWindow::psInitSize() { setMinimumWidth(st::wndMinWidth); setMinimumHeight(st::wndMinHeight); diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.h b/Telegram/SourceFiles/platform/linux/main_window_linux.h index 739063177f..a7cee027e7 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.h +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.h @@ -69,8 +69,6 @@ public: ~MainWindow(); public slots: - - void psUpdateDelegate(); void psSavePosition(Qt::WindowState state = Qt::WindowActive); void psShowTrayMenu(); diff --git a/Telegram/SourceFiles/platform/mac/main_window_mac.h b/Telegram/SourceFiles/platform/mac/main_window_mac.h index 434cb93ed8..ddbd582a71 100644 --- a/Telegram/SourceFiles/platform/mac/main_window_mac.h +++ b/Telegram/SourceFiles/platform/mac/main_window_mac.h @@ -27,11 +27,8 @@ namespace Platform { class MacPrivate : public PsMacWindowPrivate { public: - void activeSpaceChanged(); void darkModeChanged(); - void notifyClicked(unsigned long long peer, int msgid); - void notifyReplied(unsigned long long peer, int msgid, const char *str); }; @@ -83,7 +80,6 @@ public: ~MainWindow(); public slots: - void psUpdateDelegate(); void psSavePosition(Qt::WindowState state = Qt::WindowActive); void psShowTrayMenu(); diff --git a/Telegram/SourceFiles/platform/mac/main_window_mac.mm b/Telegram/SourceFiles/platform/mac/main_window_mac.mm index 08fa8495b6..ddf50c9066 100644 --- a/Telegram/SourceFiles/platform/mac/main_window_mac.mm +++ b/Telegram/SourceFiles/platform/mac/main_window_mac.mm @@ -25,6 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "historywidget.h" #include "localstorage.h" #include "window/notifications_manager_default.h" +#include "platform/mac/notifications_manager_mac.h" #include "lang.h" @@ -48,38 +49,6 @@ void MacPrivate::darkModeChanged() { Notify::unreadCounterUpdated(); } -void MacPrivate::notifyClicked(unsigned long long peer, int msgid) { - History *history = App::history(PeerId(peer)); - - App::wnd()->showFromTray(); - if (App::passcoded()) { - App::wnd()->setInnerFocus(); - App::wnd()->notifyClear(); - } else { - bool tomsg = !history->peer->isUser() && (msgid > 0); - if (tomsg) { - HistoryItem *item = App::histItemById(peerToChannel(PeerId(peer)), MsgId(msgid)); - if (!item || !item->mentionsMe()) { - tomsg = false; - } - } - Ui::showPeerHistory(history, tomsg ? msgid : ShowAtUnreadMsgId); - App::wnd()->notifyClear(history); - } -} - -void MacPrivate::notifyReplied(unsigned long long peer, int msgid, const char *str) { - History *history = App::history(PeerId(peer)); - - MainWidget::MessageToSend message; - message.history = history; - message.textWithTags = { QString::fromUtf8(str), TextWithTags::Tags() }; - message.replyTo = (msgid > 0 && !history->peer->isUser()) ? msgid : 0; - message.silent = false; - message.clearDraft = false; - App::main()->sendMessage(message); -} - MainWindow::MainWindow() : posInited(false) , icon256(qsl(":/gui/art/icon256.png")) @@ -151,10 +120,12 @@ void MainWindow::psUpdateWorkmode() { if (trayIcon) { trayIcon->setContextMenu(0); delete trayIcon; + trayIcon = nullptr; } - trayIcon = 0; } - psUpdateDelegate(); + if (auto manager = Platform::Notifications::manager()) { + manager->updateDelegate(); + } setWindowIcon(wndIcon); } @@ -220,10 +191,6 @@ void MainWindow::psUpdateCounter() { } } -void MainWindow::psUpdateDelegate() { - _private.updateDelegate(); -} - void MainWindow::psInitSize() { setMinimumWidth(st::wndMinWidth); setMinimumHeight(st::wndMinHeight); diff --git a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.h b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.h index 2ea20da9ef..bb466f1b8a 100644 --- a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.h +++ b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.h @@ -25,8 +25,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace Platform { namespace Notifications { +class Manager; + void start(); -Window::Notifications::Manager *manager(); +Manager *manager(); void finish(); void defaultNotificationShown(QWidget *widget); @@ -34,6 +36,9 @@ void defaultNotificationShown(QWidget *widget); class Manager : public Window::Notifications::NativeManager { public: Manager(); + + void updateDelegate(); + ~Manager(); protected: diff --git a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm index d6dcb90ecb..831fce549f 100644 --- a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm +++ b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm @@ -26,15 +26,72 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include +namespace { + +NeverFreedPointer ManagerInstance; + +} // namespace + NSImage *qt_mac_create_nsimage(const QPixmap &pm); +@interface NotificationDelegate : NSObject { +} + +- (id) init; +- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification; +- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification; + +@end + +@implementation NotificationDelegate { +} + +- (id) init { + if (self = [super init]) { + } + return self; +} + +- (void) userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification { + auto manager = ManagerInstance.data(); + if (!manager) { + return; + } + + NSDictionary *notificationUserInfo = [notification userInfo]; + NSNumber *launchIdObject = [notificationUserInfo objectForKey:@"launch"]; + auto notificationLaunchId = launchIdObject ? [launchIdObject unsignedLongLongValue] : 0ULL; + DEBUG_LOG(("Received notification with instance %1").arg(notificationLaunchId)); + if (notificationLaunchId != Global::LaunchId()) { // other app instance notification + return; + } + + NSNumber *peerObject = [notificationUserInfo objectForKey:@"peer"]; + auto notificationPeerId = peerObject ? [peerObject unsignedLongLongValue] : 0ULL; + if (!notificationPeerId) { + return; + } + + NSNumber *msgObject = [notificationUserInfo objectForKey:@"msgid"]; + auto notificationMsgId = msgObject ? [msgObject intValue] : 0; + if (notification.activationType == NSUserNotificationActivationTypeReplied) { + auto notificationReply = QString::fromUtf8([[[notification response] string] UTF8String]); + manager->notificationReplied(notificationPeerId, notificationMsgId, notificationReply); + } else if (notification.activationType == NSUserNotificationActivationTypeContentsClicked) { + manager->notificationActivated(notificationPeerId, notificationMsgId); + } + + [center removeDeliveredNotification: notification]; +} + +- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification { + return YES; +} + +@end + namespace Platform { namespace Notifications { -namespace { - -NeverFreedPointer ManagerInstance; - -} // namespace void start() { if (cPlatform() != dbipMacOld) { @@ -42,7 +99,7 @@ void start() { } } -Window::Notifications::Manager *manager() { +Manager *manager() { return ManagerInstance.data(); } @@ -59,16 +116,22 @@ void defaultNotificationShown(QWidget *widget) { class Manager::Impl { public: + Impl(); void showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton); void clearAll(); void clearFromHistory(History *history); + void updateDelegate(); ~Impl(); private: + NotificationDelegate *_delegate; }; +Manager::Impl::Impl() : _delegate([[NotificationDelegate alloc] init]) { +} + void Manager::Impl::showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton) { @autoreleasepool { @@ -104,11 +167,12 @@ void Manager::Impl::showNotification(PeerData *peer, MsgId msgId, const QString void Manager::Impl::clearAll() { NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; NSArray *notificationsList = [center deliveredNotifications]; - for (id notify in notificationsList) { - NSDictionary *notifyUserInfo = [notify userInfo]; - auto notifyLaunchId = [[notifyUserInfo objectForKey:@"launch"] unsignedLongLongValue]; - if (notifyLaunchId == Global::LaunchId()) { - [center removeDeliveredNotification:notify]; + for (id notification in notificationsList) { + NSDictionary *notificationUserInfo = [notification userInfo]; + NSNumber *launchIdObject = [notificationUserInfo objectForKey:@"launch"]; + auto notificationLaunchId = launchIdObject ? [launchIdObject unsignedLongLongValue] : 0ULL; + if (notificationLaunchId == Global::LaunchId()) { + [center removeDeliveredNotification:notification]; } } [center removeAllDeliveredNotifications]; @@ -119,22 +183,34 @@ void Manager::Impl::clearFromHistory(History *history) { NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; NSArray *notificationsList = [center deliveredNotifications]; - for (id notify in notificationsList) { - NSDictionary *notifyUserInfo = [notify userInfo]; - auto notifyPeerId = [[notifyUserInfo objectForKey:@"peer"] unsignedLongLongValue]; - auto notifyLaunchId = [[notifyUserInfo objectForKey:@"launch"] unsignedLongLongValue]; - if (notifyPeerId == peerId && notifyLaunchId == Global::LaunchId()) { - [center removeDeliveredNotification:notify]; + for (id notification in notificationsList) { + NSDictionary *notificationUserInfo = [notification userInfo]; + NSNumber *launchIdObject = [notificationUserInfo objectForKey:@"launch"]; + NSNumber *peerObject = [notificationUserInfo objectForKey:@"peer"]; + auto notificationLaunchId = launchIdObject ? [launchIdObject unsignedLongLongValue] : 0ULL; + auto notificationPeerId = peerObject ? [peerObject unsignedLongLongValue] : 0ULL; + if (notificationPeerId == peerId && notificationLaunchId == Global::LaunchId()) { + [center removeDeliveredNotification:notification]; } } } +void Manager::Impl::updateDelegate() { + NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; + [center setDelegate:_delegate]; +} + Manager::Impl::~Impl() { + [_delegate release]; } Manager::Manager() : _impl(std_::make_unique()) { } +void Manager::updateDelegate() { + _impl->updateDelegate(); +} + Manager::~Manager() = default; void Manager::doShowNativeNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton) { diff --git a/Telegram/SourceFiles/platform/win/main_window_win.cpp b/Telegram/SourceFiles/platform/win/main_window_win.cpp index 407c49881a..7294ef2beb 100644 --- a/Telegram/SourceFiles/platform/win/main_window_win.cpp +++ b/Telegram/SourceFiles/platform/win/main_window_win.cpp @@ -674,7 +674,6 @@ void MainWindow::psSetupTrayIcon() { psUpdateCounter(); trayIcon->show(); - psUpdateDelegate(); } void MainWindow::psUpdateWorkmode() { @@ -745,9 +744,6 @@ void MainWindow::psUpdateCounter() { SetWindowPos(ps_hWnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); } -void MainWindow::psUpdateDelegate() { -} - namespace { HMONITOR enumMonitor = 0; RECT enumMonitorWork; diff --git a/Telegram/SourceFiles/platform/win/main_window_win.h b/Telegram/SourceFiles/platform/win/main_window_win.h index cd16f71d6d..20713abe45 100644 --- a/Telegram/SourceFiles/platform/win/main_window_win.h +++ b/Telegram/SourceFiles/platform/win/main_window_win.h @@ -99,7 +99,6 @@ public: ~MainWindow(); public slots: - void psUpdateDelegate(); void psSavePosition(Qt::WindowState state = Qt::WindowActive); void psShowTrayMenu(); diff --git a/Telegram/SourceFiles/pspecific_mac_p.h b/Telegram/SourceFiles/pspecific_mac_p.h index b186e28c19..5a613ceeae 100644 --- a/Telegram/SourceFiles/pspecific_mac_p.h +++ b/Telegram/SourceFiles/pspecific_mac_p.h @@ -21,14 +21,11 @@ class PsMacWindowData; class PsMacWindowPrivate { public: - PsMacWindowPrivate(); void setWindowBadge(const QString &str); void startBounce(); - void updateDelegate(); - void enableShadow(WId winId); bool filterNativeEvent(void *event); @@ -37,10 +34,6 @@ public: } virtual void darkModeChanged() { } - virtual void notifyClicked(unsigned long long peer, int msgid) { - } - virtual void notifyReplied(unsigned long long peer, int msgid, const char *str) { - } ~PsMacWindowPrivate(); diff --git a/Telegram/SourceFiles/pspecific_mac_p.mm b/Telegram/SourceFiles/pspecific_mac_p.mm index eb358b0cf6..7f193d93b2 100644 --- a/Telegram/SourceFiles/pspecific_mac_p.mm +++ b/Telegram/SourceFiles/pspecific_mac_p.mm @@ -120,50 +120,20 @@ ApplicationDelegate *_sharedDelegate = nil; @end -@interface NotifyHandler : NSObject { -} - -- (id) init:(PsMacWindowPrivate *)aWnd; - -- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification; - -- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification; - -@end - class PsMacWindowData { public: - PsMacWindowData(PsMacWindowPrivate *wnd) : wnd(wnd), - observerHelper([[ObserverHelper alloc] init:wnd]), - notifyHandler([[NotifyHandler alloc] init:wnd]) { - } - - void onNotifyClick(NSUserNotification *notification) { - NSDictionary *dict = [notification userInfo]; - NSNumber *peerObj = [dict objectForKey:@"peer"], *msgObj = [dict objectForKey:@"msgid"]; - unsigned long long peerLong = peerObj ? [peerObj unsignedLongLongValue] : 0; - int msgId = msgObj ? [msgObj intValue] : 0; - wnd->notifyClicked(peerLong, msgId); - } - - void onNotifyReply(NSUserNotification *notification) { - NSDictionary *dict = [notification userInfo]; - NSNumber *peerObj = [dict objectForKey:@"peer"], *msgObj = [dict objectForKey:@"msgid"]; - unsigned long long peerLong = peerObj ? [peerObj unsignedLongLongValue] : 0; - int msgId = msgObj ? [msgObj intValue] : 0; - wnd->notifyReplied(peerLong, msgId, [[[notification response] string] UTF8String]); + observerHelper([[ObserverHelper alloc] init:wnd]) { } ~PsMacWindowData() { [observerHelper release]; - [notifyHandler release]; } PsMacWindowPrivate *wnd; ObserverHelper *observerHelper; - NotifyHandler *notifyHandler; + }; @implementation ObserverHelper { @@ -195,38 +165,6 @@ public: @end -@implementation NotifyHandler { - PsMacWindowPrivate *wnd; -} - -- (id) init:(PsMacWindowPrivate *)aWnd { - if (self = [super init]) { - wnd = aWnd; - } - return self; -} - -- (void) userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification { - NSNumber *instObj = [[notification userInfo] objectForKey:@"launch"]; - unsigned long long instLong = instObj ? [instObj unsignedLongLongValue] : 0; - DEBUG_LOG(("Received notification with instance %1").arg(instLong)); - if (instLong != Global::LaunchId()) { // other app instance notification - return; - } - if (notification.activationType == NSUserNotificationActivationTypeReplied) { - wnd->data->onNotifyReply(notification); - } else if (notification.activationType == NSUserNotificationActivationTypeContentsClicked) { - wnd->data->onNotifyClick(notification); - } - [center removeDeliveredNotification: notification]; -} - -- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification { - return YES; -} - -@end - PsMacWindowPrivate::PsMacWindowPrivate() : data(new PsMacWindowData(this)) { @autoreleasepool { @@ -250,11 +188,6 @@ void PsMacWindowPrivate::startBounce() { [NSApp requestUserAttention:NSInformationalRequest]; } -void PsMacWindowPrivate::updateDelegate() { - NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; - [center setDelegate:data->notifyHandler]; -} - void objc_holdOnTop(WId winId) { NSWindow *wnd = [reinterpret_cast(winId) window]; [wnd setHidesOnDeactivate:NO]; diff --git a/Telegram/SourceFiles/window/notifications_manager.cpp b/Telegram/SourceFiles/window/notifications_manager.cpp index e3249ab52f..f0c7ed0fbd 100644 --- a/Telegram/SourceFiles/window/notifications_manager.cpp +++ b/Telegram/SourceFiles/window/notifications_manager.cpp @@ -25,6 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "window/notifications_manager_default.h" #include "lang.h" #include "mainwindow.h" +#include "mainwidget.h" namespace Window { namespace Notifications { @@ -70,6 +71,22 @@ void Manager::notificationActivated(PeerId peerId, MsgId msgId) { onAfterNotificationActivated(peerId, msgId); } +void Manager::notificationReplied(PeerId peerId, MsgId msgId, const QString &reply) { + if (!peerId) return; + + auto history = App::history(peerId); + + MainWidget::MessageToSend message; + message.history = history; + message.textWithTags = { reply, TextWithTags::Tags() }; + message.replyTo = (msgId > 0 && !history->peer->isUser()) ? msgId : 0; + message.silent = false; + message.clearDraft = false; + if (auto main = App::main()) { + main->sendMessage(message); + } +} + void NativeManager::doShowNotification(HistoryItem *item, int forwardedCount) { auto hideEverything = (App::passcoded() || Global::ScreenIsLocked()); auto hideName = hideEverything || (Global::NotifyView() > dbinvShowName); diff --git a/Telegram/SourceFiles/window/notifications_manager.h b/Telegram/SourceFiles/window/notifications_manager.h index 02a2b15b77..3ea25c74a7 100644 --- a/Telegram/SourceFiles/window/notifications_manager.h +++ b/Telegram/SourceFiles/window/notifications_manager.h @@ -49,7 +49,9 @@ public: void clearFromHistory(History *history) { doClearFromHistory(history); } + void notificationActivated(PeerId peerId, MsgId msgId); + void notificationReplied(PeerId peerId, MsgId msgId, const QString &reply); virtual ~Manager() = default;