Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up systray.mm (macOS) #5602

Merged
merged 5 commits into from
Jul 24, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
148 changes: 74 additions & 74 deletions src/gui/systray.mm
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,18 @@ void sendTalkReply(UNNotificationResponse *response, UNNotificationContent* cont
return;
}

UNTextInputNotificationResponse *textInputResponse = (UNTextInputNotificationResponse*)response;
UNTextInputNotificationResponse * const textInputResponse = (UNTextInputNotificationResponse*)response;

if (!textInputResponse) {
qCWarning(lcMacSystray()) << "Notification response was not a text input response."
<< "Can't send talk reply.";
return;
}

NSString *reply = textInputResponse.userText;
NSString *token = [content.userInfo objectForKey:@"token"];
NSString *account = [content.userInfo objectForKey:@"account"];
NSString *replyTo = [content.userInfo objectForKey:@"replyTo"];
NSString * const reply = textInputResponse.userText;
NSString * const token = [content.userInfo objectForKey:@"token"];
NSString * const account = [content.userInfo objectForKey:@"account"];
NSString * const replyTo = [content.userInfo objectForKey:@"replyTo"];

const auto qReply = QString::fromNSString(reply);
const auto qReplyTo = QString::fromNSString(replyTo);
Expand All @@ -58,7 +58,8 @@ void sendTalkReply(UNNotificationResponse *response, UNNotificationContent* cont
<< "Token:" << qToken
<< "Account:" << qAccount;

QPointer<OCC::TalkReply> talkReply = new OCC::TalkReply(accountState.data(), OCC::Systray::instance());
const auto talkReply = QSharedPointer<OCC::TalkReply>::create(
accountState.data(), OCC::Systray::instance());
talkReply->sendReplyMessage(qToken, qReply, qReplyTo);
}

Expand All @@ -83,12 +84,12 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center
}

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)(void))completionHandler
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;
UNNotificationContent * const content = response.notification.request.content;
if ([content.categoryIdentifier isEqualToString:@"UPDATE"]) {

if ([response.actionIdentifier isEqualToString:@"DOWNLOAD_ACTION"] || [response.actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier]) {
Expand All @@ -112,13 +113,13 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center

double menuBarThickness()
{
const NSMenu *mainMenu = [[NSApplication sharedApplication] mainMenu];
NSMenu * const mainMenu = [[NSApplication sharedApplication] mainMenu];

if (mainMenu == nil) {
// Return this educated guess if something goes wrong.
// As of macOS 12.4 this will always return 22, even on notched Macbooks.
qCWarning(lcMacSystray) << "Got nil for main menu. Going with reasonable menu bar height guess.";
return [[NSStatusBar systemStatusBar] thickness];
return NSStatusBar.systemStatusBar.thickness;
}

return mainMenu.menuBarHeight;
Expand All @@ -127,85 +128,84 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center
// TODO: Get this to actually check for permissions
bool canOsXSendUserNotification()
{
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
UNUserNotificationCenter * const center = UNUserNotificationCenter.currentNotificationCenter;
return center != nil;
}

void registerNotificationCategories(const QString &localisedDownloadString) {
UNNotificationCategory* generalCategory = [UNNotificationCategory
categoryWithIdentifier:@"GENERAL"
actions:@[]
intentIdentifiers:@[]
options:UNNotificationCategoryOptionCustomDismissAction];
UNNotificationCategory * const 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];
UNNotificationAction * const 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];
UNNotificationCategory * const updateCategory = [UNNotificationCategory
categoryWithIdentifier:@"UPDATE"
actions:@[downloadAction]
intentIdentifiers:@[]
options:UNNotificationCategoryOptionNone];

// Create the custom action for talk notifications
UNTextInputNotificationAction* talkReplyAction = [UNTextInputNotificationAction
actionWithIdentifier:@"TALK_REPLY_ACTION"
title:QObject::tr("Reply").toNSString()
options:UNNotificationActionOptionNone
textInputButtonTitle:QObject::tr("Reply").toNSString()
textInputPlaceholder:QObject::tr("Send a Nextcloud Talk reply").toNSString()];

UNNotificationCategory* talkReplyCategory = [UNNotificationCategory
categoryWithIdentifier:@"TALK_MESSAGE"
actions:@[talkReplyAction]
intentIdentifiers:@[]
options:UNNotificationCategoryOptionNone];

[[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:[NSSet setWithObjects:generalCategory, updateCategory, talkReplyCategory, nil]];
UNTextInputNotificationAction * const talkReplyAction = [UNTextInputNotificationAction
actionWithIdentifier:@"TALK_REPLY_ACTION"
title:QObject::tr("Reply").toNSString()
options:UNNotificationActionOptionNone
textInputButtonTitle:QObject::tr("Reply").toNSString()
textInputPlaceholder:QObject::tr("Send a Nextcloud Talk reply").toNSString()];

UNNotificationCategory * const talkReplyCategory = [UNNotificationCategory
categoryWithIdentifier:@"TALK_MESSAGE"
actions:@[talkReplyAction]
intentIdentifiers:@[]
options:UNNotificationCategoryOptionNone];

[UNUserNotificationCenter.currentNotificationCenter setNotificationCategories:[NSSet setWithObjects:generalCategory, updateCategory, talkReplyCategory, nil]];
}

void checkNotificationAuth(MacNotificationAuthorizationOptions additionalAuthOption)
{
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
UNUserNotificationCenter * const center = UNUserNotificationCenter.currentNotificationCenter;
UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert + UNAuthorizationOptionSound;

if(additionalAuthOption == MacNotificationAuthorizationOptions::Provisional) {
authOptions += UNAuthorizationOptionProvisional;
}

[center requestAuthorizationWithOptions:(authOptions)
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;
}
[center requestAuthorizationWithOptions:(authOptions) 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) {
const auto errorDescription = QString::fromNSString(error.localizedDescription);
qCDebug(lcMacSystray) << "Error from notification center: " << errorDescription;
}
}
}];
}

void setUserNotificationCenterDelegate()
{
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
UNUserNotificationCenter * const center = UNUserNotificationCenter.currentNotificationCenter;

static dispatch_once_t once;
dispatch_once(&once, ^{
id delegate = [[NotificationCenterDelegate alloc] init];
[center setDelegate:delegate];
id delegate = [[NotificationCenterDelegate alloc] init];
[center setDelegate:delegate];
});
}

UNMutableNotificationContent* basicNotificationContent(const QString &title, const QString &message)
{
UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
UNMutableNotificationContent * const content = [[UNMutableNotificationContent alloc] init];
content.title = title.toNSString();
content.body = message.toNSString();
content.sound = [UNNotificationSound defaultSound];
Expand All @@ -215,69 +215,69 @@ void setUserNotificationCenterDelegate()

void sendOsXUserNotification(const QString &title, const QString &message)
{
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
UNUserNotificationCenter * const center = UNUserNotificationCenter.currentNotificationCenter;
checkNotificationAuth();

UNMutableNotificationContent* content = basicNotificationContent(title, message);
UNMutableNotificationContent * const content = basicNotificationContent(title, message);
content.categoryIdentifier = @"GENERAL";

UNTimeIntervalNotificationTrigger* trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats: NO];
UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier:@"NCUserNotification" content:content trigger:trigger];
UNTimeIntervalNotificationTrigger * const trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats:NO];
UNNotificationRequest * const 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];
UNUserNotificationCenter * const center = UNUserNotificationCenter.currentNotificationCenter;
checkNotificationAuth();

UNMutableNotificationContent* content = basicNotificationContent(title, message);
UNMutableNotificationContent * const 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];
UNTimeIntervalNotificationTrigger * const trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats:NO];
UNNotificationRequest * const request = [UNNotificationRequest requestWithIdentifier:@"NCUpdateNotification" content:content trigger:trigger];

[center addNotificationRequest:request withCompletionHandler:nil];
}

void sendOsXTalkNotification(const QString &title, const QString &message, const QString &token, const QString &replyTo, const AccountStatePtr accountState)
{
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
UNUserNotificationCenter * const center = UNUserNotificationCenter.currentNotificationCenter;
checkNotificationAuth();

if (!accountState || !accountState->account()) {
sendOsXUserNotification(title, message);
return;
}

NSString *accountNS = accountState->account()->displayName().toNSString();
NSString *tokenNS = token.toNSString();
NSString *replyToNS = replyTo.toNSString();
NSString * const accountNS = accountState->account()->displayName().toNSString();
NSString * const tokenNS = token.toNSString();
NSString * const replyToNS = replyTo.toNSString();

UNMutableNotificationContent* content = basicNotificationContent(title, message);
UNMutableNotificationContent * const content = basicNotificationContent(title, message);
content.categoryIdentifier = @"TALK_MESSAGE";
content.userInfo = [NSDictionary dictionaryWithObjects:@[accountNS, tokenNS, replyToNS] forKeys:@[@"account", @"token", @"replyTo"]];

UNTimeIntervalNotificationTrigger* trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats: NO];
UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier:@"NCTalkMessageNotification" content:content trigger:trigger];
UNTimeIntervalNotificationTrigger * const trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats:NO];
UNNotificationRequest * const request = [UNNotificationRequest requestWithIdentifier:@"NCTalkMessageNotification" content:content trigger:trigger];

[center addNotificationRequest:request withCompletionHandler:nil];
}

void setTrayWindowLevelAndVisibleOnAllSpaces(QWindow *window)
{
NSView *nativeView = (NSView *)window->winId();
NSWindow *nativeWindow = (NSWindow *)[nativeView window];
NSView * const nativeView = (NSView *)window->winId();
NSWindow * const nativeWindow = (NSWindow *)(nativeView.window);
[nativeWindow setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces | NSWindowCollectionBehaviorIgnoresCycle |
NSWindowCollectionBehaviorTransient];
[nativeWindow setLevel:NSMainMenuWindowLevel];
}

bool osXInDarkMode()
{
NSString *osxMode = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
NSString * const osxMode = [NSUserDefaults.standardUserDefaults stringForKey:@"AppleInterfaceStyle"];
return [osxMode containsString:@"Dark"];
}

Expand Down