+#include "QtCore/qurl.h"
+#include "config.h"
#include <QString>
#include <QWindow>
+#include <QLoggingCategory>
+
#import <Cocoa/Cocoa.h>
+#import <UserNotifications/UserNotifications.h>
+
+Q_LOGGING_CATEGORY(lcMacSystray, "nextcloud.gui.macsystray")
@interface NotificationCenterDelegate : NSObject
@end
@implementation NotificationCenterDelegate
+
// Always show, even if app is active at the moment.
-- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center
- shouldPresentNotification:(NSUserNotification *)notification
+- (void)userNotificationCenter:(UNUserNotificationCenter *)center
+ willPresentNotification:(UNNotification *)notification
+ withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
- Q_UNUSED(center);
- Q_UNUSED(notification);
- return YES;
+ completionHandler(UNNotificationPresentationOptionSound + UNNotificationPresentationOptionBanner);
+}
+
+- (void)userNotificationCenter:(UNUserNotificationCenter *)center
+ didReceiveNotificationResponse:(UNNotificationResponse *)response
+ withCompletionHandler:(void (^)(void))completionHandler
+{
+ qCDebug(lcMacSystray()) << "Received notification with category identifier:" << response.notification.request.content.categoryIdentifier
+ << "and action identifier" << response.actionIdentifier;
+ UNNotificationContent* content = response.notification.request.content;
+ if ([content.categoryIdentifier isEqualToString:@"UPDATE"]) {
+
+ if ([response.actionIdentifier isEqualToString:@"DOWNLOAD_ACTION"] || [response.actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier])
+ {
+ qCDebug(lcMacSystray()) << "Opening update download url in browser.";
+ [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:[content.userInfo objectForKey:@"webUrl"]]];
+ }
+ }
+
+ completionHandler();
}
@end
return [NSStatusBar systemStatusBar].thickness;
}
+// TODO: Get this to actually check for permissions
bool canOsXSendUserNotification()
{
- return NSClassFromString(@"NSUserNotificationCenter") != nil;
+ UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
+ return center != nil;
}
-void sendOsXUserNotification(const QString &title, const QString &message)
+void registerNotificationCategories(const QString &localisedDownloadString) {
+ UNNotificationCategory* generalCategory = [UNNotificationCategory
+ categoryWithIdentifier:@"GENERAL"
+ actions:@[]
+ intentIdentifiers:@[]
+ options:UNNotificationCategoryOptionCustomDismissAction];
+
+ // Create the custom actions for update notifications.
+ UNNotificationAction* downloadAction = [UNNotificationAction
+ actionWithIdentifier:@"DOWNLOAD_ACTION"
+ title:localisedDownloadString.toNSString()
+ options:UNNotificationActionOptionNone];
+
+ // Create the category with the custom actions.
+ UNNotificationCategory* updateCategory = [UNNotificationCategory
+ categoryWithIdentifier:@"UPDATE"
+ actions:@[downloadAction]
+ intentIdentifiers:@[]
+ options:UNNotificationCategoryOptionNone];
+
+ [[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:[NSSet setWithObjects:generalCategory, updateCategory, nil]];
+}
+
+void checkNotificationAuth()
+{
+ UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
+ [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound + UNAuthorizationOptionProvisional)
+ completionHandler:^(BOOL granted, NSError * _Nullable error) {
+ // Enable or disable features based on authorization.
+ if(granted) {
+ qCDebug(lcMacSystray) << "Authorization for notifications has been granted, can display notifications.";
+ } else {
+ qCDebug(lcMacSystray) << "Authorization for notifications not granted.";
+ if(error) {
+ QString errorDescription([error.localizedDescription UTF8String]);
+ qCDebug(lcMacSystray) << "Error from notification center: " << errorDescription;
+ }
+ }
+ }];
+}
+
+void setUserNotificationCenterDelegate()
{
- Class cuserNotificationCenter = NSClassFromString(@"NSUserNotificationCenter");
- id userNotificationCenter = [cuserNotificationCenter defaultUserNotificationCenter];
+ UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
static dispatch_once_t once;
dispatch_once(&once, ^{
id delegate = [[NotificationCenterDelegate alloc] init];
- [userNotificationCenter setDelegate:delegate];
+ [center setDelegate:delegate];
});
+}
+
+UNMutableNotificationContent* basicNotificationContent(const QString &title, const QString &message)
+{
+ UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
+ content.title = title.toNSString();
+ content.body = message.toNSString();
+ content.sound = [UNNotificationSound defaultSound];
+
+ return content;
+}
+
+void sendOsXUserNotification(const QString &title, const QString &message)
+{
+ UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
+ checkNotificationAuth();
- Class cuserNotification = NSClassFromString(@"NSUserNotification");
- id notification = [[cuserNotification alloc] init];
- [notification setTitle:[NSString stringWithUTF8String:title.toUtf8().data()]];
- [notification setInformativeText:[NSString stringWithUTF8String:message.toUtf8().data()]];
+ UNMutableNotificationContent* content = basicNotificationContent(title, message);
+ content.categoryIdentifier = @"GENERAL";
- [userNotificationCenter deliverNotification:notification];
- [notification release];
+ UNTimeIntervalNotificationTrigger* trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats: NO];
+ UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier:@"NCUserNotification" content:content trigger:trigger];
+
+ [center addNotificationRequest:request withCompletionHandler:nil];
+}
+
+void sendOsXUpdateNotification(const QString &title, const QString &message, const QUrl &webUrl)
+{
+ UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
+ checkNotificationAuth();
+
+ UNMutableNotificationContent* content = basicNotificationContent(title, message);
+ content.categoryIdentifier = @"UPDATE";
+ content.userInfo = [NSDictionary dictionaryWithObject:[webUrl.toNSURL() absoluteString] forKey:@"webUrl"];
+
+ UNTimeIntervalNotificationTrigger* trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats: NO];
+ UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier:@"NCUpdateNotification" content:content trigger:trigger];
+
+ [center addNotificationRequest:request withCompletionHandler:nil];
}
void setTrayWindowLevelAndVisibleOnAllSpaces(QWindow *window)
}
}
+