Code for replying from notifications, macOS uses notificationActivated().

This commit is contained in:
John Preston 2016-10-02 20:06:34 +03:00
parent 7f950d2de2
commit 2d1d62a953
12 changed files with 125 additions and 147 deletions

View File

@ -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);

View File

@ -69,8 +69,6 @@ public:
~MainWindow();
public slots:
void psUpdateDelegate();
void psSavePosition(Qt::WindowState state = Qt::WindowActive);
void psShowTrayMenu();

View File

@ -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();

View File

@ -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);

View File

@ -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:

View File

@ -26,15 +26,72 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include <Cocoa/Cocoa.h>
namespace {
NeverFreedPointer<Platform::Notifications::Manager> ManagerInstance;
} // namespace
NSImage *qt_mac_create_nsimage(const QPixmap &pm);
@interface NotificationDelegate : NSObject<NSUserNotificationCenterDelegate> {
}
- (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<Manager> 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<Impl>()) {
}
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) {

View File

@ -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;

View File

@ -99,7 +99,6 @@ public:
~MainWindow();
public slots:
void psUpdateDelegate();
void psSavePosition(Qt::WindowState state = Qt::WindowActive);
void psShowTrayMenu();

View File

@ -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();

View File

@ -120,50 +120,20 @@ ApplicationDelegate *_sharedDelegate = nil;
@end
@interface NotifyHandler : NSObject<NSUserNotificationCenterDelegate> {
}
- (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<NSView *>(winId) window];
[wnd setHidesOnDeactivate:NO];

View File

@ -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);

View File

@ -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;