diff --git a/Config/AppConfiguration.swift b/Config/AppConfiguration.swift index 3e70316b4..ce2ad7e77 100644 --- a/Config/AppConfiguration.swift +++ b/Config/AppConfiguration.swift @@ -74,27 +74,15 @@ private extension AppConfiguration { } func setupPushRuleSync(for matrixSession: MXSession) { - let firstSyncEnded = NotificationCenter.default.publisher(for: .mxSessionDidSync) - .first() - .eraseOutput() - - let rulesDidChange = NotificationCenter.default.publisher(for: NSNotification.Name(rawValue: kMXNotificationCenterDidUpdateRules)).eraseOutput() - - let rules = Publishers.Merge(rulesDidChange, firstSyncEnded) - .compactMap { _ -> [MXPushRule]? in - guard let center = matrixSession.notificationCenter else { - return nil - } - - return center.flatRules as? [MXPushRule] + let sessionIsReady = NotificationCenter.default.publisher(for: .mxSessionStateDidChange) + .first { _ in + matrixSession.state >= .running } - .eraseToAnyPublisher() + .eraseOutput() let applicationDidBecomeActive = NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification).eraseOutput() - let needsRulesCheck = Publishers.Merge(firstSyncEnded, applicationDidBecomeActive).eraseOutput() + let needsRulesCheck = Publishers.Merge(sessionIsReady, applicationDidBecomeActive).eraseToAnyPublisher() - pushRulesUpdater = .init(notificationSettingsService: MXNotificationSettingsService(session: matrixSession), - rules: rules, - needsCheck: needsRulesCheck) + pushRulesUpdater = .init(notificationSettingsService: MXNotificationSettingsService(session: matrixSession), needsCheck: needsRulesCheck) } } diff --git a/Riot/Managers/PushRulesUpdater/PushRulesUpdater.swift b/Riot/Managers/PushRulesUpdater/PushRulesUpdater.swift index b479febb1..e7ad1462e 100644 --- a/Riot/Managers/PushRulesUpdater/PushRulesUpdater.swift +++ b/Riot/Managers/PushRulesUpdater/PushRulesUpdater.swift @@ -18,13 +18,14 @@ import Combine final class PushRulesUpdater { private var cancellables: Set = .init() - private var rules: [MXPushRule] = [] + private var rules: [NotificationPushRuleType] = [] private let notificationSettingsService: NotificationSettingsServiceType - init(notificationSettingsService: NotificationSettingsServiceType, rules: AnyPublisher<[MXPushRule], Never>, needsCheck: AnyPublisher) { + init(notificationSettingsService: NotificationSettingsServiceType, needsCheck: AnyPublisher) { self.notificationSettingsService = notificationSettingsService - rules + notificationSettingsService + .rulesPublisher .weakAssign(to: \.rules, on: self) .store(in: &cancellables) @@ -38,64 +39,50 @@ final class PushRulesUpdater { private extension PushRulesUpdater { func updateRulesIfNeeded() { + print("*** check started: \(rules.count)") for rule in rules { syncRelatedRulesIfNeeded(for: rule) } } - func syncRelatedRulesIfNeeded(for rule: MXPushRule) { - let relatedRules = rule.syncedRules(in: rules) + func syncRelatedRulesIfNeeded(for rule: NotificationPushRuleType) { + guard let ruleId = NotificationPushRuleId(rawValue: rule.ruleId) else { + return + } + + let relatedRules = ruleId.syncedRules(in: rules) for relatedRule in relatedRules { - guard MXPushRule.haveSameContent(relatedRule, rule) == false else { - MXLog.debug("*** OK -> rule: \(relatedRule.ruleId)") + guard rule.hasSameContent(relatedRule) == false else { + print("*** OK -> rule: \(relatedRule.ruleId)") continue } - let index = NotificationIndex.index(when: rule.enabled) - #warning("Fix me") - let standardActions = NotificationPushRuleId(rawValue: rule.ruleId)!.standardActions(for: index) + let notificationOption = NotificationIndex.index(when: rule.enabled) - MXLog.debug("*** mismatch -> rule: \(relatedRule.ruleId)") + guard + let ruleId = NotificationPushRuleId(rawValue: rule.ruleId), + let expectedActions = ruleId.standardActions(for: notificationOption).actions + else { + return + } + + print("*** mismatch -> rule: \(relatedRule.ruleId)") Task { - try? await notificationSettingsService.updatePushRuleActions(for: relatedRule.ruleId, - enabled: rule.enabled, - actions: standardActions.actions) + try? await notificationSettingsService.updatePushRuleActions(for: relatedRule.ruleId, enabled: rule.enabled, actions: expectedActions) } } } } -private extension MXPushRule { - func syncedRules(in rules: [MXPushRule]) -> [MXPushRule] { +extension NotificationPushRuleType { + func hasSameContent(_ otherRule: NotificationPushRuleType) -> Bool { guard let ruleId = NotificationPushRuleId(rawValue: ruleId) else { - return [] - } - - return rules.filter { - guard let someRuleId = NotificationPushRuleId(rawValue: $0.ruleId) else { - return false - } - return ruleId.syncedRules.contains(someRuleId) - } - } - - static func haveSameContent(_ firstRule: MXPushRule, _ secondRule: MXPushRule) -> Bool { - guard - firstRule.enabled == secondRule.enabled, - let firstActions = firstRule.mxActions, - let secondActions = secondRule.mxActions, - firstActions.count == secondActions.count - else { return false } - return firstActions.indices.allSatisfy { index in - let action1 = firstActions[index] - let action2 = secondActions[index] - #warning("compare @property (nonatomic) NSDictionary *parameters") - return action1.actionType == action2.actionType - } + let notificationOption = NotificationIndex.index(when: enabled) + return otherRule.matches(standardActions: ruleId.standardActions(for: notificationOption)) } } diff --git a/RiotSwiftUI/Modules/Settings/Notifications/Service/MatrixSDK/MXNotificationSettingsService.swift b/RiotSwiftUI/Modules/Settings/Notifications/Service/MatrixSDK/MXNotificationSettingsService.swift index 84f25c106..d85c21e3a 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/Service/MatrixSDK/MXNotificationSettingsService.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/Service/MatrixSDK/MXNotificationSettingsService.swift @@ -17,7 +17,7 @@ import Combine import Foundation -class MXNotificationSettingsService: NotificationSettingsServiceType { +final class MXNotificationSettingsService: NotificationSettingsServiceType { private let session: MXSession private var cancellables = Set() @@ -34,8 +34,22 @@ class MXNotificationSettingsService: NotificationSettingsServiceType { init(session: MXSession) { self.session = session + // Publisher of all rule updates - let rulesUpdated = NotificationCenter.default.publisher(for: NSNotification.Name(rawValue: kMXNotificationCenterDidUpdateRules)) + let rulesUpdated: AnyPublisher + let didUpdateRules = NotificationCenter.default.publisher(for: NSNotification.Name(rawValue: kMXNotificationCenterDidUpdateRules)).eraseOutput() + + if session.state >= .running { + rulesUpdated = didUpdateRules + } else { + let sessionIsReady = NotificationCenter.default.publisher(for: .mxSessionStateDidChange) + .first { _ in + session.state >= .running + } + .eraseOutput() + + rulesUpdated = Publishers.Merge(sessionIsReady, didUpdateRules).eraseToAnyPublisher() + } // Set initial value of the content rules if let contentRules = session.notificationCenter.rules?.global.content as? [MXPushRule] { diff --git a/RiotSwiftUI/Modules/Settings/Notifications/ViewModel/NotificationSettingsViewModel.swift b/RiotSwiftUI/Modules/Settings/Notifications/ViewModel/NotificationSettingsViewModel.swift index f782901b1..bbf76577f 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/ViewModel/NotificationSettingsViewModel.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/ViewModel/NotificationSettingsViewModel.swift @@ -294,7 +294,7 @@ private extension NotificationSettingsViewModel { } } -private extension NotificationPushRuleId { +extension NotificationPushRuleId { func syncedRules(in rules: [NotificationPushRuleType]) -> [NotificationPushRuleType] { rules.filter { guard let ruleId = NotificationPushRuleId(rawValue: $0.ruleId) else {