From db1bd7ffa69cbb3c81a972929a7c6541beebf757 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Mon, 12 Oct 2020 12:57:00 +0300 Subject: [PATCH 01/34] Last changes --- Riot.xcodeproj/project.pbxproj | 10 ++ .../PushNotificationService.m | 2 +- Riot/Modules/Application/LegacyAppDelegate.m | 9 +- RiotNSE/MXSyncResponse.swift | 26 +++++ RiotNSE/NSEMemoryStore.swift | 9 +- RiotNSE/NotificationService.swift | 81 ++++++++----- RiotNSE/SyncResponseStore.swift | 106 ++++++++++++++++++ 7 files changed, 209 insertions(+), 34 deletions(-) create mode 100644 RiotNSE/MXSyncResponse.swift create mode 100644 RiotNSE/SyncResponseStore.swift diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index d488d66c8..5d27863ad 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -787,6 +787,9 @@ EC3B066A24AC6ADE000DF9BF /* CrossSigningSetupBannerCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = EC3B066624AC6ADD000DF9BF /* CrossSigningSetupBannerCell.xib */; }; EC3B066B24AC6ADE000DF9BF /* CrossSigningBannerPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC3B066724AC6ADD000DF9BF /* CrossSigningBannerPreferences.swift */; }; EC3B066C24AC6ADE000DF9BF /* CrossSigningSetupBannerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC3B066824AC6ADD000DF9BF /* CrossSigningSetupBannerCell.swift */; }; + EC45DB1725344B8A006911C1 /* MXSyncResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC45DB1525344B89006911C1 /* MXSyncResponse.swift */; }; + EC45DB1825344B8A006911C1 /* SyncResponseStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC45DB1625344B89006911C1 /* SyncResponseStore.swift */; }; + EC45DB1925344B8E006911C1 /* SyncResponseStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC45DB1625344B89006911C1 /* SyncResponseStore.swift */; }; EC49F5F92515016F003894A6 /* RoomInfoBasicViewData.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC49F5F82515016F003894A6 /* RoomInfoBasicViewData.swift */; }; EC51E78D250FC15000AAE7DB /* RoomCreationEventRowViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC51E78C250FC15000AAE7DB /* RoomCreationEventRowViewModel.swift */; }; EC51E7902510B7C700AAE7DB /* AutosizedTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC51E78F2510B7C700AAE7DB /* AutosizedTableView.swift */; }; @@ -2011,6 +2014,8 @@ EC3B066624AC6ADD000DF9BF /* CrossSigningSetupBannerCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CrossSigningSetupBannerCell.xib; sourceTree = ""; }; EC3B066724AC6ADD000DF9BF /* CrossSigningBannerPreferences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CrossSigningBannerPreferences.swift; sourceTree = ""; }; EC3B066824AC6ADD000DF9BF /* CrossSigningSetupBannerCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CrossSigningSetupBannerCell.swift; sourceTree = ""; }; + EC45DB1525344B89006911C1 /* MXSyncResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MXSyncResponse.swift; sourceTree = ""; }; + EC45DB1625344B89006911C1 /* SyncResponseStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SyncResponseStore.swift; sourceTree = ""; }; EC49F5F82515016F003894A6 /* RoomInfoBasicViewData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomInfoBasicViewData.swift; sourceTree = ""; }; EC51E78C250FC15000AAE7DB /* RoomCreationEventRowViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomCreationEventRowViewModel.swift; sourceTree = ""; }; EC51E78F2510B7C700AAE7DB /* AutosizedTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutosizedTableView.swift; sourceTree = ""; }; @@ -5139,6 +5144,8 @@ EC85D74E2477E614002C44C9 /* RiotNSE.entitlements */, EC85D7452477E5F7002C44C9 /* NotificationService.swift */, EC85D756247E700F002C44C9 /* NSEMemoryStore.swift */, + EC45DB1525344B89006911C1 /* MXSyncResponse.swift */, + EC45DB1625344B89006911C1 /* SyncResponseStore.swift */, EC85D7472477E5F7002C44C9 /* Info.plist */, EC1CA8D924D811B400DE9EBF /* NSE-Common.xcconfig */, EC1CA8BC24D1B4CF00DE9EBF /* NSE-Debug.xcconfig */, @@ -6163,11 +6170,13 @@ EC31F09C2524AE1400D407DA /* BiometricsAuthenticationPresenter.swift in Sources */, EC85D752247C0F52002C44C9 /* UNUserNotificationCenter.swift in Sources */, EC9A3EC724E1634100A8CFAE /* KeyValueStore.swift in Sources */, + EC45DB1725344B8A006911C1 /* MXSyncResponse.swift in Sources */, 32FD757A24D2C9BA00BA7B37 /* Bundle.swift in Sources */, EC31F0962521FC5300D407DA /* Strings.swift in Sources */, EC31F0972521FC6300D407DA /* Images.swift in Sources */, EC9A3EC824E1634800A8CFAE /* KeychainStore.swift in Sources */, EC31F0942521FC3700D407DA /* LocalAuthenticationService.swift in Sources */, + EC45DB1825344B8A006911C1 /* SyncResponseStore.swift in Sources */, 32FD755B24D15C7A00BA7B37 /* Configurable.swift in Sources */, EC85D755247C0F84002C44C9 /* Constants.swift in Sources */, ); @@ -6335,6 +6344,7 @@ 3291DC8D23E0BFF10009732F /* SecurityViewController.m in Sources */, B18DEDD4243377C10075FEF7 /* KeyVerificationSelfVerifyWaitViewModelType.swift in Sources */, B1C45A88232A8C2600165425 /* SettingsIdentityServerViewState.swift in Sources */, + EC45DB1925344B8E006911C1 /* SyncResponseStore.swift in Sources */, B1C782302500EAF500337EB9 /* TabBarCoordinatorType.swift in Sources */, B1C782322500F96700337EB9 /* SplitViewPresentable.swift in Sources */, B14F142F22144F6500FA0595 /* KeyBackupRecoverFromRecoveryKeyViewModelType.swift in Sources */, diff --git a/Riot/Managers/PushNotification/PushNotificationService.m b/Riot/Managers/PushNotification/PushNotificationService.m index 5058b1e16..824a68333 100644 --- a/Riot/Managers/PushNotification/PushNotificationService.m +++ b/Riot/Managers/PushNotification/PushNotificationService.m @@ -305,7 +305,7 @@ Matrix session observer used to detect new opened sessions. NSLog(@"[PushNotificationService] launchBackgroundSync"); MXWeakify(self); - [account backgroundSync:20000 success:^{ + [account backgroundSync:20000 success:^(MXSyncResponse *syncResponse) { // Sanity check MXStrongifyAndReturnIfNil(self); diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index 90073766c..ee3286608 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -605,7 +605,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni _isAppForeground = YES; - [self configurePinCodeScreenFor:application createIfRequired:NO]; +// [self configurePinCodeScreenFor:application createIfRequired:NO]; } - (void)applicationDidBecomeActive:(UIApplication *)application @@ -715,6 +715,13 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni NSArray *mxAccounts = [MXKAccountManager sharedManager].activeAccounts; for (MXKAccount *account in mxAccounts) { + SyncResponseFileStore *syncResponseStore = [[SyncResponseFileStore alloc] initWithCredentials:account.mxCredentials]; + MXSyncResponse *syncResponse = syncResponseStore.syncResponse; + if (syncResponse) + { + [account.mxSession handleSyncResponse:syncResponse]; + } + // Do not resume for now, to test we've really fetched the events [account resume]; } diff --git a/RiotNSE/MXSyncResponse.swift b/RiotNSE/MXSyncResponse.swift new file mode 100644 index 000000000..2240b86fc --- /dev/null +++ b/RiotNSE/MXSyncResponse.swift @@ -0,0 +1,26 @@ +// +// Copyright 2020 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import MatrixSDK + +extension MXSyncResponse { + + func update(with response: MXSyncResponse) { + // TODO: To be implemented + } + +} diff --git a/RiotNSE/NSEMemoryStore.swift b/RiotNSE/NSEMemoryStore.swift index a45864db2..ad8484824 100644 --- a/RiotNSE/NSEMemoryStore.swift +++ b/RiotNSE/NSEMemoryStore.swift @@ -121,10 +121,11 @@ class NSEMemoryStore: MXMemoryStore { override var syncFilterId: String? { get { - let filter = MXFilterJSONModel() - filter.room = MXRoomFilter() - filter.room.rooms = [] - return filter.jsonString() + return fileStore.syncFilterId +// let filter = MXFilterJSONModel() +// filter.room = MXRoomFilter() +// filter.room.rooms = [] +// return filter.jsonString() } set { // no-op } diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index ebc08f96f..c720e9dc0 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -29,6 +29,7 @@ class NotificationService: UNNotificationServiceExtension { /// Cached events. Keys are eventId's var cachedEvents: [String: MXEvent] = [:] static var mxSession: MXSession? + static var syncResponseStore: SyncResponseStore? var showDecryptedContentInNotifications: Bool { return RiotSettings.shared.showDecryptedContentInNotifications } @@ -100,17 +101,20 @@ class NotificationService: UNNotificationServiceExtension { } func setupLogger() { - if !NotificationService.isLoggerInitialized { - if isatty(STDERR_FILENO) == 0 { - MXLogger.setSubLogName("nse") - MXLogger.redirectNSLog(toFiles: true) - } - NotificationService.isLoggerInitialized = true - } +// if !NotificationService.isLoggerInitialized { +// if isatty(STDERR_FILENO) == 0 { +// MXLogger.setSubLogName("nse") +// MXLogger.redirectNSLog(toFiles: true) +// } +// NotificationService.isLoggerInitialized = true +// } } func setup(withRoomId roomId: String, eventId: String, completion: @escaping () -> Void) { if let userAccount = MXKAccountManager.shared()?.activeAccounts.first { + if NotificationService.syncResponseStore == nil { + NotificationService.syncResponseStore = SyncResponseFileStore(withCredentials: userAccount.mxCredentials) + } if NotificationService.mxSession == nil { let store = NSEMemoryStore(withCredentials: userAccount.mxCredentials) NotificationService.mxSession = MXSession(matrixRestClient: MXRestClient(credentials: userAccount.mxCredentials, unrecognizedCertificateHandler: nil)) @@ -216,32 +220,45 @@ class NotificationService: UNNotificationServiceExtension { // use cached event handleEncryption(forEvent: cachedEvent) } else { - // attempt to fetch the event - mxSession.event(withEventId: eventId, inRoom: roomId, success: { [weak self] (event) in - guard let self = self else { - NSLog("[NotificationService] fetchEvent: MXSession.event method returned too late successfully.") - return - } - - guard let event = event else { - NSLog("[NotificationService] fetchEvent: MXSession.event method returned successfully with no event.") - self.fallbackToBestAttemptContent(forEventId: eventId) - return - } - + // do not call the /event api and just check if the event exists in the store + if let event = mxSession.store.event(withEventId: eventId, inRoom: roomId) { + NSLog("[NotificationService] fetchEvent: We have the event in store.") // cache this event self.cachedEvents[eventId] = event // handle encryption for this event handleEncryption(forEvent: event) - }) { [weak self] (error) in - guard let self = self else { - NSLog("[NotificationService] fetchEvent: MXSession.event method returned too late with error: \(String(describing: error))") - return - } - NSLog("[NotificationService] fetchEvent: MXSession.event method returned error: \(String(describing: error))") - self.fallbackToBestAttemptContent(forEventId: eventId) + } else { + NSLog("[NotificationService] fetchEvent: We don't have the event in store. Launch a background sync to fetch it.") + self.launchBackgroundSync(forEventId: eventId, roomId: roomId) } +// +// // attempt to fetch the event +// mxSession.event(withEventId: eventId, inRoom: roomId, success: { [weak self] (event) in +// guard let self = self else { +// NSLog("[NotificationService] fetchEvent: MXSession.event method returned too late successfully.") +// return +// } +// +// guard let event = event else { +// NSLog("[NotificationService] fetchEvent: MXSession.event method returned successfully with no event.") +// self.fallbackToBestAttemptContent(forEventId: eventId) +// return +// } +// +// // cache this event +// self.cachedEvents[eventId] = event +// +// // handle encryption for this event +// handleEncryption(forEvent: event) +// }) { [weak self] (error) in +// guard let self = self else { +// NSLog("[NotificationService] fetchEvent: MXSession.event method returned too late with error: \(String(describing: error))") +// return +// } +// NSLog("[NotificationService] fetchEvent: MXSession.event method returned error: \(String(describing: error))") +// self.fallbackToBestAttemptContent(forEventId: eventId) +// } } } @@ -255,11 +272,19 @@ class NotificationService: UNNotificationServiceExtension { // launch an initial background sync mxSession.backgroundSync(withTimeout: 20, ignoreSessionState: true) { [weak self] (response) in switch response { - case .success: + case .success(let syncResponse): guard let self = self else { NSLog("[NotificationService] launchBackgroundSync: MXSession.initialBackgroundSync returned too late successfully") return } + + if let oldSyncResponse = NotificationService.syncResponseStore?.syncResponse { + oldSyncResponse.update(with: syncResponse) + NotificationService.syncResponseStore?.syncResponse = oldSyncResponse + } else { + NotificationService.syncResponseStore?.syncResponse = syncResponse + } + // do not allow to sync anymore self.fetchEvent(withEventId: eventId, roomId: roomId, allowSync: false) break diff --git a/RiotNSE/SyncResponseStore.swift b/RiotNSE/SyncResponseStore.swift new file mode 100644 index 000000000..d316baf8e --- /dev/null +++ b/RiotNSE/SyncResponseStore.swift @@ -0,0 +1,106 @@ +// +// Copyright 2020 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import MatrixSDK + +@objc protocol SyncResponseStore: NSObjectProtocol { + var syncResponse: MXSyncResponse? { get set } +} + +@objcMembers +class SyncResponseFileStore: NSObject { + + private enum SyncResponseFileStoreConstants { + static let folderNname = "SyncResponse" + static let fileName = "syncResponse.json" + static let fileEncoding: String.Encoding = .utf8 + static let fileOperationQueue: DispatchQueue = .global(qos: .default) + } + private var filePath: URL! + private var credentials: MXCredentials + + init(withCredentials credentials: MXCredentials) { + self.credentials = credentials + super.init() + setupFilePath() + } + + private func setupFilePath() { + guard let userId = credentials.userId else { + fatalError("Credentials must provide a user identifier") + } + var cachePath: URL! + + if let appGroupIdentifier = MXSDKOptions.sharedInstance().applicationGroupIdentifier { + cachePath = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupIdentifier) + } else { + cachePath = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first + } + + filePath = cachePath + .appendingPathComponent(SyncResponseFileStoreConstants.folderNname) + .appendingPathComponent(userId) + .appendingPathComponent(SyncResponseFileStoreConstants.fileName) + + SyncResponseFileStoreConstants.fileOperationQueue.async { + try? FileManager.default.createDirectory(at: self.filePath.deletingLastPathComponent(), + withIntermediateDirectories: true, + attributes: nil) + } + } + + private func readSyncResponse() -> MXSyncResponse? { + var fileContents: String? + + SyncResponseFileStoreConstants.fileOperationQueue.sync { + fileContents = try? String(contentsOf: filePath, + encoding: SyncResponseFileStoreConstants.fileEncoding) + } + guard let jsonString = fileContents else { + return nil + } + guard let json = MXTools.deserialiseJSONString(jsonString) as? [AnyHashable: Any] else { + return nil + } + return MXSyncResponse(fromJSON: json) + } + + private func saveSyncResponse(_ syncResponse: MXSyncResponse?) { + guard let syncResponse = syncResponse else { + try? FileManager.default.removeItem(at: filePath) + return + } + SyncResponseFileStoreConstants.fileOperationQueue.async { + try? syncResponse.jsonString()?.write(to: self.filePath, + atomically: true, + encoding: SyncResponseFileStoreConstants.fileEncoding) + } + } + +} + +extension SyncResponseFileStore: SyncResponseStore { + + var syncResponse: MXSyncResponse? { + get { + return readSyncResponse() + } set { + saveSyncResponse(newValue) + } + } + +} From 386a9edc534006f60d8540b2d5a42827ac91fbbc Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Mon, 12 Oct 2020 17:27:06 +0300 Subject: [PATCH 02/34] Improve SyncResponseStore --- Riot.xcodeproj/project.pbxproj | 10 ++-- Riot/Modules/Application/LegacyAppDelegate.m | 3 +- RiotNSE/MXSyncResponse.swift | 26 --------- RiotNSE/NSDictionary.swift | 55 ++++++++++++++++++++ RiotNSE/NotificationService.swift | 49 ++++------------- RiotNSE/SyncResponseStore.swift | 28 ++++++++-- 6 files changed, 96 insertions(+), 75 deletions(-) delete mode 100644 RiotNSE/MXSyncResponse.swift create mode 100644 RiotNSE/NSDictionary.swift diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index 5d27863ad..e3b76eae8 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -787,9 +787,10 @@ EC3B066A24AC6ADE000DF9BF /* CrossSigningSetupBannerCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = EC3B066624AC6ADD000DF9BF /* CrossSigningSetupBannerCell.xib */; }; EC3B066B24AC6ADE000DF9BF /* CrossSigningBannerPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC3B066724AC6ADD000DF9BF /* CrossSigningBannerPreferences.swift */; }; EC3B066C24AC6ADE000DF9BF /* CrossSigningSetupBannerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC3B066824AC6ADD000DF9BF /* CrossSigningSetupBannerCell.swift */; }; - EC45DB1725344B8A006911C1 /* MXSyncResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC45DB1525344B89006911C1 /* MXSyncResponse.swift */; }; EC45DB1825344B8A006911C1 /* SyncResponseStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC45DB1625344B89006911C1 /* SyncResponseStore.swift */; }; EC45DB1925344B8E006911C1 /* SyncResponseStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC45DB1625344B89006911C1 /* SyncResponseStore.swift */; }; + EC45DB992534969E006911C1 /* NSDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC45DB982534969E006911C1 /* NSDictionary.swift */; }; + EC45DB9A253499FE006911C1 /* NSDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC45DB982534969E006911C1 /* NSDictionary.swift */; }; EC49F5F92515016F003894A6 /* RoomInfoBasicViewData.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC49F5F82515016F003894A6 /* RoomInfoBasicViewData.swift */; }; EC51E78D250FC15000AAE7DB /* RoomCreationEventRowViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC51E78C250FC15000AAE7DB /* RoomCreationEventRowViewModel.swift */; }; EC51E7902510B7C700AAE7DB /* AutosizedTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC51E78F2510B7C700AAE7DB /* AutosizedTableView.swift */; }; @@ -2014,8 +2015,8 @@ EC3B066624AC6ADD000DF9BF /* CrossSigningSetupBannerCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CrossSigningSetupBannerCell.xib; sourceTree = ""; }; EC3B066724AC6ADD000DF9BF /* CrossSigningBannerPreferences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CrossSigningBannerPreferences.swift; sourceTree = ""; }; EC3B066824AC6ADD000DF9BF /* CrossSigningSetupBannerCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CrossSigningSetupBannerCell.swift; sourceTree = ""; }; - EC45DB1525344B89006911C1 /* MXSyncResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MXSyncResponse.swift; sourceTree = ""; }; EC45DB1625344B89006911C1 /* SyncResponseStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SyncResponseStore.swift; sourceTree = ""; }; + EC45DB982534969E006911C1 /* NSDictionary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSDictionary.swift; sourceTree = ""; }; EC49F5F82515016F003894A6 /* RoomInfoBasicViewData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomInfoBasicViewData.swift; sourceTree = ""; }; EC51E78C250FC15000AAE7DB /* RoomCreationEventRowViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomCreationEventRowViewModel.swift; sourceTree = ""; }; EC51E78F2510B7C700AAE7DB /* AutosizedTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutosizedTableView.swift; sourceTree = ""; }; @@ -5144,7 +5145,7 @@ EC85D74E2477E614002C44C9 /* RiotNSE.entitlements */, EC85D7452477E5F7002C44C9 /* NotificationService.swift */, EC85D756247E700F002C44C9 /* NSEMemoryStore.swift */, - EC45DB1525344B89006911C1 /* MXSyncResponse.swift */, + EC45DB982534969E006911C1 /* NSDictionary.swift */, EC45DB1625344B89006911C1 /* SyncResponseStore.swift */, EC85D7472477E5F7002C44C9 /* Info.plist */, EC1CA8D924D811B400DE9EBF /* NSE-Common.xcconfig */, @@ -6168,9 +6169,9 @@ EC31F0952521FC4600D407DA /* PinCodePreferences.swift in Sources */, 32FD757424D2BEF700BA7B37 /* InfoPlist.swift in Sources */, EC31F09C2524AE1400D407DA /* BiometricsAuthenticationPresenter.swift in Sources */, + EC45DB992534969E006911C1 /* NSDictionary.swift in Sources */, EC85D752247C0F52002C44C9 /* UNUserNotificationCenter.swift in Sources */, EC9A3EC724E1634100A8CFAE /* KeyValueStore.swift in Sources */, - EC45DB1725344B8A006911C1 /* MXSyncResponse.swift in Sources */, 32FD757A24D2C9BA00BA7B37 /* Bundle.swift in Sources */, EC31F0962521FC5300D407DA /* Strings.swift in Sources */, EC31F0972521FC6300D407DA /* Images.swift in Sources */, @@ -6734,6 +6735,7 @@ B1B558FA20EF768F00210D55 /* RoomMembershipBubbleCell.m in Sources */, B157FAA223264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsViewAction.swift in Sources */, EC85D6AE2477DC89002C44C9 /* RoundedButton.swift in Sources */, + EC45DB9A253499FE006911C1 /* NSDictionary.swift in Sources */, B1CE83D72422817200D07506 /* KeyVerificationVerifyByScanningViewModelType.swift in Sources */, 3232ABA1225730E100AD6A5C /* KeyVerificationCoordinatorType.swift in Sources */, B1C562D9228C0B760037F12A /* RoomContextualMenuItem.swift in Sources */, diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index ee3286608..149e11758 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -721,8 +721,9 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni { [account.mxSession handleSyncResponse:syncResponse]; } + [syncResponseStore deleteData]; // Do not resume for now, to test we've really fetched the events - [account resume]; +// [account resume]; } _isAppForeground = YES; diff --git a/RiotNSE/MXSyncResponse.swift b/RiotNSE/MXSyncResponse.swift deleted file mode 100644 index 2240b86fc..000000000 --- a/RiotNSE/MXSyncResponse.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright 2020 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation -import MatrixSDK - -extension MXSyncResponse { - - func update(with response: MXSyncResponse) { - // TODO: To be implemented - } - -} diff --git a/RiotNSE/NSDictionary.swift b/RiotNSE/NSDictionary.swift new file mode 100644 index 000000000..b0f220461 --- /dev/null +++ b/RiotNSE/NSDictionary.swift @@ -0,0 +1,55 @@ +// +// Copyright 2020 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +extension NSDictionary { + + public static func + (lhs: NSDictionary, rhs: NSDictionary) -> NSDictionary { + let dictionary = NSMutableDictionary(dictionary: lhs) + for (key, valueR) in rhs { + if let key = key as? NSCopying { + if let valueL = dictionary[key] { + switch (valueL, valueR) { + case (let dictionaryL as NSDictionary, let dictionaryR as NSDictionary): + dictionary[key] = dictionaryL + dictionaryR + break + case (let arrayL as NSArray, let arrayR as NSArray): + dictionary[key] = arrayL + arrayR + default: + dictionary[key] = valueR + } + } + else { + dictionary[key] = valueR + } + } + } + return dictionary + } + +} + +extension NSArray { + + public static func + (lhs: NSArray, rhs: NSArray) -> NSArray { + let array = NSMutableArray() + lhs.forEach { array.add($0) } + rhs.forEach { array.add($0) } + return array + } + +} diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index c720e9dc0..446f2c984 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -228,37 +228,13 @@ class NotificationService: UNNotificationServiceExtension { // handle encryption for this event handleEncryption(forEvent: event) - } else { + } else if allowSync { NSLog("[NotificationService] fetchEvent: We don't have the event in store. Launch a background sync to fetch it.") self.launchBackgroundSync(forEventId: eventId, roomId: roomId) + } else { + NSLog("[NotificationService] fetchEvent: We don't have the event in store. Do not sync anymore.") + self.fallbackToBestAttemptContent(forEventId: eventId) } -// -// // attempt to fetch the event -// mxSession.event(withEventId: eventId, inRoom: roomId, success: { [weak self] (event) in -// guard let self = self else { -// NSLog("[NotificationService] fetchEvent: MXSession.event method returned too late successfully.") -// return -// } -// -// guard let event = event else { -// NSLog("[NotificationService] fetchEvent: MXSession.event method returned successfully with no event.") -// self.fallbackToBestAttemptContent(forEventId: eventId) -// return -// } -// -// // cache this event -// self.cachedEvents[eventId] = event -// -// // handle encryption for this event -// handleEncryption(forEvent: event) -// }) { [weak self] (error) in -// guard let self = self else { -// NSLog("[NotificationService] fetchEvent: MXSession.event method returned too late with error: \(String(describing: error))") -// return -// } -// NSLog("[NotificationService] fetchEvent: MXSession.event method returned error: \(String(describing: error))") -// self.fallbackToBestAttemptContent(forEventId: eventId) -// } } } @@ -268,23 +244,18 @@ class NotificationService: UNNotificationServiceExtension { self.fallbackToBestAttemptContent(forEventId: eventId) return } - - // launch an initial background sync - mxSession.backgroundSync(withTimeout: 20, ignoreSessionState: true) { [weak self] (response) in + + // launch a background sync, set serverTimeout as 0.1 to avoid session to decide continue catching up + mxSession.backgroundSync(withTimeout: 20, serverTimeout: 0.1, ignoreSessionState: true) { [weak self] (response) in switch response { case .success(let syncResponse): guard let self = self else { NSLog("[NotificationService] launchBackgroundSync: MXSession.initialBackgroundSync returned too late successfully") return } - - if let oldSyncResponse = NotificationService.syncResponseStore?.syncResponse { - oldSyncResponse.update(with: syncResponse) - NotificationService.syncResponseStore?.syncResponse = oldSyncResponse - } else { - NotificationService.syncResponseStore?.syncResponse = syncResponse - } - + + NotificationService.syncResponseStore?.update(with: syncResponse) + // do not allow to sync anymore self.fetchEvent(withEventId: eventId, roomId: roomId, allowSync: false) break diff --git a/RiotNSE/SyncResponseStore.swift b/RiotNSE/SyncResponseStore.swift index d316baf8e..f3dbe0db3 100644 --- a/RiotNSE/SyncResponseStore.swift +++ b/RiotNSE/SyncResponseStore.swift @@ -18,7 +18,9 @@ import Foundation import MatrixSDK @objc protocol SyncResponseStore: NSObjectProtocol { - var syncResponse: MXSyncResponse? { get set } + var syncResponse: MXSyncResponse? { get } + func update(with response: MXSyncResponse?) + func deleteData() } @objcMembers @@ -96,11 +98,27 @@ class SyncResponseFileStore: NSObject { extension SyncResponseFileStore: SyncResponseStore { var syncResponse: MXSyncResponse? { - get { - return readSyncResponse() - } set { - saveSyncResponse(newValue) + return readSyncResponse() + } + + func update(with response: MXSyncResponse?) { + guard let response = response else { + // Return if no new response + return + } + if let syncResponse = syncResponse { + // current sync response exists, merge it with the new response + var dictionary = NSDictionary(dictionary: syncResponse.jsonDictionary()) + dictionary = dictionary + NSDictionary(dictionary: response.jsonDictionary()) + saveSyncResponse(MXSyncResponse(fromJSON: dictionary as? [AnyHashable : Any])) + } else { + // no current sync response, directly save the new one + saveSyncResponse(response) } } + func deleteData() { + saveSyncResponse(nil) + } + } From 056cf111c78c8104eaab6bb160a3e774d794e20e Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Mon, 12 Oct 2020 21:51:57 +0300 Subject: [PATCH 03/34] Use store in the Kit --- Riot.xcodeproj/project.pbxproj | 12 --- RiotNSE/NSDictionary.swift | 55 ------------- RiotNSE/NotificationService.swift | 3 +- RiotNSE/SyncResponseStore.swift | 124 ------------------------------ 4 files changed, 2 insertions(+), 192 deletions(-) delete mode 100644 RiotNSE/NSDictionary.swift delete mode 100644 RiotNSE/SyncResponseStore.swift diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index e3b76eae8..d488d66c8 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -787,10 +787,6 @@ EC3B066A24AC6ADE000DF9BF /* CrossSigningSetupBannerCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = EC3B066624AC6ADD000DF9BF /* CrossSigningSetupBannerCell.xib */; }; EC3B066B24AC6ADE000DF9BF /* CrossSigningBannerPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC3B066724AC6ADD000DF9BF /* CrossSigningBannerPreferences.swift */; }; EC3B066C24AC6ADE000DF9BF /* CrossSigningSetupBannerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC3B066824AC6ADD000DF9BF /* CrossSigningSetupBannerCell.swift */; }; - EC45DB1825344B8A006911C1 /* SyncResponseStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC45DB1625344B89006911C1 /* SyncResponseStore.swift */; }; - EC45DB1925344B8E006911C1 /* SyncResponseStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC45DB1625344B89006911C1 /* SyncResponseStore.swift */; }; - EC45DB992534969E006911C1 /* NSDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC45DB982534969E006911C1 /* NSDictionary.swift */; }; - EC45DB9A253499FE006911C1 /* NSDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC45DB982534969E006911C1 /* NSDictionary.swift */; }; EC49F5F92515016F003894A6 /* RoomInfoBasicViewData.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC49F5F82515016F003894A6 /* RoomInfoBasicViewData.swift */; }; EC51E78D250FC15000AAE7DB /* RoomCreationEventRowViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC51E78C250FC15000AAE7DB /* RoomCreationEventRowViewModel.swift */; }; EC51E7902510B7C700AAE7DB /* AutosizedTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC51E78F2510B7C700AAE7DB /* AutosizedTableView.swift */; }; @@ -2015,8 +2011,6 @@ EC3B066624AC6ADD000DF9BF /* CrossSigningSetupBannerCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CrossSigningSetupBannerCell.xib; sourceTree = ""; }; EC3B066724AC6ADD000DF9BF /* CrossSigningBannerPreferences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CrossSigningBannerPreferences.swift; sourceTree = ""; }; EC3B066824AC6ADD000DF9BF /* CrossSigningSetupBannerCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CrossSigningSetupBannerCell.swift; sourceTree = ""; }; - EC45DB1625344B89006911C1 /* SyncResponseStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SyncResponseStore.swift; sourceTree = ""; }; - EC45DB982534969E006911C1 /* NSDictionary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSDictionary.swift; sourceTree = ""; }; EC49F5F82515016F003894A6 /* RoomInfoBasicViewData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomInfoBasicViewData.swift; sourceTree = ""; }; EC51E78C250FC15000AAE7DB /* RoomCreationEventRowViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomCreationEventRowViewModel.swift; sourceTree = ""; }; EC51E78F2510B7C700AAE7DB /* AutosizedTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutosizedTableView.swift; sourceTree = ""; }; @@ -5145,8 +5139,6 @@ EC85D74E2477E614002C44C9 /* RiotNSE.entitlements */, EC85D7452477E5F7002C44C9 /* NotificationService.swift */, EC85D756247E700F002C44C9 /* NSEMemoryStore.swift */, - EC45DB982534969E006911C1 /* NSDictionary.swift */, - EC45DB1625344B89006911C1 /* SyncResponseStore.swift */, EC85D7472477E5F7002C44C9 /* Info.plist */, EC1CA8D924D811B400DE9EBF /* NSE-Common.xcconfig */, EC1CA8BC24D1B4CF00DE9EBF /* NSE-Debug.xcconfig */, @@ -6169,7 +6161,6 @@ EC31F0952521FC4600D407DA /* PinCodePreferences.swift in Sources */, 32FD757424D2BEF700BA7B37 /* InfoPlist.swift in Sources */, EC31F09C2524AE1400D407DA /* BiometricsAuthenticationPresenter.swift in Sources */, - EC45DB992534969E006911C1 /* NSDictionary.swift in Sources */, EC85D752247C0F52002C44C9 /* UNUserNotificationCenter.swift in Sources */, EC9A3EC724E1634100A8CFAE /* KeyValueStore.swift in Sources */, 32FD757A24D2C9BA00BA7B37 /* Bundle.swift in Sources */, @@ -6177,7 +6168,6 @@ EC31F0972521FC6300D407DA /* Images.swift in Sources */, EC9A3EC824E1634800A8CFAE /* KeychainStore.swift in Sources */, EC31F0942521FC3700D407DA /* LocalAuthenticationService.swift in Sources */, - EC45DB1825344B8A006911C1 /* SyncResponseStore.swift in Sources */, 32FD755B24D15C7A00BA7B37 /* Configurable.swift in Sources */, EC85D755247C0F84002C44C9 /* Constants.swift in Sources */, ); @@ -6345,7 +6335,6 @@ 3291DC8D23E0BFF10009732F /* SecurityViewController.m in Sources */, B18DEDD4243377C10075FEF7 /* KeyVerificationSelfVerifyWaitViewModelType.swift in Sources */, B1C45A88232A8C2600165425 /* SettingsIdentityServerViewState.swift in Sources */, - EC45DB1925344B8E006911C1 /* SyncResponseStore.swift in Sources */, B1C782302500EAF500337EB9 /* TabBarCoordinatorType.swift in Sources */, B1C782322500F96700337EB9 /* SplitViewPresentable.swift in Sources */, B14F142F22144F6500FA0595 /* KeyBackupRecoverFromRecoveryKeyViewModelType.swift in Sources */, @@ -6735,7 +6724,6 @@ B1B558FA20EF768F00210D55 /* RoomMembershipBubbleCell.m in Sources */, B157FAA223264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsViewAction.swift in Sources */, EC85D6AE2477DC89002C44C9 /* RoundedButton.swift in Sources */, - EC45DB9A253499FE006911C1 /* NSDictionary.swift in Sources */, B1CE83D72422817200D07506 /* KeyVerificationVerifyByScanningViewModelType.swift in Sources */, 3232ABA1225730E100AD6A5C /* KeyVerificationCoordinatorType.swift in Sources */, B1C562D9228C0B760037F12A /* RoomContextualMenuItem.swift in Sources */, diff --git a/RiotNSE/NSDictionary.swift b/RiotNSE/NSDictionary.swift deleted file mode 100644 index b0f220461..000000000 --- a/RiotNSE/NSDictionary.swift +++ /dev/null @@ -1,55 +0,0 @@ -// -// Copyright 2020 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation - -extension NSDictionary { - - public static func + (lhs: NSDictionary, rhs: NSDictionary) -> NSDictionary { - let dictionary = NSMutableDictionary(dictionary: lhs) - for (key, valueR) in rhs { - if let key = key as? NSCopying { - if let valueL = dictionary[key] { - switch (valueL, valueR) { - case (let dictionaryL as NSDictionary, let dictionaryR as NSDictionary): - dictionary[key] = dictionaryL + dictionaryR - break - case (let arrayL as NSArray, let arrayR as NSArray): - dictionary[key] = arrayL + arrayR - default: - dictionary[key] = valueR - } - } - else { - dictionary[key] = valueR - } - } - } - return dictionary - } - -} - -extension NSArray { - - public static func + (lhs: NSArray, rhs: NSArray) -> NSArray { - let array = NSMutableArray() - lhs.forEach { array.add($0) } - rhs.forEach { array.add($0) } - return array - } - -} diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index 446f2c984..2900c1d3f 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -113,7 +113,8 @@ class NotificationService: UNNotificationServiceExtension { func setup(withRoomId roomId: String, eventId: String, completion: @escaping () -> Void) { if let userAccount = MXKAccountManager.shared()?.activeAccounts.first { if NotificationService.syncResponseStore == nil { - NotificationService.syncResponseStore = SyncResponseFileStore(withCredentials: userAccount.mxCredentials) + NotificationService.syncResponseStore = SyncResponseFileStore() + NotificationService.syncResponseStore?.open(withCredentials: userAccount.mxCredentials) } if NotificationService.mxSession == nil { let store = NSEMemoryStore(withCredentials: userAccount.mxCredentials) diff --git a/RiotNSE/SyncResponseStore.swift b/RiotNSE/SyncResponseStore.swift deleted file mode 100644 index f3dbe0db3..000000000 --- a/RiotNSE/SyncResponseStore.swift +++ /dev/null @@ -1,124 +0,0 @@ -// -// Copyright 2020 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation -import MatrixSDK - -@objc protocol SyncResponseStore: NSObjectProtocol { - var syncResponse: MXSyncResponse? { get } - func update(with response: MXSyncResponse?) - func deleteData() -} - -@objcMembers -class SyncResponseFileStore: NSObject { - - private enum SyncResponseFileStoreConstants { - static let folderNname = "SyncResponse" - static let fileName = "syncResponse.json" - static let fileEncoding: String.Encoding = .utf8 - static let fileOperationQueue: DispatchQueue = .global(qos: .default) - } - private var filePath: URL! - private var credentials: MXCredentials - - init(withCredentials credentials: MXCredentials) { - self.credentials = credentials - super.init() - setupFilePath() - } - - private func setupFilePath() { - guard let userId = credentials.userId else { - fatalError("Credentials must provide a user identifier") - } - var cachePath: URL! - - if let appGroupIdentifier = MXSDKOptions.sharedInstance().applicationGroupIdentifier { - cachePath = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupIdentifier) - } else { - cachePath = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first - } - - filePath = cachePath - .appendingPathComponent(SyncResponseFileStoreConstants.folderNname) - .appendingPathComponent(userId) - .appendingPathComponent(SyncResponseFileStoreConstants.fileName) - - SyncResponseFileStoreConstants.fileOperationQueue.async { - try? FileManager.default.createDirectory(at: self.filePath.deletingLastPathComponent(), - withIntermediateDirectories: true, - attributes: nil) - } - } - - private func readSyncResponse() -> MXSyncResponse? { - var fileContents: String? - - SyncResponseFileStoreConstants.fileOperationQueue.sync { - fileContents = try? String(contentsOf: filePath, - encoding: SyncResponseFileStoreConstants.fileEncoding) - } - guard let jsonString = fileContents else { - return nil - } - guard let json = MXTools.deserialiseJSONString(jsonString) as? [AnyHashable: Any] else { - return nil - } - return MXSyncResponse(fromJSON: json) - } - - private func saveSyncResponse(_ syncResponse: MXSyncResponse?) { - guard let syncResponse = syncResponse else { - try? FileManager.default.removeItem(at: filePath) - return - } - SyncResponseFileStoreConstants.fileOperationQueue.async { - try? syncResponse.jsonString()?.write(to: self.filePath, - atomically: true, - encoding: SyncResponseFileStoreConstants.fileEncoding) - } - } - -} - -extension SyncResponseFileStore: SyncResponseStore { - - var syncResponse: MXSyncResponse? { - return readSyncResponse() - } - - func update(with response: MXSyncResponse?) { - guard let response = response else { - // Return if no new response - return - } - if let syncResponse = syncResponse { - // current sync response exists, merge it with the new response - var dictionary = NSDictionary(dictionary: syncResponse.jsonDictionary()) - dictionary = dictionary + NSDictionary(dictionary: response.jsonDictionary()) - saveSyncResponse(MXSyncResponse(fromJSON: dictionary as? [AnyHashable : Any])) - } else { - // no current sync response, directly save the new one - saveSyncResponse(response) - } - } - - func deleteData() { - saveSyncResponse(nil) - } - -} From 4aec136ec295a1f6483aec12d4d235255d4e488d Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Mon, 12 Oct 2020 21:52:21 +0300 Subject: [PATCH 04/34] Use handling in MXKAccount --- Riot/Modules/Application/LegacyAppDelegate.m | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index 149e11758..cb596bb02 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -715,15 +715,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni NSArray *mxAccounts = [MXKAccountManager sharedManager].activeAccounts; for (MXKAccount *account in mxAccounts) { - SyncResponseFileStore *syncResponseStore = [[SyncResponseFileStore alloc] initWithCredentials:account.mxCredentials]; - MXSyncResponse *syncResponse = syncResponseStore.syncResponse; - if (syncResponse) - { - [account.mxSession handleSyncResponse:syncResponse]; - } - [syncResponseStore deleteData]; - // Do not resume for now, to test we've really fetched the events -// [account resume]; + [account resume]; } _isAppForeground = YES; From de389a430c4c9a08b8da29362d245155da03bf86 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Mon, 12 Oct 2020 21:52:43 +0300 Subject: [PATCH 05/34] Revert logger --- RiotNSE/NotificationService.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index 2900c1d3f..f3b13417e 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -101,13 +101,13 @@ class NotificationService: UNNotificationServiceExtension { } func setupLogger() { -// if !NotificationService.isLoggerInitialized { -// if isatty(STDERR_FILENO) == 0 { -// MXLogger.setSubLogName("nse") -// MXLogger.redirectNSLog(toFiles: true) -// } -// NotificationService.isLoggerInitialized = true -// } + if !NotificationService.isLoggerInitialized { + if isatty(STDERR_FILENO) == 0 { + MXLogger.setSubLogName("nse") + MXLogger.redirectNSLog(toFiles: true) + } + NotificationService.isLoggerInitialized = true + } } func setup(withRoomId roomId: String, eventId: String, completion: @escaping () -> Void) { From a3e392560cf10ae1810df335b566dea3b0fb3a86 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Tue, 13 Oct 2020 18:11:58 +0300 Subject: [PATCH 06/34] Remove commented codes --- Riot/Modules/Application/LegacyAppDelegate.m | 2 -- RiotNSE/NSEMemoryStore.swift | 5 +---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index cb596bb02..2276bac84 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -604,8 +604,6 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni } _isAppForeground = YES; - -// [self configurePinCodeScreenFor:application createIfRequired:NO]; } - (void)applicationDidBecomeActive:(UIApplication *)application diff --git a/RiotNSE/NSEMemoryStore.swift b/RiotNSE/NSEMemoryStore.swift index ad8484824..e927df5a0 100644 --- a/RiotNSE/NSEMemoryStore.swift +++ b/RiotNSE/NSEMemoryStore.swift @@ -121,11 +121,8 @@ class NSEMemoryStore: MXMemoryStore { override var syncFilterId: String? { get { + // Return real sync filter return fileStore.syncFilterId -// let filter = MXFilterJSONModel() -// filter.room = MXRoomFilter() -// filter.room.rooms = [] -// return filter.jsonString() } set { // no-op } From 667cf2b933b1cdc4316ea99359920a20cb89e727 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Tue, 13 Oct 2020 18:12:42 +0300 Subject: [PATCH 07/34] Update CHANGES.rst --- CHANGES.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index ff1fc5797..64e420a27 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,7 +5,7 @@ Changes to be released in next version * 🙌 Improvements - * + * NSE: Background sync and store/aggregate sync responses on pushes, to make messages available when the app is foregrounded (#3579). 🐛 Bugfix * From 66b24716dfcda87771b0d95ecf1bc52f62e9c3b7 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Thu, 22 Oct 2020 17:26:25 +0300 Subject: [PATCH 08/34] Rever background sync method --- Riot/Managers/PushNotification/PushNotificationService.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Managers/PushNotification/PushNotificationService.m b/Riot/Managers/PushNotification/PushNotificationService.m index 824a68333..5058b1e16 100644 --- a/Riot/Managers/PushNotification/PushNotificationService.m +++ b/Riot/Managers/PushNotification/PushNotificationService.m @@ -305,7 +305,7 @@ Matrix session observer used to detect new opened sessions. NSLog(@"[PushNotificationService] launchBackgroundSync"); MXWeakify(self); - [account backgroundSync:20000 success:^(MXSyncResponse *syncResponse) { + [account backgroundSync:20000 success:^{ // Sanity check MXStrongifyAndReturnIfNil(self); From c5c173e0a002b2d3f7f7ec4795c32b76ace8d4ee Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Thu, 22 Oct 2020 17:27:35 +0300 Subject: [PATCH 09/34] Use new background sync service --- RiotNSE/NotificationService.swift | 512 ++++++++++-------------------- 1 file changed, 166 insertions(+), 346 deletions(-) diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index f3b13417e..4cbe6a317 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -21,22 +21,21 @@ import MatrixSDK class NotificationService: UNNotificationServiceExtension { /// Content handlers. Keys are eventId's - var contentHandlers: [String: ((UNNotificationContent) -> Void)] = [:] + private var contentHandlers: [String: ((UNNotificationContent) -> Void)] = [:] + + private var userAccount: MXKAccount? /// Best attempt contents. Will be updated incrementally, if something fails during the process, this best attempt content will be showed as notification. Keys are eventId's - var bestAttemptContents: [String: UNMutableNotificationContent] = [:] + private var bestAttemptContents: [String: UNMutableNotificationContent] = [:] - /// Cached events. Keys are eventId's - var cachedEvents: [String: MXEvent] = [:] - static var mxSession: MXSession? - static var syncResponseStore: SyncResponseStore? - var showDecryptedContentInNotifications: Bool { + private static var backgroundSyncService: MXBackgroundSyncService! + private var showDecryptedContentInNotifications: Bool { return RiotSettings.shared.showDecryptedContentInNotifications } - lazy var configuration: Configurable = { + private lazy var configuration: Configurable = { return CommonConfiguration() }() - static var isLoggerInitialized: Bool = false + private static var isLoggerInitialized: Bool = false private lazy var pushGatewayRestClient: MXPushGatewayRestClient = { let url = URL(string: BuildSettings.serverConfigSygnalAPIUrlString)! return MXPushGatewayRestClient(pushGateway: url.scheme! + "://" + url.host!, andOnUnrecognizedCertificateBlock: nil) @@ -111,29 +110,12 @@ class NotificationService: UNNotificationServiceExtension { } func setup(withRoomId roomId: String, eventId: String, completion: @escaping () -> Void) { - if let userAccount = MXKAccountManager.shared()?.activeAccounts.first { - if NotificationService.syncResponseStore == nil { - NotificationService.syncResponseStore = SyncResponseFileStore() - NotificationService.syncResponseStore?.open(withCredentials: userAccount.mxCredentials) - } - if NotificationService.mxSession == nil { - let store = NSEMemoryStore(withCredentials: userAccount.mxCredentials) - NotificationService.mxSession = MXSession(matrixRestClient: MXRestClient(credentials: userAccount.mxCredentials, unrecognizedCertificateHandler: nil)) - NotificationService.mxSession?.setStore(store, completion: { (response) in - switch response { - case .success: - completion() - break - case .failure(let error): - NSLog("[NotificationService] setup: MXSession.setStore method returned error: \(String(describing: error))") - self.fallbackToBestAttemptContent(forEventId: eventId) - break - } - }) - } else { - NSLog("[NotificationService] Instance: Reusing session") - completion() + self.userAccount = MXKAccountManager.shared()?.activeAccounts.first + if let userAccount = userAccount { + if NotificationService.backgroundSyncService == nil { + NotificationService.backgroundSyncService = MXBackgroundSyncService(withCredentials: userAccount.mxCredentials) } + completion() } else { NSLog("[NotificationService] setup: No active accounts") fallbackToBestAttemptContent(forEventId: eventId) @@ -149,10 +131,9 @@ class NotificationService: UNNotificationServiceExtension { NSLog("[NotificationService] preprocessPayload: Do not preprocess because app protection is set") return } - guard let session = NotificationService.mxSession else { return } - guard let roomDisplayName = session.store.summary?(ofRoom: roomId)?.displayname else { return } - let isDirect = session.directUserId(inRoom: roomId) != nil - if isDirect { + guard let roomSummary = NotificationService.backgroundSyncService.roomSummary(forRoomId: roomId) else { return } + guard let roomDisplayName = roomSummary.displayname else { return } + if roomSummary.isDirect == true { bestAttemptContents[eventId]?.body = NSString.localizedUserNotificationString(forKey: "MESSAGE_FROM_X", arguments: [roomDisplayName as Any]) } else { bestAttemptContents[eventId]?.body = NSString.localizedUserNotificationString(forKey: "MESSAGE_IN_X", arguments: [roomDisplayName as Any]) @@ -160,125 +141,29 @@ class NotificationService: UNNotificationServiceExtension { } func fetchEvent(withEventId eventId: String, roomId: String, allowSync: Bool = true) { - guard let mxSession = NotificationService.mxSession else { - // there is something wrong, do not change the content - NSLog("[NotificationService] fetchEvent: Either originalContent or mxSession is missing.") - fallbackToBestAttemptContent(forEventId: eventId) - return - } + NSLog("[NotificationService] fetchEvent") - /// Inline function to handle decryption failure - func handleDecryptionFailure() { - if allowSync { - NSLog("[NotificationService] fetchEvent: Launch a background sync.") - self.launchBackgroundSync(forEventId: eventId, roomId: roomId) - } else { - NSLog("[NotificationService] fetchEvent: Do not sync anymore.") - self.fallbackToBestAttemptContent(forEventId: eventId) - } - } - - /// Inline function to handle encryption for event, either from cache or from the backend - /// - Parameter event: The event to be handled - func handleEncryption(forEvent event: MXEvent) { - if !event.isEncrypted { - // not encrypted, go on processing - NSLog("[NotificationService] fetchEvent: Event not encrypted.") - self.processEvent(event) - return - } - - // encrypted - if event.clear != nil { - // already decrypted - NSLog("[NotificationService] fetchEvent: Event already decrypted.") - self.processEvent(event) - return - } - - // should decrypt it first - if mxSession.crypto.hasKeys(toDecryptEvent: event) { - // we have keys to decrypt the event - NSLog("[NotificationService] fetchEvent: Event needs to be decrpyted, and we have the keys to decrypt it.") - if mxSession.decryptEvent(event, inTimeline: nil) { - // decryption succeeded - NSLog("[NotificationService] fetchEvent: Event decrypted successfully.") - self.processEvent(event) - } else { - // decryption failed - NSLog("[NotificationService] fetchEvent: Decryption failed even crypto claimed it has the keys.") - handleDecryptionFailure() - } - } else { - // we don't have keys to decrypt the event - NSLog("[NotificationService] fetchEvent: Event needs to be decrpyted, but we don't have the keys to decrypt it.") - handleDecryptionFailure() - } - } - - // check if we've fetched the event before - if let cachedEvent = self.cachedEvents[eventId] { - // use cached event - handleEncryption(forEvent: cachedEvent) - } else { - // do not call the /event api and just check if the event exists in the store - if let event = mxSession.store.event(withEventId: eventId, inRoom: roomId) { - NSLog("[NotificationService] fetchEvent: We have the event in store.") - // cache this event - self.cachedEvents[eventId] = event - - // handle encryption for this event - handleEncryption(forEvent: event) - } else if allowSync { - NSLog("[NotificationService] fetchEvent: We don't have the event in store. Launch a background sync to fetch it.") - self.launchBackgroundSync(forEventId: eventId, roomId: roomId) - } else { - NSLog("[NotificationService] fetchEvent: We don't have the event in store. Do not sync anymore.") - self.fallbackToBestAttemptContent(forEventId: eventId) - } - } + NotificationService.backgroundSyncService.event(withEventId: eventId, + inRoom: roomId, + completion: { (response) in + switch response { + case .success(let event): + NSLog("[NotificationService] fetchEvent: Event fetched successfully") + self.processEvent(event) + case .failure(let error): + NSLog("[NotificationService] fetchEvent: error: \(error)") + self.fallbackToBestAttemptContent(forEventId: eventId) + } + }) } - func launchBackgroundSync(forEventId eventId: String, roomId: String) { - guard let mxSession = NotificationService.mxSession else { - NSLog("[NotificationService] launchBackgroundSync: mxSession is missing.") - self.fallbackToBestAttemptContent(forEventId: eventId) - return - } - - // launch a background sync, set serverTimeout as 0.1 to avoid session to decide continue catching up - mxSession.backgroundSync(withTimeout: 20, serverTimeout: 0.1, ignoreSessionState: true) { [weak self] (response) in - switch response { - case .success(let syncResponse): - guard let self = self else { - NSLog("[NotificationService] launchBackgroundSync: MXSession.initialBackgroundSync returned too late successfully") - return - } - - NotificationService.syncResponseStore?.update(with: syncResponse) - - // do not allow to sync anymore - self.fetchEvent(withEventId: eventId, roomId: roomId, allowSync: false) - break - case .failure(let error): - guard let self = self else { - NSLog("[NotificationService] launchBackgroundSync: MXSession.initialBackgroundSync returned too late with error: \(String(describing: error))") - return - } - NSLog("[NotificationService] launchBackgroundSync: MXSession.initialBackgroundSync returned with error: \(String(describing: error))") - self.fallbackToBestAttemptContent(forEventId: eventId) - break - } - } - } - - func processEvent(_ event: MXEvent) { - guard let content = bestAttemptContents[event.eventId], let mxSession = NotificationService.mxSession else { + private func processEvent(_ event: MXEvent) { + guard let content = bestAttemptContents[event.eventId], let userAccount = userAccount else { self.fallbackToBestAttemptContent(forEventId: event.eventId) return } - self.notificationContent(forEvent: event, inSession: mxSession) { (notificationContent) in + self.notificationContent(forEvent: event, forAccount: userAccount) { (notificationContent) in var isUnwantedNotification = false // Modify the notification content here... @@ -301,7 +186,7 @@ class NotificationService: UNNotificationServiceExtension { } } - func fallbackToBestAttemptContent(forEventId eventId: String) { + private func fallbackToBestAttemptContent(forEventId eventId: String) { NSLog("[NotificationService] fallbackToBestAttemptContent: method called.") guard let content = bestAttemptContents[eventId] else { @@ -313,188 +198,160 @@ class NotificationService: UNNotificationServiceExtension { contentHandlers[eventId]?(content) } - func notificationContent(forEvent event: MXEvent, inSession session: MXSession, onComplete: @escaping (UNNotificationContent?) -> Void) { + private func notificationContent(forEvent event: MXEvent, forAccount account: MXKAccount, onComplete: @escaping (UNNotificationContent?) -> Void) { guard let content = event.content, content.count > 0 else { NSLog("[NotificationService] notificationContentForEvent: empty event content") onComplete(nil) return } - guard let room = MXRoom.load(from: session.store, withRoomId: event.roomId, matrixSession: session) as? MXRoom else { - NSLog("[NotificationService] notificationContentForEvent: Unknown room") - onComplete(nil) - return - } + + let roomId = event.roomId! + let isRoomMentionsOnly = NotificationService.backgroundSyncService.isRoomMentionsOnly(roomId) + let roomSummary = NotificationService.backgroundSyncService.roomSummary(forRoomId: roomId) NSLog("[NotificationService] notificationContentForEvent: Attempt to fetch the room state") - room.state { (roomState) in - guard let roomState = roomState else { - NSLog("[NotificationService] notificationContentForEvent: Could not fetch the room state") - onComplete(nil) - return - } - - var notificationTitle: String? - var notificationBody: String? - - var threadIdentifier = room.roomId - let eventSenderName = roomState.members.memberName(event.sender) - let currentUserId = session.credentials.userId - - let pushRule = session.notificationCenter.rule(matching: event, roomState: roomState) - - switch event.eventType { - case .callInvite: - let offer = event.content["offer"] as? [AnyHashable: Any] - let sdp = offer?["sdp"] as? String - let isVideoCall = sdp?.contains("m=video") ?? false + + NotificationService.backgroundSyncService.roomState(forRoomId: roomId, completion: { (response) in + switch response { + case .success(let roomState): + var notificationTitle: String? + var notificationBody: String? - if isVideoCall { - notificationBody = NSString.localizedUserNotificationString(forKey: "VIDEO_CALL_FROM_USER", arguments: [eventSenderName as Any]) - } else { - notificationBody = NSString.localizedUserNotificationString(forKey: "VOICE_CALL_FROM_USER", arguments: [eventSenderName as Any]) - } + var threadIdentifier: String? = roomId + let eventSenderName = roomState.members.memberName(event.sender) + let currentUserId = account.mxCredentials.userId + let roomDisplayName = roomSummary?.displayname + let pushRule = NotificationService.backgroundSyncService.pushRule(matching: event, roomState: roomState) - // call notifications should stand out from normal messages, so we don't stack them - threadIdentifier = nil - self.sendVoipPush(forEvent: event) - case .roomMessage, .roomEncrypted: - if room.isMentionsOnly { - // A local notification will be displayed only for highlighted notification. - var isHighlighted = false + switch event.eventType { + case .callInvite: + let offer = event.content["offer"] as? [AnyHashable: Any] + let sdp = offer?["sdp"] as? String + let isVideoCall = sdp?.contains("m=video") ?? false - // Check whether is there an highlight tweak on it - for ruleAction in pushRule?.actions ?? [] { - guard let action = ruleAction as? MXPushRuleAction else { continue } - guard action.actionType == MXPushRuleActionTypeSetTweak else { continue } - guard action.parameters["set_tweak"] as? String == "highlight" else { continue } - // Check the highlight tweak "value" - // If not present, highlight. Else check its value before highlighting - if nil == action.parameters["value"] || true == (action.parameters["value"] as? Bool) { - isHighlighted = true - break + if isVideoCall { + notificationBody = NSString.localizedUserNotificationString(forKey: "VIDEO_CALL_FROM_USER", arguments: [eventSenderName as Any]) + } else { + notificationBody = NSString.localizedUserNotificationString(forKey: "VOICE_CALL_FROM_USER", arguments: [eventSenderName as Any]) + } + + // call notifications should stand out from normal messages, so we don't stack them + threadIdentifier = nil + self.sendVoipPush(forEvent: event) + case .roomMessage, .roomEncrypted: + if isRoomMentionsOnly { + // A local notification will be displayed only for highlighted notification. + var isHighlighted = false + + // Check whether is there an highlight tweak on it + for ruleAction in pushRule?.actions ?? [] { + guard let action = ruleAction as? MXPushRuleAction else { continue } + guard action.actionType == MXPushRuleActionTypeSetTweak else { continue } + guard action.parameters["set_tweak"] as? String == "highlight" else { continue } + // Check the highlight tweak "value" + // If not present, highlight. Else check its value before highlighting + if nil == action.parameters["value"] || true == (action.parameters["value"] as? Bool) { + isHighlighted = true + break + } + } + + if !isHighlighted { + // Ignore this notif. + NSLog("[NotificationService] notificationContentForEvent: Ignore non highlighted notif in mentions only room") + onComplete(nil) + return } } - if !isHighlighted { - // Ignore this notif. - NSLog("[NotificationService] notificationContentForEvent: Ignore non highlighted notif in mentions only room") - onComplete(nil) - return - } - } - - var msgType = event.content["msgtype"] as? String - let messageContent = event.content["body"] as? String - - if event.isEncrypted && !self.showDecryptedContentInNotifications { - // Hide the content - msgType = nil - } - - let roomDisplayName = session.store.summary?(ofRoom: room.roomId)?.displayname - let myUserId = session.myUser.userId - let isIncomingEvent = event.sender != myUserId - - // Display the room name only if it is different than the sender name - if roomDisplayName != nil && roomDisplayName != eventSenderName { - notificationTitle = NSString.localizedUserNotificationString(forKey: "MSG_FROM_USER_IN_ROOM_TITLE", arguments: [eventSenderName as Any, roomDisplayName as Any]) + var msgType = event.content["msgtype"] as? String + let messageContent = event.content["body"] as? String - if msgType == kMXMessageTypeText { - notificationBody = messageContent - } else if msgType == kMXMessageTypeEmote { - notificationBody = NSString.localizedUserNotificationString(forKey: "ACTION_FROM_USER", arguments: [eventSenderName as Any, messageContent as Any]) - } else if msgType == kMXMessageTypeImage { - notificationBody = NSString.localizedUserNotificationString(forKey: "IMAGE_FROM_USER", arguments: [eventSenderName as Any, messageContent as Any]) - } else if room.isDirect && isIncomingEvent && msgType == kMXMessageTypeKeyVerificationRequest { - session.crypto.keyVerificationManager.keyVerification(fromKeyVerificationEvent: event, - success:{ (keyVerification) in - guard let request = keyVerification.request, request.state == MXKeyVerificationRequestStatePending else { - onComplete(nil) - return - } - // TODO: Add accept and decline actions to notification - let body = NSString.localizedUserNotificationString(forKey: "KEY_VERIFICATION_REQUEST_FROM_USER", arguments: [eventSenderName as Any]) - - let notificationContent = self.notificationContent(withTitle: notificationTitle, - body: body, - threadIdentifier: threadIdentifier, - userId: currentUserId, - event: event, - pushRule: pushRule) - - onComplete(notificationContent) - }, failure:{ (error) in - NSLog("[NotificationService] notificationContentForEvent: failed to fetch key verification with error: \(error)") - onComplete(nil) - }) + if event.isEncrypted && !self.showDecryptedContentInNotifications { + // Hide the content + msgType = nil + } + + let isIncomingEvent = event.sender != currentUserId + + // Display the room name only if it is different than the sender name + if roomDisplayName != nil && roomDisplayName != eventSenderName { + notificationTitle = NSString.localizedUserNotificationString(forKey: "MSG_FROM_USER_IN_ROOM_TITLE", arguments: [eventSenderName as Any, roomDisplayName as Any]) + + if msgType == kMXMessageTypeText { + notificationBody = messageContent + } else if msgType == kMXMessageTypeEmote { + notificationBody = NSString.localizedUserNotificationString(forKey: "ACTION_FROM_USER", arguments: [eventSenderName as Any, messageContent as Any]) + } else if msgType == kMXMessageTypeImage { + notificationBody = NSString.localizedUserNotificationString(forKey: "IMAGE_FROM_USER", arguments: [eventSenderName as Any, messageContent as Any]) + } else { + // Encrypted messages falls here + notificationBody = NSString.localizedUserNotificationString(forKey: "MESSAGE", arguments: []) + } } else { - // Encrypted messages falls here - notificationBody = NSString.localizedUserNotificationString(forKey: "MESSAGE", arguments: []) + notificationTitle = eventSenderName + + switch msgType { + case kMXMessageTypeText: + notificationBody = messageContent + break + case kMXMessageTypeEmote: + notificationBody = NSString.localizedUserNotificationString(forKey: "ACTION_FROM_USER", arguments: [eventSenderName as Any, messageContent as Any]) + break + case kMXMessageTypeImage: + notificationBody = NSString.localizedUserNotificationString(forKey: "IMAGE_FROM_USER", arguments: [eventSenderName as Any, messageContent as Any]) + break + default: + // Encrypted messages falls here + notificationBody = NSString.localizedUserNotificationString(forKey: "MESSAGE", arguments: []) + break + } + } + break + case .roomMember: + if roomDisplayName != nil && roomDisplayName != eventSenderName { + notificationBody = NSString.localizedUserNotificationString(forKey: "USER_INVITE_TO_NAMED_ROOM", arguments: [eventSenderName as Any, roomDisplayName as Any]) + } else { + notificationBody = NSString.localizedUserNotificationString(forKey: "USER_INVITE_TO_CHAT", arguments: [eventSenderName as Any]) + } + case .sticker: + if roomDisplayName != nil && roomDisplayName != eventSenderName { + notificationTitle = NSString.localizedUserNotificationString(forKey: "MSG_FROM_USER_IN_ROOM_TITLE", arguments: [eventSenderName as Any, roomDisplayName as Any]) + } else { + notificationTitle = eventSenderName } - } else { - notificationTitle = eventSenderName - switch msgType { - case kMXMessageTypeText: - notificationBody = messageContent - break - case kMXMessageTypeEmote: - notificationBody = NSString.localizedUserNotificationString(forKey: "ACTION_FROM_USER", arguments: [eventSenderName as Any, messageContent as Any]) - break - case kMXMessageTypeImage: - notificationBody = NSString.localizedUserNotificationString(forKey: "IMAGE_FROM_USER", arguments: [eventSenderName as Any, messageContent as Any]) - break - default: - // Encrypted messages falls here - notificationBody = NSString.localizedUserNotificationString(forKey: "MESSAGE", arguments: []) - break - } - } - break - case .roomMember: - let roomDisplayName = room.summary.displayname - - if roomDisplayName != nil && roomDisplayName != eventSenderName { - notificationBody = NSString.localizedUserNotificationString(forKey: "USER_INVITE_TO_NAMED_ROOM", arguments: [eventSenderName as Any, roomDisplayName as Any]) - } else { - notificationBody = NSString.localizedUserNotificationString(forKey: "USER_INVITE_TO_CHAT", arguments: [eventSenderName as Any]) - } - case .sticker: - let roomDisplayName = room.summary.displayname - - if roomDisplayName != nil && roomDisplayName != eventSenderName { - notificationTitle = NSString.localizedUserNotificationString(forKey: "MSG_FROM_USER_IN_ROOM_TITLE", arguments: [eventSenderName as Any, roomDisplayName as Any]) - } else { - notificationTitle = eventSenderName + notificationBody = NSString.localizedUserNotificationString(forKey: "STICKER_FROM_USER", arguments: [eventSenderName as Any]) + default: + break } - notificationBody = NSString.localizedUserNotificationString(forKey: "STICKER_FROM_USER", arguments: [eventSenderName as Any]) - default: - break - } - - if self.localAuthenticationService.isProtectionSet { - NSLog("[NotificationService] notificationContentForEvent: Resetting title and body because app protection is set") - notificationBody = NSString.localizedUserNotificationString(forKey: "MESSAGE_PROTECTED", arguments: []) - notificationTitle = nil - } - - guard notificationBody != nil else { - NSLog("[NotificationService] notificationContentForEvent: notificationBody is nil") + if self.localAuthenticationService.isProtectionSet { + NSLog("[NotificationService] notificationContentForEvent: Resetting title and body because app protection is set") + notificationBody = NSString.localizedUserNotificationString(forKey: "MESSAGE_PROTECTED", arguments: []) + notificationTitle = nil + } + + guard notificationBody != nil else { + NSLog("[NotificationService] notificationContentForEvent: notificationBody is nil") + onComplete(nil) + return + } + + let notificationContent = self.notificationContent(withTitle: notificationTitle, + body: notificationBody, + threadIdentifier: threadIdentifier, + userId: currentUserId, + event: event, + pushRule: pushRule) + + NSLog("[NotificationService] notificationContentForEvent: Calling onComplete.") + onComplete(notificationContent) + case .failure(let error): + NSLog("[NotificationService] notificationContentForEvent: error: \(error)") onComplete(nil) - return } - - let notificationContent = self.notificationContent(withTitle: notificationTitle, - body: notificationBody, - threadIdentifier: threadIdentifier, - userId: currentUserId, - event: event, - pushRule: pushRule) - - NSLog("[NotificationService] notificationContentForEvent: Calling onComplete.") - onComplete(notificationContent) - } + }) } func notificationContent(withTitle title: String?, @@ -594,40 +451,3 @@ class NotificationService: UNNotificationServiceExtension { } } - -extension MXRoom { - - func getRoomPushRule() -> MXPushRule? { - guard let rules = self.mxSession.notificationCenter.rules.global.room else { - return nil - } - - for rule in rules { - guard let pushRule = rule as? MXPushRule else { continue } - // the rule id is the room Id - // it is the server trick to avoid duplicated rule on the same room. - if pushRule.ruleId == self.roomId { - return pushRule - } - } - - return nil - } - - var isMentionsOnly: Bool { - // Check push rules at room level - guard let rule = self.getRoomPushRule() else { - return false - } - - for ruleAction in rule.actions { - guard let action = ruleAction as? MXPushRuleAction else { continue } - if action.actionType == MXPushRuleActionTypeDontNotify { - return rule.enabled - } - } - - return false - } - -} From b36b66190a2f8579e59fc3b0ced17d7f15e19eed Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Thu, 22 Oct 2020 17:27:51 +0300 Subject: [PATCH 10/34] Remove NSEMemoryStore --- Riot.xcodeproj/project.pbxproj | 4 - RiotNSE/NSEMemoryStore.swift | 131 --------------------------------- 2 files changed, 135 deletions(-) delete mode 100644 RiotNSE/NSEMemoryStore.swift diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index 4964ea84a..21367b38f 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -884,7 +884,6 @@ EC85D752247C0F52002C44C9 /* UNUserNotificationCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC85D750247C0E8F002C44C9 /* UNUserNotificationCenter.swift */; }; EC85D754247C0F5B002C44C9 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC85D753247C0F5B002C44C9 /* Constants.swift */; }; EC85D755247C0F84002C44C9 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC85D753247C0F5B002C44C9 /* Constants.swift */; }; - EC85D757247E700F002C44C9 /* NSEMemoryStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC85D756247E700F002C44C9 /* NSEMemoryStore.swift */; }; EC9A3EC524E1616900A8CFAE /* PushNotificationStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC9A3EC424E1616900A8CFAE /* PushNotificationStore.swift */; }; EC9A3EC624E1632C00A8CFAE /* PushNotificationStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC9A3EC424E1616900A8CFAE /* PushNotificationStore.swift */; }; EC9A3EC724E1634100A8CFAE /* KeyValueStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC1CA87124C823E700DE9EBF /* KeyValueStore.swift */; }; @@ -2113,7 +2112,6 @@ EC85D74E2477E614002C44C9 /* RiotNSE.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RiotNSE.entitlements; sourceTree = ""; }; EC85D750247C0E8F002C44C9 /* UNUserNotificationCenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UNUserNotificationCenter.swift; sourceTree = ""; }; EC85D753247C0F5B002C44C9 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; - EC85D756247E700F002C44C9 /* NSEMemoryStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSEMemoryStore.swift; sourceTree = ""; }; EC9A3EC424E1616900A8CFAE /* PushNotificationStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PushNotificationStore.swift; sourceTree = ""; }; ECAE7AE424EC0E01002FA813 /* TableViewSections.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewSections.swift; sourceTree = ""; }; ECAE7AE624EC15F7002FA813 /* Section.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Section.swift; sourceTree = ""; }; @@ -5144,7 +5142,6 @@ children = ( EC85D74E2477E614002C44C9 /* RiotNSE.entitlements */, EC85D7452477E5F7002C44C9 /* NotificationService.swift */, - EC85D756247E700F002C44C9 /* NSEMemoryStore.swift */, EC85D7472477E5F7002C44C9 /* Info.plist */, EC1CA8D924D811B400DE9EBF /* NSE-Common.xcconfig */, EC1CA8BC24D1B4CF00DE9EBF /* NSE-Debug.xcconfig */, @@ -6159,7 +6156,6 @@ files = ( EC85D74F2477E8EB002C44C9 /* RiotSettings.swift in Sources */, 32FD756824D2AD5100BA7B37 /* BuildSettings.swift in Sources */, - EC85D757247E700F002C44C9 /* NSEMemoryStore.swift in Sources */, EC2B4EF224A1EF34005EB739 /* DataProtectionHelper.swift in Sources */, EC85D7462477E5F7002C44C9 /* NotificationService.swift in Sources */, 32FD755424D074C700BA7B37 /* CommonConfiguration.swift in Sources */, diff --git a/RiotNSE/NSEMemoryStore.swift b/RiotNSE/NSEMemoryStore.swift deleted file mode 100644 index e927df5a0..000000000 --- a/RiotNSE/NSEMemoryStore.swift +++ /dev/null @@ -1,131 +0,0 @@ -/* - Copyright 2020 New Vector Ltd - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -import Foundation -import MatrixSDK - -// error domain -let NSEMemoryStoreErrorDomain: String = "NSEMemoryStoreErrorDomain" - -// error codes -enum NSEMemoryStoreErrorCode: Int { - case userIDMissing = 1001 // User ID is missing in credentials -} - -/// Fake memory store implementation. Uses some real values from an MXFileStore instance. -class NSEMemoryStore: MXMemoryStore { - - // In-memory value for eventStreamToken. Will be used as eventStreamToken if provided. - private var lastStoredEventStreamToken: String? - private var credentials: MXCredentials - // real store - private var fileStore: MXFileStore! - private var myUser: MXUser? - - init(withCredentials credentials: MXCredentials) { - self.credentials = credentials - if fileStore == nil { - fileStore = MXFileStore(credentials: credentials) - // load real eventStreamToken - fileStore.loadMetaData() - } - } - - override func open(with credentials: MXCredentials, onComplete: (() -> Void)?, failure: ((Error?) -> Void)? = nil) { - super.open(with: credentials, onComplete: { - guard let userId = credentials.userId else { - failure?(NSError(domain: NSEMemoryStoreErrorDomain, - code: NSEMemoryStoreErrorCode.userIDMissing.rawValue, - userInfo: nil)) - return - } - // load session user before calling onComplete - self.fileStore.asyncUsers(withUserIds: [userId], success: { (users) in - if let user = users.first { - self.myUser = user - } - onComplete?() - }, failure: failure) - }, failure: failure) - } - - // Return real eventStreamToken, to be able to launch a meaningful background sync - override var eventStreamToken: String? { - get { - // if more up-to-date token exists, use it - if let token = lastStoredEventStreamToken { - return token - } - return fileStore.eventStreamToken - } set { - // store new token values in memory, and return these values in future reads - lastStoredEventStreamToken = newValue - } - } - - // Return real userAccountData, to be able to use push rules - override var userAccountData: [AnyHashable : Any]? { - get { - return fileStore.userAccountData - } set { - // no-op - } - } - - // This store should act like as a permanent one - override var isPermanent: Bool { - return true - } - - // Some mandatory methods to implement to be permanent - override func storeState(forRoom roomId: String, stateEvents: [MXEvent]) { - // no-op - } - - // Fetch real room state - override func state(ofRoom roomId: String, success: @escaping ([MXEvent]) -> Void, failure: ((Error) -> Void)? = nil) { - fileStore.state(ofRoom: roomId, success: success, failure: failure) - } - - // Fetch real soom summary - override func summary(ofRoom roomId: String) -> MXRoomSummary? { - return fileStore.summary(ofRoom: roomId) - } - - // Fetch real room account data - override func accountData(ofRoom roomId: String) -> MXRoomAccountData? { - return fileStore.accountData(ofRoom: roomId) - } - - // Override and return a user to be stored on session.myUser - override func user(withUserId userId: String) -> MXUser? { - if userId == credentials.userId, let myUser = myUser { - // if asking for session user and myUser is set, return that - return myUser - } - return MXUser(userId: userId) - } - - override var syncFilterId: String? { - get { - // Return real sync filter - return fileStore.syncFilterId - } set { - // no-op - } - } - -} From 2968b37b32dba9b15af5bacc1b11676b2432f343 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Thu, 22 Oct 2020 17:28:49 +0300 Subject: [PATCH 11/34] Remove MatrixSDK SwiftSupport subspec --- Podfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/Podfile b/Podfile index ec37a426d..d049c6b22 100644 --- a/Podfile +++ b/Podfile @@ -35,7 +35,6 @@ end # Method to import the right MatrixKit flavour def import_MatrixKit pod 'MatrixSDK', $matrixSDKVersionSpec - pod 'MatrixSDK/SwiftSupport', $matrixSDKVersionSpec pod 'MatrixSDK/JingleCallStack', $matrixSDKVersionSpec pod 'MatrixKit', $matrixKitVersionSpec end @@ -43,7 +42,6 @@ end # Method to import the right MatrixKit/AppExtension flavour def import_MatrixKitAppExtension pod 'MatrixSDK', $matrixSDKVersionSpec - pod 'MatrixSDK/SwiftSupport', $matrixSDKVersionSpec pod 'MatrixKit/AppExtension', $matrixKitVersionSpec end From eab8d1284583fea1772d9979081cbadc88b94994 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Fri, 23 Oct 2020 18:53:46 +0300 Subject: [PATCH 12/34] Remove commented code --- RiotNSE/NotificationService.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index 4cbe6a317..c70fce918 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -272,8 +272,6 @@ class NotificationService: UNNotificationServiceExtension { msgType = nil } - let isIncomingEvent = event.sender != currentUserId - // Display the room name only if it is different than the sender name if roomDisplayName != nil && roomDisplayName != eventSenderName { notificationTitle = NSString.localizedUserNotificationString(forKey: "MSG_FROM_USER_IN_ROOM_TITLE", arguments: [eventSenderName as Any, roomDisplayName as Any]) From db4ba58399e25a3cf266f8469a37cccfe798f10b Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Tue, 8 Dec 2020 22:01:46 +0100 Subject: [PATCH 13/34] Plugged BuildSettings.messageDetailsAllowShare to self.allowActionsInDocumentPreview MXKRoomViewController's property --- CHANGES.rst | 1 + Riot/Modules/Room/RoomViewController.m | 3 +++ 2 files changed, 4 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 156e69460..8ab48d846 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -31,6 +31,7 @@ Changes in 1.1.2 (2020-12-02) 🙌 Improvements * Room History: Remove the report option for outgoing messages. * Empty views: Add empty screen when there is nothing to display on home, people, favourites and rooms screen (#3836). + * BuildSettings.messageDetailsAllowShare now hide /show action button in document preview 🐛 Bugfix * Restore the modular widget events in the rooms histories. diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 6d9e8e2bb..27b14118f 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -294,6 +294,9 @@ // Listen to the event sent state changes [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(eventDidChangeSentState:) name:kMXEventDidChangeSentStateNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(eventDidChangeIdentifier:) name:kMXEventDidChangeIdentifierNotification object:nil]; + + // Show / hide actions button in document preview according BuildSettings + self.allowActionsInDocumentPreview = BuildSettings.messageDetailsAllowShare; } - (void)viewDidLoad From c46360f77ce99cde2063dd6f0941c1f7497b8a06 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Wed, 9 Dec 2020 10:15:47 +0100 Subject: [PATCH 14/34] Update CHANGES.rst Co-authored-by: manuroe --- CHANGES.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 8ab48d846..3e0c10271 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -31,7 +31,7 @@ Changes in 1.1.2 (2020-12-02) 🙌 Improvements * Room History: Remove the report option for outgoing messages. * Empty views: Add empty screen when there is nothing to display on home, people, favourites and rooms screen (#3836). - * BuildSettings.messageDetailsAllowShare now hide /show action button in document preview + * BuildSettings.messageDetailsAllowShare now hide /show action button in document preview (#3864). 🐛 Bugfix * Restore the modular widget events in the rooms histories. From c842e0bf938460853dfba5bd7db9018061bb47b5 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Wed, 9 Dec 2020 14:01:45 +0300 Subject: [PATCH 15/34] Clean up resources after completion --- RiotNSE/NotificationService.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index c70fce918..759efca9d 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -183,6 +183,9 @@ class NotificationService: UNNotificationServiceExtension { NSLog("[NotificationService] processEvent: Calling content handler for: \(String(describing: event.eventId)), isUnwanted: \(isUnwantedNotification)") self.contentHandlers[event.eventId]?(content) + // clear maps + self.contentHandlers.removeValue(forKey: event.eventId) + self.bestAttemptContents.removeValue(forKey: event.eventId) } } @@ -196,6 +199,9 @@ class NotificationService: UNNotificationServiceExtension { // call contentHandler contentHandlers[eventId]?(content) + // clear maps + contentHandlers.removeValue(forKey: eventId) + bestAttemptContents.removeValue(forKey: eventId) } private func notificationContent(forEvent event: MXEvent, forAccount account: MXKAccount, onComplete: @escaping (UNNotificationContent?) -> Void) { From bd29f66c5af2d8064e90a34ffca1539986f93de8 Mon Sep 17 00:00:00 2001 From: manuroe Date: Wed, 9 Dec 2020 18:49:20 +0100 Subject: [PATCH 16/34] PushNotificationService: Remove double start for profiling AnalyticsNoficationsTimeToDisplayContent --- Riot/Modules/Application/LegacyAppDelegate.m | 3 --- 1 file changed, 3 deletions(-) diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index 5cb448e23..c6be618c7 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -1107,9 +1107,6 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni - (void)pushNotificationService:(PushNotificationService *)pushNotificationService shouldNavigateToRoomWithId:(NSString *)roomId { - [MXSDKOptions.sharedInstance.profiler startMeasuringTaskWithName:AnalyticsNoficationsTimeToDisplayContent - category:AnalyticsNoficationsCategory]; - _lastNavigatedRoomIdFromPush = roomId; [self navigateToRoomById:roomId]; } From a81b5e3f7b60500af25a7168484467709876237d Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Fri, 11 Dec 2020 12:57:10 +0300 Subject: [PATCH 17/34] Force reloading account details on every notification --- RiotNSE/NotificationService.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index 759efca9d..e97eeab1b 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -110,6 +110,7 @@ class NotificationService: UNNotificationServiceExtension { } func setup(withRoomId roomId: String, eventId: String, completion: @escaping () -> Void) { + MXKAccountManager.shared()?.forceReloadAccounts() self.userAccount = MXKAccountManager.shared()?.activeAccounts.first if let userAccount = userAccount { if NotificationService.backgroundSyncService == nil { From c909654f35025dbb046542d414ac21f7c34814bb Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Fri, 11 Dec 2020 12:58:04 +0300 Subject: [PATCH 18/34] Update CHANGES.rst --- CHANGES.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 7f5e4c0f1..bd7fb8f6c 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -8,7 +8,7 @@ Changes to be released in next version * 🐛 Bugfix - * + * Refresh account details on NSE runs (#3719). ⚠️ API Changes * From db97912da38c5adac7e74b9488a6d09646ef925d Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Dec 2020 13:09:01 +0100 Subject: [PATCH 19/34] AuthenticationVC: Update SSO button wording. --- Riot/Assets/en.lproj/Vector.strings | 2 +- Riot/Generated/Strings.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index dc29d77fc..910125790 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -72,7 +72,7 @@ "auth_register" = "Register"; "auth_submit" = "Submit"; "auth_skip" = "Skip"; -"auth_login_single_sign_on" = "Sign in with single sign-on"; +"auth_login_single_sign_on" = "Sign In"; "auth_send_reset_email" = "Send Reset Email"; "auth_return_to_login" = "Return to login screen"; "auth_user_id_placeholder" = "Email or user name"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 46934e2a6..8bbb3550d 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -114,7 +114,7 @@ internal enum VectorL10n { internal static var authLogin: String { return VectorL10n.tr("Vector", "auth_login") } - /// Sign in with single sign-on + /// Sign In internal static var authLoginSingleSignOn: String { return VectorL10n.tr("Vector", "auth_login_single_sign_on") } From 15b17bf5d5fe9cf82c53ecef1c4f013f8f592ed1 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Dec 2020 13:09:08 +0100 Subject: [PATCH 20/34] Update changes --- CHANGES.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index bd7fb8f6c..a1c97f07d 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,7 +5,7 @@ Changes to be released in next version * 🙌 Improvements - * + * AuthVC: Update SSO button wording. 🐛 Bugfix * Refresh account details on NSE runs (#3719). From 6da7a798592979ebf46fa2a082780b9740537f4f Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Wed, 16 Dec 2020 18:17:18 +0300 Subject: [PATCH 21/34] version++ --- CHANGES.rst | 5 ++++- Podfile | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index a1c97f07d..600bac046 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,4 +1,4 @@ -Changes to be released in next version +Changes in 1.1.3 (2020-12-16) ================================================= ✨ Features @@ -22,6 +22,9 @@ Changes to be released in next version Others * +Improvements: + * Upgrade MatrixKit version ([v0.13.3](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.13.3)). + Changes in 1.1.2 (2020-12-02) ================================================= diff --git a/Podfile b/Podfile index 30a587c78..57559860c 100644 --- a/Podfile +++ b/Podfile @@ -11,7 +11,7 @@ use_frameworks! # - `{ {kit spec hash} => {sdk spec hash}` to depend on specific pod options (:git => …, :podspec => …) for each repo. Used by Fastfile during CI # # Warning: our internal tooling depends on the name of this variable name, so be sure not to change it -$matrixKitVersion = '= 0.13.2' +$matrixKitVersion = '= 0.13.3' # $matrixKitVersion = :local # $matrixKitVersion = {'develop' => 'develop'} From dbdb12dd8d51433ce2497e890a691e7b46c83fc8 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Wed, 16 Dec 2020 19:00:51 +0300 Subject: [PATCH 22/34] finish version++ --- Podfile.lock | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/Podfile.lock b/Podfile.lock index 497b76094..f3ca284a7 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -60,39 +60,37 @@ PODS: - MatomoTracker (7.2.2): - MatomoTracker/Core (= 7.2.2) - MatomoTracker/Core (7.2.2) - - MatrixKit (0.13.2): + - MatrixKit (0.13.3): - Down (~> 0.9.3) - DTCoreText (~> 1.6.23) - HPGrowingTextView (~> 1.1) - libPhoneNumber-iOS (~> 0.9.13) - - MatrixKit/Core (= 0.13.2) - - MatrixSDK (= 0.17.4) - - MatrixKit/AppExtension (0.13.2): + - MatrixKit/Core (= 0.13.3) + - MatrixSDK (= 0.17.5) + - MatrixKit/AppExtension (0.13.3): - Down (~> 0.9.3) - DTCoreText (~> 1.6.23) - DTCoreText/Extension - HPGrowingTextView (~> 1.1) - libPhoneNumber-iOS (~> 0.9.13) - - MatrixSDK (= 0.17.4) - - MatrixKit/Core (0.13.2): + - MatrixSDK (= 0.17.5) + - MatrixKit/Core (0.13.3): - Down (~> 0.9.3) - DTCoreText (~> 1.6.23) - HPGrowingTextView (~> 1.1) - libPhoneNumber-iOS (~> 0.9.13) - - MatrixSDK (= 0.17.4) - - MatrixSDK (0.17.4): - - MatrixSDK/Core (= 0.17.4) - - MatrixSDK/Core (0.17.4): + - MatrixSDK (= 0.17.5) + - MatrixSDK (0.17.5): + - MatrixSDK/Core (= 0.17.5) + - MatrixSDK/Core (0.17.5): - AFNetworking (~> 4.0.0) - GZIP (~> 1.3.0) - libbase58 (~> 0.1.4) - OLMKit (~> 3.1.0) - Realm (= 10.1.4) - - MatrixSDK/JingleCallStack (0.17.4): + - MatrixSDK/JingleCallStack (0.17.5): - JitsiMeetSDK (= 2.11.0) - MatrixSDK/Core - - MatrixSDK/SwiftSupport (0.17.4): - - MatrixSDK/Core - OLMKit (3.1.0): - OLMKit/olmc (= 3.1.0) - OLMKit/olmcpp (= 3.1.0) @@ -129,11 +127,10 @@ DEPENDENCIES: - KeychainAccess (~> 4.2.1) - KTCenterFlowLayout (~> 1.3.1) - MatomoTracker (~> 7.2.2) - - MatrixKit (= 0.13.2) - - MatrixKit/AppExtension (= 0.13.2) + - MatrixKit (= 0.13.3) + - MatrixKit/AppExtension (= 0.13.3) - MatrixSDK - MatrixSDK/JingleCallStack - - MatrixSDK/SwiftSupport - OLMKit - ReadMoreTextView (~> 3.0.1) - Reusable (~> 4.1) @@ -202,8 +199,8 @@ SPEC CHECKSUMS: LoggerAPI: ad9c4a6f1e32f518fdb43a1347ac14d765ab5e3d Logging: beeb016c9c80cf77042d62e83495816847ef108b MatomoTracker: a59ec4da0f580be57bdc6baa708a71a86532a832 - MatrixKit: 411348d4690b414e18958a0437c13edc21054a18 - MatrixSDK: 39282219213aebf621326f6335073b5a2b1e9113 + MatrixKit: 86f5239fab112ab0d3714fd1f366916ebd4d2b25 + MatrixSDK: aadf483438804d9e93d5d46ad3e5e832b7bb8848 OLMKit: 4ee0159d63feeb86d836fdcfefe418e163511639 ReadMoreTextView: 19147adf93abce6d7271e14031a00303fe28720d Realm: 80f4fb2971ccb9adc27a47d0955ae8e533a7030b @@ -215,6 +212,6 @@ SPEC CHECKSUMS: zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb -PODFILE CHECKSUM: 5f40ae970fc6a939c548fedf78849358a895c315 +PODFILE CHECKSUM: 22fcc5047435925034265c61cd821507736bf492 COCOAPODS: 1.10.0 From 16fe73c2c39a6297226ec7e7402072245d4dfe7e Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Wed, 16 Dec 2020 19:23:37 +0300 Subject: [PATCH 25/34] Prepare for new sprint --- CHANGES.rst | 24 ++++++++++++++++++++++++ Riot.xcodeproj/project.pbxproj | 8 ++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 600bac046..20509ff47 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,27 @@ +Changes to be released in next version +================================================= + +✨ Features + * + +🙌 Improvements + * + +🐛 Bugfix + * + +⚠️ API Changes + * + +🗣 Translations + * + +🧱 Build + * + +Others + * + Changes in 1.1.3 (2020-12-16) ================================================= diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index c454cec20..a243dd18b 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -7347,7 +7347,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1.1.3; + CURRENT_PROJECT_VERSION = 1.1.4; DEFINES_MODULE = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -7367,7 +7367,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.1.3; + MARKETING_VERSION = 1.1.4; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -7406,7 +7406,7 @@ CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 1.1.3; + CURRENT_PROJECT_VERSION = 1.1.4; DEFINES_MODULE = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -7419,7 +7419,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.1.3; + MARKETING_VERSION = 1.1.4; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; From 6998f313a6857ff568a4d9892f315f9e00650710 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Fri, 18 Dec 2020 14:14:35 +0300 Subject: [PATCH 26/34] Log memory footprint --- Riot.xcodeproj/project.pbxproj | 6 +++ Riot/Utils/Memory.swift | 69 +++++++++++++++++++++++++++++++ RiotNSE/NotificationService.swift | 46 +++++++++++++-------- 3 files changed, 104 insertions(+), 17 deletions(-) create mode 100644 Riot/Utils/Memory.swift diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index a243dd18b..fca434ab0 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -911,6 +911,8 @@ ECB5D98F255420F8000AD89C /* Keychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECB5D98E255420F8000AD89C /* Keychain.swift */; }; ECB5D9902554221F000AD89C /* Keychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECB5D98E255420F8000AD89C /* Keychain.swift */; }; ECDC15F224AF41D2003437CF /* FormattedBodyParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECDC15F124AF41D2003437CF /* FormattedBodyParser.swift */; }; + ECE36F7F258B578300122124 /* Memory.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECE36F7E258B578300122124 /* Memory.swift */; }; + ECE36F80258B579900122124 /* Memory.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECE36F7E258B578300122124 /* Memory.swift */; }; ECF57A4425090C23004BBF9D /* CreateRoomCoordinatorBridgePresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECF57A3825090C23004BBF9D /* CreateRoomCoordinatorBridgePresenter.swift */; }; ECF57A4525090C23004BBF9D /* CreateRoomCoordinatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECF57A3925090C23004BBF9D /* CreateRoomCoordinatorType.swift */; }; ECF57A4625090C23004BBF9D /* CreateRoomCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECF57A3A25090C23004BBF9D /* CreateRoomCoordinator.swift */; }; @@ -2149,6 +2151,7 @@ ECB101352477D00700CF8C11 /* UniversalLink.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UniversalLink.m; sourceTree = ""; }; ECB5D98E255420F8000AD89C /* Keychain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Keychain.swift; sourceTree = ""; }; ECDC15F124AF41D2003437CF /* FormattedBodyParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormattedBodyParser.swift; sourceTree = ""; }; + ECE36F7E258B578300122124 /* Memory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Memory.swift; sourceTree = ""; }; ECF57A3825090C23004BBF9D /* CreateRoomCoordinatorBridgePresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateRoomCoordinatorBridgePresenter.swift; sourceTree = ""; }; ECF57A3925090C23004BBF9D /* CreateRoomCoordinatorType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateRoomCoordinatorType.swift; sourceTree = ""; }; ECF57A3A25090C23004BBF9D /* CreateRoomCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateRoomCoordinator.swift; sourceTree = ""; }; @@ -5501,6 +5504,7 @@ EC2B4EF024A1EEBD005EB739 /* DataProtectionHelper.swift */, ECDC15F124AF41D2003437CF /* FormattedBodyParser.swift */, B158E72025485B9E000A7F75 /* Base32Coder.swift */, + ECE36F7E258B578300122124 /* Memory.swift */, ); path = Utils; sourceTree = ""; @@ -6216,6 +6220,7 @@ EC9A3EC624E1632C00A8CFAE /* PushNotificationStore.swift in Sources */, EC31F0952521FC4600D407DA /* PinCodePreferences.swift in Sources */, 32FD757424D2BEF700BA7B37 /* InfoPlist.swift in Sources */, + ECE36F80258B579900122124 /* Memory.swift in Sources */, ECB5D9902554221F000AD89C /* Keychain.swift in Sources */, EC31F09C2524AE1400D407DA /* BiometricsAuthenticationPresenter.swift in Sources */, EC85D752247C0F52002C44C9 /* UNUserNotificationCenter.swift in Sources */, @@ -6786,6 +6791,7 @@ B1B5574720EE6C4D00210D55 /* UsersDevicesViewController.m in Sources */, B1098BFF21ECFE65000DDA48 /* PasswordStrengthView.swift in Sources */, ECFBD5D2250A7AAF00DD5F5A /* ShowDirectoryViewState.swift in Sources */, + ECE36F7F258B578300122124 /* Memory.swift in Sources */, B1B558D220EF768F00210D55 /* RoomEncryptedDataBubbleCell.m in Sources */, B10A3E8F24FE4368007C380F /* Timeline_1.swift in Sources */, EC711BB024A63B58008F830C /* SecureBackupBannerCell.swift in Sources */, diff --git a/Riot/Utils/Memory.swift b/Riot/Utils/Memory.swift new file mode 100644 index 000000000..3869bf084 --- /dev/null +++ b/Riot/Utils/Memory.swift @@ -0,0 +1,69 @@ +// +// Copyright 2020 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +@objcMembers +class Memory: NSObject { + + private static var numberFormatter: NumberFormatter { + let formatter = NumberFormatter() + formatter.alwaysShowsDecimalSeparator = true + formatter.decimalSeparator = "." + formatter.groupingSeparator = "" + formatter.maximumFractionDigits = 2 + formatter.minimumFractionDigits = 2 + return formatter + } + + private static func memoryFootprint() -> Float? { + // The `TASK_VM_INFO_COUNT` and `TASK_VM_INFO_REV1_COUNT` macros are too + // complex for the Swift C importer, so we have to define them ourselves. + let TASK_VM_INFO_COUNT = mach_msg_type_number_t(MemoryLayout.size / MemoryLayout.size) + let TASK_VM_INFO_REV1_COUNT = mach_msg_type_number_t(MemoryLayout.offset(of: \task_vm_info_data_t.min_address)! / MemoryLayout.size) + var info = task_vm_info_data_t() + var count = TASK_VM_INFO_COUNT + let kr = withUnsafeMutablePointer(to: &info) { infoPtr in + infoPtr.withMemoryRebound(to: integer_t.self, capacity: Int(count)) { intPtr in + task_info(mach_task_self_, task_flavor_t(TASK_VM_INFO), intPtr, &count) + } + } + guard + kr == KERN_SUCCESS, + count >= TASK_VM_INFO_REV1_COUNT + else { return nil } + + let usedBytes = Float(info.phys_footprint) + return usedBytes + } + + static func formattedMemoryFootprint() -> String { + let usedBytes: UInt64? = UInt64(self.memoryFootprint() ?? 0) + let usedMB = Double(usedBytes ?? 0) / 1024 / 1024 + guard let formattedStr = numberFormatter.string(from: NSNumber(value: usedMB)) else { + return "" + } + return "\(formattedStr) MB" + } + + // For testing purposes + static func allocateMemoryOfSize(numberOfBytes: Int) { + var buffer = [UInt8](repeating: 0, count: numberOfBytes) + for i in 0 ..< numberOfBytes { + buffer[i] = UInt8(i % 7) + } + } +} diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index e97eeab1b..c4a300503 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -20,6 +20,8 @@ import MatrixSDK class NotificationService: UNNotificationServiceExtension { + // MARK: - Properties + /// Content handlers. Keys are eventId's private var contentHandlers: [String: ((UNNotificationContent) -> Void)] = [:] @@ -43,6 +45,8 @@ class NotificationService: UNNotificationServiceExtension { private var pushNotificationStore: PushNotificationStore = PushNotificationStore() private let localAuthenticationService = LocalAuthenticationService(pinCodePreferences: .shared) + // MARK: - Method Overrides + override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { // Set static application settings configuration.setupSettings() @@ -56,12 +60,13 @@ class NotificationService: UNNotificationServiceExtension { setupLogger() NSLog("[NotificationService] Instance: \(self), thread: \(Thread.current)") - + logMemory() + UNUserNotificationCenter.current().removeUnwantedNotifications() let userInfo = request.content.userInfo NSLog("[NotificationService] Payload came: \(userInfo)") - + // check if this is a Matrix notification guard let roomId = userInfo["room_id"] as? String, let eventId = userInfo["event_id"] as? String else { // it's not a Matrix notification, do not change the content @@ -96,10 +101,17 @@ class NotificationService: UNNotificationServiceExtension { // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used. NSLog("[NotificationService] serviceExtensionTimeWillExpire") + logMemory() // No-op here. If the process is killed by the OS due to time limit, it will also show the notification with the original content. } - func setupLogger() { + // MARK: - Private + + private func logMemory() { + NSLog("[NotificationService] Memory footprint: \(Memory.formattedMemoryFootprint())") + } + + private func setupLogger() { if !NotificationService.isLoggerInitialized { if isatty(STDERR_FILENO) == 0 { MXLogger.setSubLogName("nse") @@ -109,7 +121,7 @@ class NotificationService: UNNotificationServiceExtension { } } - func setup(withRoomId roomId: String, eventId: String, completion: @escaping () -> Void) { + private func setup(withRoomId roomId: String, eventId: String, completion: @escaping () -> Void) { MXKAccountManager.shared()?.forceReloadAccounts() self.userAccount = MXKAccountManager.shared()?.activeAccounts.first if let userAccount = userAccount { @@ -127,7 +139,7 @@ class NotificationService: UNNotificationServiceExtension { /// - Parameters: /// - eventId: Event identifier to mutate best attempt content /// - roomId: Room identifier to fetch display name - func preprocessPayload(forEventId eventId: String, roomId: String) { + private func preprocessPayload(forEventId eventId: String, roomId: String) { if localAuthenticationService.isProtectionSet { NSLog("[NotificationService] preprocessPayload: Do not preprocess because app protection is set") return @@ -141,7 +153,7 @@ class NotificationService: UNNotificationServiceExtension { } } - func fetchEvent(withEventId eventId: String, roomId: String, allowSync: Bool = true) { + private func fetchEvent(withEventId eventId: String, roomId: String, allowSync: Bool = true) { NSLog("[NotificationService] fetchEvent") NotificationService.backgroundSyncService.event(withEventId: eventId, @@ -155,7 +167,7 @@ class NotificationService: UNNotificationServiceExtension { NSLog("[NotificationService] fetchEvent: error: \(error)") self.fallbackToBestAttemptContent(forEventId: eventId) } - }) + }) } private func processEvent(_ event: MXEvent) { @@ -163,7 +175,7 @@ class NotificationService: UNNotificationServiceExtension { self.fallbackToBestAttemptContent(forEventId: event.eventId) return } - + self.notificationContent(forEvent: event, forAccount: userAccount) { (notificationContent) in var isUnwantedNotification = false @@ -359,12 +371,12 @@ class NotificationService: UNNotificationServiceExtension { }) } - func notificationContent(withTitle title: String?, - body: String?, - threadIdentifier: String?, - userId: String?, - event: MXEvent, - pushRule: MXPushRule?) -> UNNotificationContent { + private func notificationContent(withTitle title: String?, + body: String?, + threadIdentifier: String?, + userId: String?, + event: MXEvent, + pushRule: MXPushRule?) -> UNNotificationContent { let notificationContent = UNMutableNotificationContent() if let title = title { @@ -387,7 +399,7 @@ class NotificationService: UNNotificationServiceExtension { return notificationContent } - func notificationUserInfo(forEvent event: MXEvent, andUserId userId: String?) -> [AnyHashable: Any] { + private func notificationUserInfo(forEvent event: MXEvent, andUserId userId: String?) -> [AnyHashable: Any] { var notificationUserInfo: [AnyHashable: Any] = [ "type": "full", "room_id": event.roomId as Any, @@ -399,7 +411,7 @@ class NotificationService: UNNotificationServiceExtension { return notificationUserInfo } - func notificationSoundName(fromPushRule pushRule: MXPushRule?) -> String? { + private func notificationSoundName(fromPushRule pushRule: MXPushRule?) -> String? { var soundName: String? // Set sound name based on the value provided in action of MXPushRule @@ -418,7 +430,7 @@ class NotificationService: UNNotificationServiceExtension { return soundName } - func notificationCategoryIdentifier(forEvent event: MXEvent) -> String? { + private func notificationCategoryIdentifier(forEvent event: MXEvent) -> String? { let isNotificationContentShown = (!event.isEncrypted || self.showDecryptedContentInNotifications) && !localAuthenticationService.isProtectionSet From 79f1cd3a08bbc79f4ac46d9861767d5b141242d9 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Fri, 18 Dec 2020 15:03:00 +0300 Subject: [PATCH 27/34] Polish memory footprinter and logs --- Riot/Utils/Memory.swift | 33 ++++++++++++++++++++----------- RiotNSE/NotificationService.swift | 6 +++++- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/Riot/Utils/Memory.swift b/Riot/Utils/Memory.swift index 3869bf084..1c59a201b 100644 --- a/Riot/Utils/Memory.swift +++ b/Riot/Utils/Memory.swift @@ -16,9 +16,11 @@ import Foundation +/// Util class to log memory footprint and allocate memory for debugging purposes. @objcMembers class Memory: NSObject { + /// Memory formatter, uses exact 2 fraction digits and no grouping private static var numberFormatter: NumberFormatter { let formatter = NumberFormatter() formatter.alwaysShowsDecimalSeparator = true @@ -29,11 +31,16 @@ class Memory: NSObject { return formatter } + /// Details: https://developer.apple.com/forums/thread/105088 + /// - Returns: Current memory footprint private static func memoryFootprint() -> Float? { - // The `TASK_VM_INFO_COUNT` and `TASK_VM_INFO_REV1_COUNT` macros are too - // complex for the Swift C importer, so we have to define them ourselves. + // The `TASK_VM_INFO_COUNT` and `TASK_VM_INFO_REV1_COUNT` macros are too + // complex for the Swift C importer, so we have to define them ourselves. let TASK_VM_INFO_COUNT = mach_msg_type_number_t(MemoryLayout.size / MemoryLayout.size) - let TASK_VM_INFO_REV1_COUNT = mach_msg_type_number_t(MemoryLayout.offset(of: \task_vm_info_data_t.min_address)! / MemoryLayout.size) + guard let offset = MemoryLayout.offset(of: \task_vm_info_data_t.min_address) else { + return nil + } + let TASK_VM_INFO_REV1_COUNT = mach_msg_type_number_t(offset / MemoryLayout.size) var info = task_vm_info_data_t() var count = TASK_VM_INFO_COUNT let kr = withUnsafeMutablePointer(to: &info) { infoPtr in @@ -41,29 +48,31 @@ class Memory: NSObject { task_info(mach_task_self_, task_flavor_t(TASK_VM_INFO), intPtr, &count) } } - guard - kr == KERN_SUCCESS, - count >= TASK_VM_INFO_REV1_COUNT - else { return nil } + guard kr == KERN_SUCCESS, count >= TASK_VM_INFO_REV1_COUNT else { + return nil + } - let usedBytes = Float(info.phys_footprint) - return usedBytes + return Float(info.phys_footprint) } + /// Formatted memory footprint for debugging purposes + /// - Returns: Memory footprint in MBs as a readable string static func formattedMemoryFootprint() -> String { - let usedBytes: UInt64? = UInt64(self.memoryFootprint() ?? 0) - let usedMB = Double(usedBytes ?? 0) / 1024 / 1024 + let usedBytes = UInt64(self.memoryFootprint() ?? 0) + let usedMB = Double(usedBytes) / 1024 / 1024 guard let formattedStr = numberFormatter.string(from: NSNumber(value: usedMB)) else { return "" } return "\(formattedStr) MB" } - // For testing purposes + /// Allocates some memory + /// - Parameter numberOfBytes: Amount of memory to be allocated, in number of bytes static func allocateMemoryOfSize(numberOfBytes: Int) { var buffer = [UInt8](repeating: 0, count: numberOfBytes) for i in 0 ..< numberOfBytes { buffer[i] = UInt8(i % 7) } } + } diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index c4a300503..26c1c8c51 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -60,6 +60,8 @@ class NotificationService: UNNotificationServiceExtension { setupLogger() NSLog("[NotificationService] Instance: \(self), thread: \(Thread.current)") + + // log memory at the beginning of the process logMemory() UNUserNotificationCenter.current().removeUnwantedNotifications() @@ -101,7 +103,6 @@ class NotificationService: UNNotificationServiceExtension { // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used. NSLog("[NotificationService] serviceExtensionTimeWillExpire") - logMemory() // No-op here. If the process is killed by the OS due to time limit, it will also show the notification with the original content. } @@ -199,6 +200,9 @@ class NotificationService: UNNotificationServiceExtension { // clear maps self.contentHandlers.removeValue(forKey: event.eventId) self.bestAttemptContents.removeValue(forKey: event.eventId) + + // log memory again at the end of the process + self.logMemory() } } From 1ae06936ed2f7e00baaabc6eb52e130d6087e085 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Fri, 18 Dec 2020 15:03:58 +0300 Subject: [PATCH 28/34] Update CHANGES.rst --- CHANGES.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 20509ff47..e40fa5c9a 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,7 +5,7 @@ Changes to be released in next version * 🙌 Improvements - * + * Log NSE memory footprint for debugging purposes. 🐛 Bugfix * From ddcbe1ca52cdbc352f0f035465e9744c32549f7b Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Fri, 18 Dec 2020 15:43:06 +0300 Subject: [PATCH 29/34] version++ --- CHANGES.rst | 5 ++++- Podfile | 2 +- Riot.xcodeproj/project.pbxproj | 8 ++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index e40fa5c9a..c37b1888b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,4 +1,4 @@ -Changes to be released in next version +Changes in 1.1.3 (2020-12-18) ================================================= ✨ Features @@ -22,6 +22,9 @@ Changes to be released in next version Others * +Improvements: + * Upgrade MatrixKit version ([v0.13.4](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.13.4)). + Changes in 1.1.3 (2020-12-16) ================================================= diff --git a/Podfile b/Podfile index 57559860c..177c8627b 100644 --- a/Podfile +++ b/Podfile @@ -11,7 +11,7 @@ use_frameworks! # - `{ {kit spec hash} => {sdk spec hash}` to depend on specific pod options (:git => …, :podspec => …) for each repo. Used by Fastfile during CI # # Warning: our internal tooling depends on the name of this variable name, so be sure not to change it -$matrixKitVersion = '= 0.13.3' +$matrixKitVersion = '= 0.13.4' # $matrixKitVersion = :local # $matrixKitVersion = {'develop' => 'develop'} diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index fca434ab0..92722ae04 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -7353,7 +7353,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1.1.4; + CURRENT_PROJECT_VERSION = 1.1.3; DEFINES_MODULE = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -7373,7 +7373,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.1.4; + MARKETING_VERSION = 1.1.3; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -7412,7 +7412,7 @@ CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 1.1.4; + CURRENT_PROJECT_VERSION = 1.1.3; DEFINES_MODULE = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -7425,7 +7425,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.1.4; + MARKETING_VERSION = 1.1.3; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; From 771254a8fa52a6bf8a01d9e69cbdc0ab458679ac Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Fri, 18 Dec 2020 15:45:57 +0300 Subject: [PATCH 30/34] Update CHANGES.rst --- CHANGES.rst | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index c37b1888b..72449c393 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,38 +1,12 @@ Changes in 1.1.3 (2020-12-18) ================================================= -✨ Features - * - -🙌 Improvements - * Log NSE memory footprint for debugging purposes. - -🐛 Bugfix - * - -⚠️ API Changes - * - -🗣 Translations - * - -🧱 Build - * - -Others - * - -Improvements: - * Upgrade MatrixKit version ([v0.13.4](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.13.4)). - -Changes in 1.1.3 (2020-12-16) -================================================= - ✨ Features * 🙌 Improvements * AuthVC: Update SSO button wording. + * Log NSE memory footprint for debugging purposes. 🐛 Bugfix * Refresh account details on NSE runs (#3719). @@ -51,6 +25,7 @@ Others Improvements: * Upgrade MatrixKit version ([v0.13.3](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.13.3)). + * Upgrade MatrixKit version ([v0.13.4](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.13.4)). Changes in 1.1.2 (2020-12-02) ================================================= From e751d66c3daa45c3be9a70e46426e094ab703d16 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Fri, 18 Dec 2020 16:25:48 +0300 Subject: [PATCH 31/34] finish version++ --- Podfile.lock | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Podfile.lock b/Podfile.lock index f3ca284a7..d0d853a25 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -60,35 +60,35 @@ PODS: - MatomoTracker (7.2.2): - MatomoTracker/Core (= 7.2.2) - MatomoTracker/Core (7.2.2) - - MatrixKit (0.13.3): + - MatrixKit (0.13.4): - Down (~> 0.9.3) - DTCoreText (~> 1.6.23) - HPGrowingTextView (~> 1.1) - libPhoneNumber-iOS (~> 0.9.13) - - MatrixKit/Core (= 0.13.3) - - MatrixSDK (= 0.17.5) - - MatrixKit/AppExtension (0.13.3): + - MatrixKit/Core (= 0.13.4) + - MatrixSDK (= 0.17.6) + - MatrixKit/AppExtension (0.13.4): - Down (~> 0.9.3) - DTCoreText (~> 1.6.23) - DTCoreText/Extension - HPGrowingTextView (~> 1.1) - libPhoneNumber-iOS (~> 0.9.13) - - MatrixSDK (= 0.17.5) - - MatrixKit/Core (0.13.3): + - MatrixSDK (= 0.17.6) + - MatrixKit/Core (0.13.4): - Down (~> 0.9.3) - DTCoreText (~> 1.6.23) - HPGrowingTextView (~> 1.1) - libPhoneNumber-iOS (~> 0.9.13) - - MatrixSDK (= 0.17.5) - - MatrixSDK (0.17.5): - - MatrixSDK/Core (= 0.17.5) - - MatrixSDK/Core (0.17.5): + - MatrixSDK (= 0.17.6) + - MatrixSDK (0.17.6): + - MatrixSDK/Core (= 0.17.6) + - MatrixSDK/Core (0.17.6): - AFNetworking (~> 4.0.0) - GZIP (~> 1.3.0) - libbase58 (~> 0.1.4) - OLMKit (~> 3.1.0) - Realm (= 10.1.4) - - MatrixSDK/JingleCallStack (0.17.5): + - MatrixSDK/JingleCallStack (0.17.6): - JitsiMeetSDK (= 2.11.0) - MatrixSDK/Core - OLMKit (3.1.0): @@ -127,8 +127,8 @@ DEPENDENCIES: - KeychainAccess (~> 4.2.1) - KTCenterFlowLayout (~> 1.3.1) - MatomoTracker (~> 7.2.2) - - MatrixKit (= 0.13.3) - - MatrixKit/AppExtension (= 0.13.3) + - MatrixKit (= 0.13.4) + - MatrixKit/AppExtension (= 0.13.4) - MatrixSDK - MatrixSDK/JingleCallStack - OLMKit @@ -199,8 +199,8 @@ SPEC CHECKSUMS: LoggerAPI: ad9c4a6f1e32f518fdb43a1347ac14d765ab5e3d Logging: beeb016c9c80cf77042d62e83495816847ef108b MatomoTracker: a59ec4da0f580be57bdc6baa708a71a86532a832 - MatrixKit: 86f5239fab112ab0d3714fd1f366916ebd4d2b25 - MatrixSDK: aadf483438804d9e93d5d46ad3e5e832b7bb8848 + MatrixKit: 8dec5df9b3bb6621b8411ec37f93a0e3abe01db8 + MatrixSDK: 43d329b4070301f714808f02872ec1747c2f9b7d OLMKit: 4ee0159d63feeb86d836fdcfefe418e163511639 ReadMoreTextView: 19147adf93abce6d7271e14031a00303fe28720d Realm: 80f4fb2971ccb9adc27a47d0955ae8e533a7030b @@ -212,6 +212,6 @@ SPEC CHECKSUMS: zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb -PODFILE CHECKSUM: 22fcc5047435925034265c61cd821507736bf492 +PODFILE CHECKSUM: 198d9f0614bcf132a6aa31bdf8c1beb0360fdea7 COCOAPODS: 1.10.0 From 3f16bf82d8ee24d2703353bf58503a744f242012 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Fri, 18 Dec 2020 16:49:51 +0300 Subject: [PATCH 34/34] Prepare for new sprint --- CHANGES.rst | 24 ++++++++++++++++++++++++ Riot.xcodeproj/project.pbxproj | 8 ++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 72449c393..342e45a41 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,27 @@ +Changes to be released in next version +================================================= + +✨ Features + * + +🙌 Improvements + * + +🐛 Bugfix + * + +⚠️ API Changes + * + +🗣 Translations + * + +🧱 Build + * + +Others + * + Changes in 1.1.3 (2020-12-18) ================================================= diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index 92722ae04..fca434ab0 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -7353,7 +7353,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1.1.3; + CURRENT_PROJECT_VERSION = 1.1.4; DEFINES_MODULE = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -7373,7 +7373,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.1.3; + MARKETING_VERSION = 1.1.4; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -7412,7 +7412,7 @@ CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 1.1.3; + CURRENT_PROJECT_VERSION = 1.1.4; DEFINES_MODULE = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -7425,7 +7425,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.1.3; + MARKETING_VERSION = 1.1.4; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule;