SubscriptionManager.swift 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import Foundation
  2. import FirebaseMessaging
  3. /// Manager to combine persisting a subscription to the data store and subscribing to Firebase.
  4. /// This is to centralize the logic in one place.
  5. struct SubscriptionManager {
  6. private let tag = "SubscriptionManager"
  7. var store: Store
  8. func subscribe(baseUrl: String, topic: String) {
  9. Log.d(tag, "Subscribing to \(topicUrl(baseUrl: baseUrl, topic: topic))")
  10. if baseUrl == Config.appBaseUrl {
  11. Messaging.messaging().subscribe(toTopic: topic)
  12. } else {
  13. Messaging.messaging().subscribe(toTopic: topicHash(baseUrl: baseUrl, topic: topic))
  14. }
  15. let subscription = store.saveSubscription(baseUrl: baseUrl, topic: topic)
  16. poll(subscription)
  17. }
  18. func unsubscribe(_ subscription: Subscription) {
  19. Log.d(tag, "Unsubscribing from \(subscription.urlString())")
  20. DispatchQueue.main.async {
  21. if let baseUrl = subscription.baseUrl, let topic = subscription.topic {
  22. if baseUrl == Config.appBaseUrl {
  23. Messaging.messaging().unsubscribe(fromTopic: topic)
  24. } else {
  25. Messaging.messaging().unsubscribe(fromTopic: topicHash(baseUrl: baseUrl, topic: topic))
  26. }
  27. }
  28. store.delete(subscription: subscription)
  29. }
  30. }
  31. func poll(_ subscription: Subscription) {
  32. poll(subscription) { _ in }
  33. }
  34. func poll(_ subscription: Subscription, completionHandler: @escaping ([Message]) -> Void) {
  35. // This is a bit of a hack but it prevents us from polling dead subscriptions
  36. if (subscription.baseUrl == nil) {
  37. Log.d(tag, "Attempting to poll dead subscription failed")
  38. completionHandler([])
  39. return
  40. }
  41. let user = store.getUser(baseUrl: subscription.baseUrl!)?.toBasicUser()
  42. Log.d(tag, "Polling from \(subscription.urlString()) with user \(user?.username ?? "anonymous")")
  43. ApiService.shared.poll(subscription: subscription, user: user) { messages, error in
  44. guard let messages = messages else {
  45. Log.e(tag, "Polling failed", error)
  46. completionHandler([])
  47. return
  48. }
  49. Log.d(tag, "Polling success, \(messages.count) new message(s)", messages)
  50. if !messages.isEmpty {
  51. DispatchQueue.main.sync {
  52. for message in messages {
  53. store.save(notificationFromMessage: message, withSubscription: subscription)
  54. }
  55. }
  56. }
  57. completionHandler(messages)
  58. }
  59. }
  60. }