2022-05-10 17:12:15 +03:00
|
|
|
#include "QtCore/qurl.h"
|
|
|
|
#include "config.h"
|
2015-02-07 20:23:09 +03:00
|
|
|
#include <QString>
|
2020-11-30 21:24:41 +03:00
|
|
|
#include <QWindow>
|
2022-05-10 17:12:15 +03:00
|
|
|
#include <QLoggingCategory>
|
|
|
|
|
2015-02-07 20:23:09 +03:00
|
|
|
#import <Cocoa/Cocoa.h>
|
2022-05-10 17:12:15 +03:00
|
|
|
#import <UserNotifications/UserNotifications.h>
|
|
|
|
|
|
|
|
Q_LOGGING_CATEGORY(lcMacSystray, "nextcloud.gui.macsystray")
|
2015-02-07 20:23:09 +03:00
|
|
|
|
2016-01-05 15:32:46 +03:00
|
|
|
@interface NotificationCenterDelegate : NSObject
|
|
|
|
@end
|
|
|
|
@implementation NotificationCenterDelegate
|
2022-05-10 17:12:15 +03:00
|
|
|
|
2016-01-05 15:32:46 +03:00
|
|
|
// Always show, even if app is active at the moment.
|
2022-05-10 17:12:15 +03:00
|
|
|
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
|
|
|
|
willPresentNotification:(UNNotification *)notification
|
|
|
|
withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
|
2016-01-05 15:32:46 +03:00
|
|
|
{
|
2022-05-10 17:12:15 +03:00
|
|
|
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();
|
2016-01-05 15:32:46 +03:00
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
2015-02-07 20:23:09 +03:00
|
|
|
namespace OCC {
|
|
|
|
|
2022-05-17 20:20:04 +03:00
|
|
|
enum MacNotificationAuthorizationOptions {
|
|
|
|
Default = 0,
|
|
|
|
Provisional
|
|
|
|
};
|
|
|
|
|
2022-02-03 18:37:17 +03:00
|
|
|
double statusBarThickness()
|
|
|
|
{
|
|
|
|
return [NSStatusBar systemStatusBar].thickness;
|
|
|
|
}
|
|
|
|
|
2022-05-10 17:12:15 +03:00
|
|
|
// TODO: Get this to actually check for permissions
|
2015-02-07 20:23:09 +03:00
|
|
|
bool canOsXSendUserNotification()
|
|
|
|
{
|
2022-05-10 17:12:15 +03:00
|
|
|
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
|
|
|
|
return center != nil;
|
2015-02-07 20:23:09 +03:00
|
|
|
}
|
|
|
|
|
2022-05-10 17:12:15 +03:00
|
|
|
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]];
|
|
|
|
}
|
|
|
|
|
2022-05-17 20:20:04 +03:00
|
|
|
void checkNotificationAuth(MacNotificationAuthorizationOptions additionalAuthOption = MacNotificationAuthorizationOptions::Provisional)
|
2022-05-10 17:12:15 +03:00
|
|
|
{
|
|
|
|
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
|
2022-05-17 20:20:04 +03:00
|
|
|
UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert + UNAuthorizationOptionSound;
|
|
|
|
|
|
|
|
if(additionalAuthOption == MacNotificationAuthorizationOptions::Provisional) {
|
|
|
|
authOptions += UNAuthorizationOptionProvisional;
|
|
|
|
}
|
|
|
|
|
|
|
|
[center requestAuthorizationWithOptions:(authOptions)
|
2022-05-10 17:12:15 +03:00
|
|
|
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()
|
2015-02-07 20:23:09 +03:00
|
|
|
{
|
2022-05-10 17:12:15 +03:00
|
|
|
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
|
2015-02-07 20:23:09 +03:00
|
|
|
|
2016-01-05 15:32:46 +03:00
|
|
|
static dispatch_once_t once;
|
|
|
|
dispatch_once(&once, ^{
|
|
|
|
id delegate = [[NotificationCenterDelegate alloc] init];
|
2022-05-10 17:12:15 +03:00
|
|
|
[center setDelegate:delegate];
|
2016-01-05 15:32:46 +03:00
|
|
|
});
|
2022-05-10 17:12:15 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
2016-01-05 15:32:46 +03:00
|
|
|
|
2022-05-10 17:12:15 +03:00
|
|
|
UNMutableNotificationContent* content = basicNotificationContent(title, message);
|
|
|
|
content.categoryIdentifier = @"GENERAL";
|
2015-02-07 20:23:09 +03:00
|
|
|
|
2022-05-10 17:12:15 +03:00
|
|
|
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];
|
2015-02-07 20:23:09 +03:00
|
|
|
}
|
|
|
|
|
2020-11-30 21:24:41 +03:00
|
|
|
void setTrayWindowLevelAndVisibleOnAllSpaces(QWindow *window)
|
|
|
|
{
|
|
|
|
NSView *nativeView = (NSView *)window->winId();
|
|
|
|
NSWindow *nativeWindow = (NSWindow *)[nativeView window];
|
|
|
|
[nativeWindow setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces | NSWindowCollectionBehaviorIgnoresCycle |
|
|
|
|
NSWindowCollectionBehaviorTransient];
|
|
|
|
[nativeWindow setLevel:NSMainMenuWindowLevel];
|
|
|
|
}
|
|
|
|
|
2022-02-04 05:39:38 +03:00
|
|
|
bool osXInDarkMode()
|
|
|
|
{
|
|
|
|
NSString *osxMode = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
|
|
|
|
return [osxMode containsString:@"Dark"];
|
|
|
|
}
|
|
|
|
|
2015-02-07 20:23:09 +03:00
|
|
|
}
|
2022-05-10 17:12:15 +03:00
|
|
|
|