#include "QtCore/qurl.h"
+#include "account.h"
+#include "accountstate.h"
+#include "accountmanager.h"
#include "config.h"
+#include "systray.h"
+#include "tray/talkreply.h"
#include <QString>
#include <QWindow>
#include <QLoggingCategory>
Q_LOGGING_CATEGORY(lcMacSystray, "nextcloud.gui.macsystray")
+/************************* Private utility functions *************************/
+
+namespace {
+
+void sendTalkReply(UNNotificationResponse *response, UNNotificationContent* content)
+{
+ if (!response || !content) {
+ qCWarning(lcMacSystray()) << "Invalid notification response or content."
+ << "Can't send talk reply.";
+ return;
+ }
+
+ UNTextInputNotificationResponse *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"];
+
+ const auto qReply = QString::fromNSString(reply);
+ const auto qReplyTo = QString::fromNSString(replyTo);
+ const auto qToken = QString::fromNSString(token);
+ const auto qAccount = QString::fromNSString(account);
+
+ const auto accountState = OCC::AccountManager::instance()->accountFromUserId(qAccount);
+
+ if (!accountState) {
+ qCWarning(lcMacSystray()) << "Could not find account matching" << qAccount
+ << "Can't send talk reply.";
+ return;
+ }
+
+ qCDebug(lcMacSystray()) << "Sending talk reply from macOS notification."
+ << "Reply is:" << qReply
+ << "Replying to:" << qReplyTo
+ << "Token:" << qToken
+ << "Account:" << qAccount;
+
+ QPointer<OCC::TalkReply> talkReply = new OCC::TalkReply(accountState.data(), OCC::Systray::instance());
+ talkReply->sendReplyMessage(qToken, qReply, qReplyTo);
+}
+
+} // anonymous namespace
+
+/**************************** Objective-C classes ****************************/
+
@interface NotificationCenterDelegate : NSObject
@end
@implementation NotificationCenterDelegate
UNNotificationContent* content = response.notification.request.content;
if ([content.categoryIdentifier isEqualToString:@"UPDATE"]) {
- if ([response.actionIdentifier isEqualToString:@"DOWNLOAD_ACTION"] || [response.actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier])
- {
+ 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"]]];
}
+ } else if ([content.categoryIdentifier isEqualToString:@"TALK_MESSAGE"]) {
+
+ if ([response.actionIdentifier isEqualToString:@"TALK_REPLY_ACTION"]) {
+ sendTalkReply(response, content);
+ }
}
completionHandler();
}
@end
-namespace OCC {
+/********************* Methods accessible to C++ Systray *********************/
-enum MacNotificationAuthorizationOptions {
- Default = 0,
- Provisional
-};
+namespace OCC {
double menuBarThickness()
{
intentIdentifiers:@[]
options:UNNotificationCategoryOptionNone];
- [[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:[NSSet setWithObjects:generalCategory, updateCategory, nil]];
+ // 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]];
}
-void checkNotificationAuth(MacNotificationAuthorizationOptions additionalAuthOption = MacNotificationAuthorizationOptions::Provisional)
+void checkNotificationAuth(MacNotificationAuthorizationOptions additionalAuthOption)
{
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert + UNAuthorizationOptionSound;
[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];
+ checkNotificationAuth();
+
+ if (!accountState || !accountState->account()) {
+ sendOsXUserNotification(title, message);
+ return;
+ }
+
+ NSString *accountNS = accountState->account()->displayName().toNSString();
+ NSString *tokenNS = token.toNSString();
+ NSString *replyToNS = replyTo.toNSString();
+
+ UNMutableNotificationContent* 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];
+
+ [center addNotificationRequest:request withCompletionHandler:nil];
+}
+
void setTrayWindowLevelAndVisibleOnAllSpaces(QWindow *window)
{
NSView *nativeView = (NSView *)window->winId();
return [osxMode containsString:@"Dark"];
}
-}
-
+} // OCC namespace