NB Broken! Build in Xcode fixed, macOS notifications done by Manager.

This commit is contained in:
John Preston 2016-10-02 18:44:54 +03:00
parent 0bf55835f5
commit c2aa8d3c77
8 changed files with 508 additions and 377 deletions

View file

@ -0,0 +1,39 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "lang.h"
#include <Cocoa/Cocoa.h>
namespace Platform {
inline NSString *Q2NSString(const QString &str) {
return [NSString stringWithUTF8String:str.toUtf8().constData()];
}
inline NSString *NSlang(LangKey key) {
return Q2NSString(lang(key));
}
inline QString NS2QString(NSString *str) {
return QString::fromUtf8([str cStringUsingEncoding:NSUTF8StringEncoding]);
}
} // namespace Platform

View file

@ -0,0 +1,19 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#include "stdafx.h"
#include "platform/mac/mac_utilities.h"

View file

@ -22,25 +22,39 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "platform/mac/notifications_manager_mac.h" #include "platform/mac/notifications_manager_mac.h"
#include "pspecific.h" #include "pspecific.h"
#include "platform/mac/mac_utilities.h"
#include <Cocoa/Cocoa.h>
NSImage *qt_mac_create_nsimage(const QPixmap &pm);
namespace Platform { namespace Platform {
namespace Notifications { namespace Notifications {
namespace {
NeverFreedPointer<Manager> ManagerInstance;
} // namespace
void start() { void start() {
if (cPlatform() != dbipMacOld) {
ManagerInstance.makeIfNull();
}
} }
Window::Notifications::Manager *manager() { Window::Notifications::Manager *manager() {
return nullptr; return ManagerInstance.data();
} }
void finish() { void finish() {
ManagerInstance.clear();
} }
void defaultNotificationShown(QWidget *widget) { void defaultNotificationShown(QWidget *widget) {
widget->hide(); widget->hide();
objc_holdOnTop(widget->winId()); objc_holdOnTop(widget->winId());
widget->show(); widget->show();
psShowOverAll(w, false); psShowOverAll(widget, false);
} }
class Manager::Impl { class Manager::Impl {
@ -56,18 +70,23 @@ private:
}; };
void Manager::Impl::showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton) { void Manager::Impl::showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, bool showUserpic, const QString &msg, bool showReplyButton) {
auto notification = [[NSUserNotification alloc] init]; @autoreleasepool {
NSUserNotification *notification = [[[NSUserNotification alloc] init] autorelease];
if ([notification respondsToSelector:@selector(setIdentifier:)]) {
auto identifier = QString::number(Global::LaunchId()) + '_' + QString::number(peer->id) + '_' + QString::number(msgId);
auto identifierValue = Q2NSString(identifier);
[notification setIdentifier:identifierValue];
}
[notification setUserInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedLongLong:peer->id],@"peer",[NSNumber numberWithInt:msgId],@"msgid",[NSNumber numberWithUnsignedLongLong:Global::LaunchId()],@"launch",nil]]; [notification setUserInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedLongLong:peer->id],@"peer",[NSNumber numberWithInt:msgId],@"msgid",[NSNumber numberWithUnsignedLongLong:Global::LaunchId()],@"launch",nil]];
[notification setTitle:QNSString(title).s()]; [notification setTitle:Q2NSString(title)];
[notification setSubtitle:QNSString(subtitle).s()]; [notification setSubtitle:Q2NSString(subtitle)];
[notification setInformativeText:QNSString(msg).s()]; [notification setInformativeText:Q2NSString(msg)];
if (showUserpic && [notification respondsToSelector:@selector(setContentImage:)]) { if (showUserpic && [notification respondsToSelector:@selector(setContentImage:)]) {
auto userpic = peer->genUserpic(st::notifyMacPhotoSize); auto userpic = peer->genUserpic(st::notifyMacPhotoSize);
auto img = qt_mac_create_nsimage(userpic); NSImage *img = [qt_mac_create_nsimage(userpic) autorelease];
[notification setContentImage:img]; [notification setContentImage:img];
[img release];
} }
if (showReplyButton && [notification respondsToSelector:@selector(setHasReplyButton:)]) { if (showReplyButton && [notification respondsToSelector:@selector(setHasReplyButton:)]) {
@ -76,24 +95,32 @@ void Manager::Impl::showNotification(PeerData *peer, MsgId msgId, const QString
[notification setSoundName:nil]; [notification setSoundName:nil];
auto center = [NSUserNotificationCenter defaultUserNotificationCenter]; NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
[center deliverNotification:notification]; [center deliverNotification:notification];
[notification release]; }
} }
void Manager::Impl::clearAll() { void Manager::Impl::clearAll() {
auto center = [NSUserNotificationCenter defaultUserNotificationCenter]; 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];
}
}
[center removeAllDeliveredNotifications]; [center removeAllDeliveredNotifications];
} }
void Manager::Impl::clearFromHistory(History *history) { void Manager::Impl::clearFromHistory(History *history) {
unsigned long long peerId = history->peer->id; unsigned long long peerId = history->peer->id;
auto center = [NSUserNotificationCenter defaultUserNotificationCenter]; NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
auto notificationsList = [center deliveredNotifications]; NSArray *notificationsList = [center deliveredNotifications];
for (id notify in notificationsList) { for (id notify in notificationsList) {
auto notifyUserInfo = [notify userInfo]; NSDictionary *notifyUserInfo = [notify userInfo];
auto notifyPeerId = [[notifyUserInfo objectForKey:@"peer"] unsignedLongLongValue]; auto notifyPeerId = [[notifyUserInfo objectForKey:@"peer"] unsignedLongLongValue];
auto notifyLaunchId = [[notifyUserInfo objectForKey:@"launch"] unsignedLongLongValue]; auto notifyLaunchId = [[notifyUserInfo objectForKey:@"launch"] unsignedLongLongValue];
if (notifyPeerId == peerId && notifyLaunchId == Global::LaunchId()) { if (notifyPeerId == peerId && notifyLaunchId == Global::LaunchId()) {
@ -102,6 +129,9 @@ void Manager::Impl::clearFromHistory(History *history) {
} }
} }
Manager::Impl::~Impl() {
}
Manager::Manager() : _impl(std_::make_unique<Impl>()) { Manager::Manager() : _impl(std_::make_unique<Impl>()) {
} }

View file

@ -50,7 +50,7 @@ namespace {
// Delete notify photo file after 1 minute of not using. // Delete notify photo file after 1 minute of not using.
constexpr int kNotifyDeletePhotoAfterMs = 60000; constexpr int kNotifyDeletePhotoAfterMs = 60000;
NeverFreedPointer<Manager> ToastsManager; NeverFreedPointer<Manager> ManagerInstance;
ComPtr<IToastNotificationManagerStatics> _notificationManager; ComPtr<IToastNotificationManagerStatics> _notificationManager;
ComPtr<IToastNotifier> _notifier; ComPtr<IToastNotifier> _notifier;
@ -361,7 +361,7 @@ QString getImage(const StorageKey &key, PeerData *peer) {
if (i != _images.cend()) { if (i != _images.cend()) {
if (i->until) { if (i->until) {
i->until = ms + kNotifyDeletePhotoAfterMs; i->until = ms + kNotifyDeletePhotoAfterMs;
if (auto manager = ToastsManager.data()) { if (auto manager = ManagerInstance.data()) {
manager->clearNotifyPhotosInMs(-kNotifyDeletePhotoAfterMs); manager->clearNotifyPhotosInMs(-kNotifyDeletePhotoAfterMs);
} }
} }
@ -369,7 +369,7 @@ QString getImage(const StorageKey &key, PeerData *peer) {
Image v; Image v;
if (key.first) { if (key.first) {
v.until = ms + kNotifyDeletePhotoAfterMs; v.until = ms + kNotifyDeletePhotoAfterMs;
if (auto manager = ToastsManager.data()) { if (auto manager = ManagerInstance.data()) {
manager->clearNotifyPhotosInMs(-kNotifyDeletePhotoAfterMs); manager->clearNotifyPhotosInMs(-kNotifyDeletePhotoAfterMs);
} }
} else { } else {
@ -391,16 +391,16 @@ QString getImage(const StorageKey &key, PeerData *peer) {
void start() { void start() {
if (init()) { if (init()) {
ToastsManager.makeIfNull(); ManagerInstance.makeIfNull();
} }
} }
Manager *manager() { Manager *manager() {
return ToastsManager.data(); return ManagerInstance.data();
} }
void finish() { void finish() {
ToastsManager.reset(); ManagerInstance.clear();
} }
uint64 clearImages(uint64 ms) { uint64 clearImages(uint64 ms) {

File diff suppressed because it is too large Load diff

View file

@ -49,6 +49,7 @@ public:
void clearFromHistory(History *history) { void clearFromHistory(History *history) {
doClearFromHistory(history); doClearFromHistory(history);
} }
virtual ~Manager() = default;
protected: protected:
virtual void doUpdateAll() = 0; virtual void doUpdateAll() = 0;

View file

@ -35,20 +35,20 @@ namespace {
// 3 desktop notifies at the same time. // 3 desktop notifies at the same time.
constexpr int kNotifyWindowsCount = 3; constexpr int kNotifyWindowsCount = 3;
NeverFreedPointer<Manager> FallbackManager; NeverFreedPointer<Manager> ManagerInstance;
} // namespace } // namespace
void start() { void start() {
FallbackManager.makeIfNull(); ManagerInstance.makeIfNull();
} }
Manager *manager() { Manager *manager() {
return FallbackManager.data(); return ManagerInstance.data();
} }
void finish() { void finish() {
FallbackManager.reset(); ManagerInstance.clear();
} }
Manager::Manager() { Manager::Manager() {
@ -340,7 +340,7 @@ void Widget::itemRemoved(HistoryItem *deleted) {
void Widget::unlinkHistoryAndNotify() { void Widget::unlinkHistoryAndNotify() {
unlinkHistory(); unlinkHistory();
if (auto manager = FallbackManager.data()) { if (auto manager = ManagerInstance.data()) {
manager->showNextFromQueue(); manager->showNextFromQueue();
} }
} }
@ -355,14 +355,14 @@ void Widget::unlinkHistory(History *history) {
void Widget::enterEvent(QEvent *e) { void Widget::enterEvent(QEvent *e) {
if (!_history) return; if (!_history) return;
if (auto manager = FallbackManager.data()) { if (auto manager = ManagerInstance.data()) {
manager->stopAllHiding(); manager->stopAllHiding();
} }
} }
void Widget::leaveEvent(QEvent *e) { void Widget::leaveEvent(QEvent *e) {
if (!_history) return; if (!_history) return;
if (auto manager = FallbackManager.data()) { if (auto manager = ManagerInstance.data()) {
manager->startAllHiding(); manager->startAllHiding();
} }
} }
@ -446,7 +446,7 @@ void Widget::step_appearance(float64 ms, bool timer) {
} }
Widget::~Widget() { Widget::~Widget() {
if (auto manager = FallbackManager.data()) { if (auto manager = ManagerInstance.data()) {
manager->removeFromShown(this); manager->removeFromShown(this);
} }
} }

View file

@ -326,6 +326,8 @@
'<(src_loc)/platform/linux/main_window_linux.h', '<(src_loc)/platform/linux/main_window_linux.h',
'<(src_loc)/platform/linux/notifications_manager_linux.cpp', '<(src_loc)/platform/linux/notifications_manager_linux.cpp',
'<(src_loc)/platform/linux/notifications_manager_linux.h', '<(src_loc)/platform/linux/notifications_manager_linux.h',
'<(src_loc)/platform/mac/mac_utilities.mm',
'<(src_loc)/platform/mac/mac_utilities.h',
'<(src_loc)/platform/mac/main_window_mac.mm', '<(src_loc)/platform/mac/main_window_mac.mm',
'<(src_loc)/platform/mac/main_window_mac.h', '<(src_loc)/platform/mac/main_window_mac.h',
'<(src_loc)/platform/mac/notifications_manager_mac.mm', '<(src_loc)/platform/mac/notifications_manager_mac.mm',
@ -524,6 +526,8 @@
'<(src_loc)/pspecific_mac.h', '<(src_loc)/pspecific_mac.h',
'<(src_loc)/pspecific_mac_p.mm', '<(src_loc)/pspecific_mac_p.mm',
'<(src_loc)/pspecific_mac_p.h', '<(src_loc)/pspecific_mac_p.h',
'<(src_loc)/platform/mac/mac_utilities.mm',
'<(src_loc)/platform/mac/mac_utilities.h',
'<(src_loc)/platform/mac/main_window_mac.mm', '<(src_loc)/platform/mac/main_window_mac.mm',
'<(src_loc)/platform/mac/main_window_mac.h', '<(src_loc)/platform/mac/main_window_mac.h',
'<(src_loc)/platform/mac/notifications_manager_mac.mm', '<(src_loc)/platform/mac/notifications_manager_mac.mm',