Merge branch 'macos_api_updates' into 'master'

Update macOS notifications to use UserNotifications framework

See merge request nheko-reborn/nheko!13
This commit is contained in:
Nicolas Werner 2021-11-02 01:33:36 +00:00
commit a9dde2ef68
4 changed files with 60 additions and 23 deletions

View file

@ -591,7 +591,7 @@ include(Translations)
set(TRANSLATION_DEPS ${LANG_QRC} ${QRC} ${QM_SRC}) set(TRANSLATION_DEPS ${LANG_QRC} ${QRC} ${QM_SRC})
if (APPLE) if (APPLE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework Foundation -framework Cocoa") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework Foundation -framework Cocoa -framework UserNotifications")
set(SRC_FILES ${SRC_FILES} src/notifications/ManagerMac.mm src/notifications/ManagerMac.cpp src/emoji/MacHelper.mm) set(SRC_FILES ${SRC_FILES} src/notifications/ManagerMac.mm src/notifications/ManagerMac.cpp src/emoji/MacHelper.mm)
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.16.0") if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.16.0")
set_source_files_properties( src/notifications/ManagerMac.mm src/emoji/MacHelper.mm PROPERTIES SKIP_PRECOMPILE_HEADERS ON) set_source_files_properties( src/notifications/ManagerMac.mm src/emoji/MacHelper.mm PROPERTIES SKIP_PRECOMPILE_HEADERS ON)

View file

@ -77,10 +77,12 @@ private:
private: private:
// Objective-C(++) doesn't like to do lots of regular C++, so the actual notification // Objective-C(++) doesn't like to do lots of regular C++, so the actual notification
// posting is split out // posting is split out
void objCxxPostNotification(const QString &title, void objCxxPostNotification(const QString &room_name,
const QString &room_id,
const QString &event_id,
const QString &subtitle, const QString &subtitle,
const QString &informativeText, const QString &informativeText,
const QImage &bodyImage); const QString &bodyImagePath);
#endif #endif
#if defined(Q_OS_WINDOWS) #if defined(Q_OS_WINDOWS)

View file

@ -33,6 +33,9 @@ NotificationsManager::postNotification(const mtx::responses::Notification &notif
cache::displayName(QString::fromStdString(notification.room_id), cache::displayName(QString::fromStdString(notification.room_id),
QString::fromStdString(mtx::accessors::sender(notification.event))); QString::fromStdString(mtx::accessors::sender(notification.event)));
const auto room_id = QString::fromStdString(notification.room_id);
const auto event_id = QString::fromStdString(mtx::accessors::event_id(notification.event));
const auto isEncrypted = std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>( const auto isEncrypted = std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
&notification.event) != nullptr; &notification.event) != nullptr;
const auto isReply = utils::isReply(notification.event); const auto isReply = utils::isReply(notification.event);
@ -41,7 +44,7 @@ NotificationsManager::postNotification(const mtx::responses::Notification &notif
const QString messageInfo = (isReply ? tr("%1 replied with an encrypted message") const QString messageInfo = (isReply ? tr("%1 replied with an encrypted message")
: tr("%1 sent an encrypted message")) : tr("%1 sent an encrypted message"))
.arg(sender); .arg(sender);
objCxxPostNotification(room_name, messageInfo, "", QImage()); objCxxPostNotification(room_name, room_id, event_id, messageInfo, "", "");
} else { } else {
const QString messageInfo = const QString messageInfo =
(isReply ? tr("%1 replied to a message") : tr("%1 sent a message")).arg(sender); (isReply ? tr("%1 replied to a message") : tr("%1 sent a message")).arg(sender);
@ -49,12 +52,17 @@ NotificationsManager::postNotification(const mtx::responses::Notification &notif
MxcImageProvider::download( MxcImageProvider::download(
QString::fromStdString(mtx::accessors::url(notification.event)).remove("mxc://"), QString::fromStdString(mtx::accessors::url(notification.event)).remove("mxc://"),
QSize(200, 80), QSize(200, 80),
[this, notification, room_name, messageInfo](QString, QSize, QImage image, QString) { [this, notification, room_name, room_id, event_id, messageInfo](
objCxxPostNotification( QString, QSize, QImage, QString imgPath) {
room_name, messageInfo, formatNotification(notification), image); objCxxPostNotification(room_name,
room_id,
event_id,
messageInfo,
formatNotification(notification),
imgPath);
}); });
else else
objCxxPostNotification( objCxxPostNotification(
room_name, messageInfo, formatNotification(notification), QImage()); room_name, room_id, event_id, messageInfo, formatNotification(notification), "");
} }
} }

View file

@ -2,38 +2,65 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <AppKit/NSImage.h> #import <AppKit/NSImage.h>
#import <UserNotifications/UserNotifications.h>
#include <QtMac> #include <QtMac>
#include <QImage> #include <QImage>
@interface NSUserNotification (CFIPrivate)
- (void)set_identityImage:(NSImage *)image;
@end
NotificationsManager::NotificationsManager(QObject *parent): QObject(parent) NotificationsManager::NotificationsManager(QObject *parent): QObject(parent)
{ {
} }
void void
NotificationsManager::objCxxPostNotification(const QString &title, NotificationsManager::objCxxPostNotification(const QString &room_name,
const QString &room_id,
const QString &event_id,
const QString &subtitle, const QString &subtitle,
const QString &informativeText, const QString &informativeText,
const QImage &bodyImage) const QString &bodyImagePath)
{ {
UNAuthorizationOptions options = UNAuthorizationOptionAlert + UNAuthorizationOptionSound;
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
NSUserNotification *notif = [[NSUserNotification alloc] init]; [center requestAuthorizationWithOptions:options
completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (!granted) {
NSLog(@"No notification access");
if (error) {
NSLog(@"%@",[error localizedDescription]);
}
}
}];
notif.title = title.toNSString(); UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
notif.subtitle = subtitle.toNSString();
notif.informativeText = informativeText.toNSString();
notif.soundName = NSUserNotificationDefaultSoundName;
if (!bodyImage.isNull()) content.title = room_name.toNSString();
notif.contentImage = [[NSImage alloc] initWithCGImage: bodyImage.toCGImage() size: NSZeroSize]; content.subtitle = subtitle.toNSString();
content.body = informativeText.toNSString();
content.sound = [UNNotificationSound defaultSound];
content.threadIdentifier = room_id.toNSString();
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification: notif]; if (!bodyImagePath.isEmpty()) {
[notif autorelease]; NSError * _Nullable error;
NSURL *imageURL = [NSURL URLWithString:bodyImagePath.toNSString()];
NSArray* attachments = [NSMutableArray array];
UNNotificationAttachment *attachment = [UNNotificationAttachment attachmentWithIdentifier:@"" URL:imageURL options:nil error:&error];
if (error) {
NSLog(@"%@",[error localizedDescription]);
}
content.attachments = [attachments arrayByAddingObject:attachment];
}
UNNotificationRequest *notificationRequest = [UNNotificationRequest requestWithIdentifier:event_id.toNSString() content:content trigger:nil];
[center addNotificationRequest:notificationRequest withCompletionHandler:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(@"Unable to Add Notification Request");
}
}];
[content autorelease];
} }
//unused //unused