Use communication notifications

This commit is contained in:
Thomas Ricouard 2023-02-14 08:54:23 +01:00
parent 05815e6d35
commit d73b6952d9
4 changed files with 61 additions and 4 deletions

View file

@ -8,6 +8,8 @@
<array> <array>
<string>app-usage</string> <string>app-usage</string>
</array> </array>
<key>com.apple.developer.usernotifications.communication</key>
<true/>
<key>com.apple.security.app-sandbox</key> <key>com.apple.security.app-sandbox</key>
<true/> <true/>
<key>com.apple.security.application-groups</key> <key>com.apple.security.application-groups</key>

View file

@ -17,6 +17,10 @@
</array> </array>
<key>ITSAppUsesNonExemptEncryption</key> <key>ITSAppUsesNonExemptEncryption</key>
<false/> <false/>
<key>NSUserActivityTypes</key>
<array>
<string>INSendMessageIntent</string>
</array>
<key>UIBackgroundModes</key> <key>UIBackgroundModes</key>
<array> <array>
<string>remote-notification</string> <string>remote-notification</string>

View file

@ -4,6 +4,13 @@
<dict> <dict>
<key>NSExtension</key> <key>NSExtension</key>
<dict> <dict>
<key>NSExtensionAttributes</key>
<dict>
<key>IntentsSupported</key>
<array>
<string>INSendMessageIntent</string>
</array>
</dict>
<key>NSExtensionPointIdentifier</key> <key>NSExtensionPointIdentifier</key>
<string>com.apple.usernotifications.service</string> <string>com.apple.usernotifications.service</string>
<key>NSExtensionPrincipalClass</key> <key>NSExtensionPrincipalClass</key>

View file

@ -5,6 +5,8 @@ import KeychainSwift
import Models import Models
import UIKit import UIKit
import UserNotifications import UserNotifications
import Intents
import Network
@MainActor @MainActor
class NotificationService: UNNotificationServiceExtension { class NotificationService: UNNotificationServiceExtension {
@ -15,7 +17,7 @@ class NotificationService: UNNotificationServiceExtension {
self.contentHandler = contentHandler self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent { if var bestAttemptContent {
let privateKey = PushNotificationsService.shared.notificationsPrivateKeyAsKey let privateKey = PushNotificationsService.shared.notificationsPrivateKeyAsKey
let auth = PushNotificationsService.shared.notificationsAuthKeyAsKey let auth = PushNotificationsService.shared.notificationsAuthKeyAsKey
@ -58,6 +60,7 @@ class NotificationService: UNNotificationServiceExtension {
bestAttemptContent.userInfo["plaintext"] = plaintextData bestAttemptContent.userInfo["plaintext"] = plaintextData
bestAttemptContent.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: "glass.caf")) bestAttemptContent.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: "glass.caf"))
let preferences = UserPreferences.shared let preferences = UserPreferences.shared
preferences.pushNotificationsCount += 1 preferences.pushNotificationsCount += 1
@ -75,8 +78,16 @@ class NotificationService: UNNotificationServiceExtension {
if let (data, _) = try? await URLSession.shared.data(for: .init(url: url)) { if let (data, _) = try? await URLSession.shared.data(for: .init(url: url)) {
if let image = UIImage(data: data) { if let image = UIImage(data: data) {
try? image.pngData()?.write(to: fileURL) try? image.pngData()?.write(to: fileURL)
if let attachment = try? UNNotificationAttachment(identifier: filename, url: fileURL, options: nil) {
bestAttemptContent.attachments = [attachment] if let remoteNotification = await toRemoteNotification(localNotification: notification) {
let intent = buildMessageIntent(remoteNotification: remoteNotification, avatarURL: fileURL)
bestAttemptContent = try bestAttemptContent.updating(from: intent) as! UNMutableNotificationContent
let newBody = "\(bestAttemptContent.userInfo["i"] as? String ?? "") \n\(notification.title)\n\(notification.body.escape())"
bestAttemptContent.body = newBody
} else {
if let attachment = try? UNNotificationAttachment(identifier: filename, url: fileURL, options: nil) {
bestAttemptContent.attachments = [attachment]
}
} }
} }
contentHandler(bestAttemptContent) contentHandler(bestAttemptContent)
@ -89,4 +100,37 @@ class NotificationService: UNNotificationServiceExtension {
} }
} }
} }
private func toRemoteNotification(localNotification: MastodonPushNotification) async -> Models.Notification? {
do {
if let account = AppAccountsManager.shared.availableAccounts.first(where: { $0.oauthToken?.accessToken == localNotification.accessToken }) {
let client = Client(server: account.server, oauthToken: account.oauthToken)
let remoteNotification: Models.Notification = try await client.get(endpoint: Notifications.notification(id: String(localNotification.notificationID)))
return remoteNotification
}
} catch {
return nil
}
return nil
}
private func buildMessageIntent(remoteNotification: Models.Notification, avatarURL: URL) -> INSendMessageIntent {
let handle = INPersonHandle(value: remoteNotification.account.id, type: .unknown)
let avatar = INImage(url: avatarURL)
let sender = INPerson(personHandle: handle,
nameComponents: nil,
displayName: remoteNotification.account.safeDisplayName,
image: avatar,
contactIdentifier: nil,
customIdentifier: nil)
let intent = INSendMessageIntent(recipients: nil,
outgoingMessageType: .outgoingMessageText,
content: nil,
speakableGroupName: nil,
conversationIdentifier: remoteNotification.account.id,
serviceName: nil,
sender: sender,
attachments: nil)
return intent
}
} }