NotificationService.swift 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. import UserNotifications
  2. import CoreData
  3. /// This app extension is responsible for persisting the incoming notification to the data store (Core Data). It will eventually be the entity that
  4. /// fetches notification content from selfhosted servers (when a "poll request" is received). This is not implemented yet.
  5. ///
  6. /// Note that the app extension does not run as part of the main app, so log messages are not printed in the main Xcode window. To debug,
  7. /// select Debug -> Attach to Process by PID or Name, and select the extension. Don't forget to set a breakpoint, or you're not gonna have a good time.
  8. class NotificationService: UNNotificationServiceExtension {
  9. let tag = "NotificationService"
  10. var contentHandler: ((UNNotificationContent) -> Void)?
  11. var bestAttemptContent: UNMutableNotificationContent?
  12. override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
  13. self.contentHandler = contentHandler
  14. self.bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
  15. Log.d(tag, "Notification received (in service)") // Logs from extensions are not printed in Xcode!
  16. if let bestAttemptContent = bestAttemptContent {
  17. let userInfo = bestAttemptContent.userInfo
  18. // Set notification title to short URL if there is no title. The title is always set
  19. // by the server, but it may be empty.
  20. if let topic = userInfo["topic"] as? String,
  21. let title = userInfo["title"] as? String {
  22. if title == "" {
  23. bestAttemptContent.title = topicShortUrl(baseUrl: Config.appBaseUrl, topic: topic)
  24. }
  25. }
  26. // Play a sound, and group by topic
  27. bestAttemptContent.sound = .default
  28. bestAttemptContent.threadIdentifier = userInfo["topic"] as? String ?? ""
  29. // Save notification to store, and display it
  30. Store.shared.save(notificationFromUserInfo: userInfo)
  31. contentHandler(bestAttemptContent)
  32. }
  33. }
  34. override func serviceExtensionTimeWillExpire() {
  35. // Called just before the extension will be terminated by the system.
  36. // Use this as an opportunity to deliver your "best attempt" at modified content,
  37. // otherwise the original push payload will be used.
  38. if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
  39. contentHandler(bestAttemptContent)
  40. }
  41. }
  42. }