TF-2384 Handle NSE to get plain notification in iOS

Signed-off-by: dab246 <tdvu@linagora.com>
(cherry picked from commit 364f32a14b9888f73a3a103b8b5e1bc9b31e148e)
This commit is contained in:
dab246
2023-12-24 20:09:25 +07:00
committed by Dat H. Pham
parent edcc30808c
commit a1f86d502a
18 changed files with 932 additions and 73 deletions
+100
View File
@@ -0,0 +1,100 @@
import UserNotifications
class NotificationService: UNNotificationServiceExtension {
private var handler: ((UNNotificationContent) -> Void)?
private var modifiedContent: UNMutableNotificationContent?
private lazy var keychainController = KeychainController(service: .sessions,
accessGroup: InfoPlistReader.main.keychainAccessGroupIdentifier)
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
guard let payloadData = request.content.userInfo as? [String: Any],
!keychainController.retrieveSharingSessions().isEmpty else {
return self.discard()
}
handler = contentHandler
modifiedContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
self.modifiedContent?.title = InfoPlistReader(bundle: .app).bundleDisplayName
Task {
await handleGetNewEmails(payloadData: payloadData)
}
}
override func serviceExtensionTimeWillExpire() {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
notify()
}
private func handleGetNewEmails(payloadData: [String: Any]) async {
let mapStateChanges: [String: [TypeName: String]] = PayloadParser.shared.parsingPayloadNotification(payloadData: payloadData)
if (mapStateChanges.isEmpty) {
return self.discard()
} else {
guard let currentAccountId = mapStateChanges.keys.first,
let keychainSharingSession = keychainController.retrieveSharingSessionFromKeychain(accountId: currentAccountId),
let listStateOfAccount = mapStateChanges[currentAccountId],
let newEmailState = listStateOfAccount[TypeName.EmailDelivery],
let oldEmailState = keychainSharingSession.emailState,
newEmailState != oldEmailState,
keychainSharingSession.tokenOIDC != nil || keychainSharingSession.basicAuth != nil else {
return self.discard()
}
JmapClient.shared.getNewEmails(
apiUrl: keychainSharingSession.apiUrl,
accountId: keychainSharingSession.accountId,
sinceState: oldEmailState,
authenticationType: keychainSharingSession.authenticationType,
tokenOidc: keychainSharingSession.tokenOIDC,
basicAuth: keychainSharingSession.basicAuth,
onSuccess: { emails in
self.keychainController.updateEmailStateToKeychain(accountId: keychainSharingSession.accountId, newState: newEmailState)
self.modifiedContent?.subtitle = emails.first?.subject ?? ""
self.modifiedContent?.body = emails.first?.preview ?? ""
self.modifiedContent?.badge = NSNumber(value: emails.count)
return self.notify()
},
onFailure: { error in
if let errorJmap = error as? JmapExceptions, errorJmap == JmapExceptions.notFoundNewEmails {
return self.discard()
} else {
self.modifiedContent?.body = "You have new emails"
self.modifiedContent?.badge = NSNumber(value: 1)
return self.notify()
}
}
)
}
}
private func notify() {
guard let modifiedContent else {
return discard()
}
handler?(modifiedContent)
cleanUp()
}
private func discard() {
handler?(UNMutableNotificationContent())
cleanUp()
}
private func cleanUp() {
handler = nil
modifiedContent = nil
}
deinit {
cleanUp()
}
}