From 095db614c18be06ad841adfec608b207e1a5e553 Mon Sep 17 00:00:00 2001 From: manuroe Date: Wed, 22 Sep 2021 11:06:55 +0200 Subject: [PATCH 01/42] Enable Swift Header for MatrixSDKTests PRODUCT_NAME for MatrixSDKTests is hardcoded like for MatrixSDK. It allows to have the same product name for iOS and macOS and, thus, the same swift headers --- MatrixSDK.xcodeproj/project.pbxproj | 22 +++++++++-------- MatrixSDKTests/MatrixSDKTestsSwiftHeader.h | 28 ++++++++++++++++++++++ 2 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 MatrixSDKTests/MatrixSDKTestsSwiftHeader.h diff --git a/MatrixSDK.xcodeproj/project.pbxproj b/MatrixSDK.xcodeproj/project.pbxproj index d7e16484af..3236262c5e 100644 --- a/MatrixSDK.xcodeproj/project.pbxproj +++ b/MatrixSDK.xcodeproj/project.pbxproj @@ -1654,6 +1654,7 @@ 322691351E5EFF8700966A6E /* MXDeviceListOperationsPool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MXDeviceListOperationsPool.m; path = MatrixSDK/Crypto/Data/MXDeviceListOperationsPool.m; sourceTree = SOURCE_ROOT; }; 3229534F25A5F7220012FCF0 /* MXBackgroundCryptoStore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXBackgroundCryptoStore.h; sourceTree = ""; }; 3229535025A5F7220012FCF0 /* MXBackgroundCryptoStore.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MXBackgroundCryptoStore.m; sourceTree = ""; }; + 322985CD26FAFC58001890BC /* MatrixSDKTestsSwiftHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MatrixSDKTestsSwiftHeader.h; sourceTree = ""; }; 322A51B41D9AB15900C8536D /* MXCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXCrypto.h; sourceTree = ""; }; 322A51B51D9AB15900C8536D /* MXCrypto.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXCrypto.m; sourceTree = ""; }; 322A51C11D9AC8FE00C8536D /* MXCryptoAlgorithms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXCryptoAlgorithms.h; sourceTree = ""; }; @@ -1989,7 +1990,7 @@ 32C6F92D19DD814400EA4E9C /* MatrixSDK.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MatrixSDK.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 32C6F93119DD814400EA4E9C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 32C6F93219DD814400EA4E9C /* MatrixSDK.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MatrixSDK.h; sourceTree = ""; }; - 32C6F93819DD814400EA4E9C /* MatrixSDKTests-iOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "MatrixSDKTests-iOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 32C6F93819DD814400EA4E9C /* MatrixSDKTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MatrixSDKTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 32C6F93B19DD814400EA4E9C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 32C78B65256CFC4D008130B1 /* MXCryptoVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXCryptoVersion.h; sourceTree = ""; }; 32C78B66256CFC4D008130B1 /* MXCryptoMigration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXCryptoMigration.m; sourceTree = ""; }; @@ -2224,7 +2225,7 @@ B1A026FF26162110001AADFF /* MXSpaceChildrenResponse.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MXSpaceChildrenResponse.m; sourceTree = ""; }; B1C854ED25E7B492005867D0 /* MXRoomType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXRoomType.h; sourceTree = ""; }; B1DDC9D52418098200D208E3 /* MXIncomingSASTransaction_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXIncomingSASTransaction_Private.h; sourceTree = ""; }; - B1E09A0E2397FA950057C069 /* MatrixSDKTests-macOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "MatrixSDKTests-macOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + B1E09A0E2397FA950057C069 /* MatrixSDKTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MatrixSDKTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; B1F939F426289F2600D0E525 /* MXSpaceChildContentTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXSpaceChildContentTests.swift; sourceTree = ""; }; B57EF0A39A7649D55CA1208A /* libPods-MatrixSDK-MatrixSDK-iOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-MatrixSDK-MatrixSDK-iOS.a"; sourceTree = BUILT_PRODUCTS_DIR; }; BD0431D223F108AED4C70A42 /* Pods-SDK-MatrixSDK-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDK-MatrixSDK-iOS.debug.xcconfig"; path = "Target Support Files/Pods-SDK-MatrixSDK-iOS/Pods-SDK-MatrixSDK-iOS.debug.xcconfig"; sourceTree = ""; }; @@ -3351,9 +3352,9 @@ isa = PBXGroup; children = ( 32C6F92D19DD814400EA4E9C /* MatrixSDK.framework */, - 32C6F93819DD814400EA4E9C /* MatrixSDKTests-iOS.xctest */, + 32C6F93819DD814400EA4E9C /* MatrixSDKTests.xctest */, B14EF36B2397E90400758AF0 /* MatrixSDK.framework */, - B1E09A0E2397FA950057C069 /* MatrixSDKTests-macOS.xctest */, + B1E09A0E2397FA950057C069 /* MatrixSDKTests.xctest */, ); name = Products; sourceTree = ""; @@ -3488,6 +3489,7 @@ B1F939F426289F2600D0E525 /* MXSpaceChildContentTests.swift */, 3A7B8CFD267FCD9B00D9DD96 /* MXDehydrationTests.m */, ECB6FA8D267CFF4300A941E4 /* MXCredentialsUnitTests.swift */, + 322985CD26FAFC58001890BC /* MatrixSDKTestsSwiftHeader.h */, ); path = MatrixSDKTests; sourceTree = ""; @@ -4853,7 +4855,7 @@ ); name = "MatrixSDKTests-iOS"; productName = MatrixSDKTests; - productReference = 32C6F93819DD814400EA4E9C /* MatrixSDKTests-iOS.xctest */; + productReference = 32C6F93819DD814400EA4E9C /* MatrixSDKTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; B14EF1C72397E90400758AF0 /* MatrixSDK-macOS */ = { @@ -4892,7 +4894,7 @@ ); name = "MatrixSDKTests-macOS"; productName = "MatrixSDKTests-macOS"; - productReference = B1E09A0E2397FA950057C069 /* MatrixSDKTests-macOS.xctest */; + productReference = B1E09A0E2397FA950057C069 /* MatrixSDKTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ @@ -6142,7 +6144,7 @@ LIBRARY_SEARCH_PATHS = "$(inherited)"; OTHER_LDFLAGS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = "org.matrix.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = MatrixSDKTests; SDKROOT = iphoneos; SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/MatrixSDKTests/MatrixSDKTests-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -6167,7 +6169,7 @@ LIBRARY_SEARCH_PATHS = "$(inherited)"; OTHER_LDFLAGS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = "org.matrix.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = MatrixSDKTests; SDKROOT = iphoneos; SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/MatrixSDKTests/MatrixSDKTests-Bridging-Header.h"; SWIFT_VERSION = 5.0; @@ -6250,7 +6252,7 @@ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "matrix.org.MatrixSDKTests-macOS"; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = MatrixSDKTests; SDKROOT = macosx; SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/MatrixSDKTests/MatrixSDKTests-Bridging-Header.h"; }; @@ -6279,7 +6281,7 @@ LIBRARY_SEARCH_PATHS = "$(inherited)"; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "matrix.org.MatrixSDKTests-macOS"; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = MatrixSDKTests; SDKROOT = macosx; SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/MatrixSDKTests/MatrixSDKTests-Bridging-Header.h"; }; diff --git a/MatrixSDKTests/MatrixSDKTestsSwiftHeader.h b/MatrixSDKTests/MatrixSDKTestsSwiftHeader.h new file mode 100644 index 0000000000..512cb0d74d --- /dev/null +++ b/MatrixSDKTests/MatrixSDKTestsSwiftHeader.h @@ -0,0 +1,28 @@ +// +// Copyright 2021 The Matrix.org Foundation C.I.C +// +// 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. +// + +#ifndef MatrixSDKTestsSwiftHeader_h +#define MatrixSDKTestsSwiftHeader_h + + +#if __has_include() +#import +#elif __has_include("MatrixSDKTests-Swift.h") +#import "MatrixSDKTests-Swift.h" +#else +#endif + +#endif /* MatrixSDKTestsSwiftHeader_h */ From 279de5415b4d0c83f85af80c6d434a2073b95f5a Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 23 Sep 2021 00:19:51 +0200 Subject: [PATCH 02/42] Tests: Add TestObserver to track open MXSession at end of a test --- MatrixSDK.xcodeproj/project.pbxproj | 20 ++++ MatrixSDKTests/MatrixSDKTestsData.m | 7 ++ MatrixSDKTests/Utils/MXSession.swift | 128 ++++++++++++++++++++++++ MatrixSDKTests/Utils/TestObserver.swift | 51 ++++++++++ 4 files changed, 206 insertions(+) create mode 100644 MatrixSDKTests/Utils/MXSession.swift create mode 100644 MatrixSDKTests/Utils/TestObserver.swift diff --git a/MatrixSDK.xcodeproj/project.pbxproj b/MatrixSDK.xcodeproj/project.pbxproj index 3236262c5e..d9fdce8146 100644 --- a/MatrixSDK.xcodeproj/project.pbxproj +++ b/MatrixSDK.xcodeproj/project.pbxproj @@ -107,6 +107,10 @@ 3229535225A5F7220012FCF0 /* MXBackgroundCryptoStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 3229534F25A5F7220012FCF0 /* MXBackgroundCryptoStore.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3229535325A5F7220012FCF0 /* MXBackgroundCryptoStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 3229535025A5F7220012FCF0 /* MXBackgroundCryptoStore.m */; }; 3229535425A5F7220012FCF0 /* MXBackgroundCryptoStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 3229535025A5F7220012FCF0 /* MXBackgroundCryptoStore.m */; }; + 322985CB26FAF898001890BC /* MXSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322985CA26FAF898001890BC /* MXSession.swift */; }; + 322985CC26FAF898001890BC /* MXSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322985CA26FAF898001890BC /* MXSession.swift */; }; + 322985CF26FBAE7B001890BC /* TestObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322985CE26FBAE7B001890BC /* TestObserver.swift */; }; + 322985D026FBAE7B001890BC /* TestObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322985CE26FBAE7B001890BC /* TestObserver.swift */; }; 322A51B61D9AB15900C8536D /* MXCrypto.h in Headers */ = {isa = PBXBuildFile; fileRef = 322A51B41D9AB15900C8536D /* MXCrypto.h */; settings = {ATTRIBUTES = (Public, ); }; }; 322A51B71D9AB15900C8536D /* MXCrypto.m in Sources */ = {isa = PBXBuildFile; fileRef = 322A51B51D9AB15900C8536D /* MXCrypto.m */; }; 322A51C31D9AC8FE00C8536D /* MXCryptoAlgorithms.h in Headers */ = {isa = PBXBuildFile; fileRef = 322A51C11D9AC8FE00C8536D /* MXCryptoAlgorithms.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -1654,7 +1658,9 @@ 322691351E5EFF8700966A6E /* MXDeviceListOperationsPool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MXDeviceListOperationsPool.m; path = MatrixSDK/Crypto/Data/MXDeviceListOperationsPool.m; sourceTree = SOURCE_ROOT; }; 3229534F25A5F7220012FCF0 /* MXBackgroundCryptoStore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXBackgroundCryptoStore.h; sourceTree = ""; }; 3229535025A5F7220012FCF0 /* MXBackgroundCryptoStore.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MXBackgroundCryptoStore.m; sourceTree = ""; }; + 322985CA26FAF898001890BC /* MXSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXSession.swift; sourceTree = ""; }; 322985CD26FAFC58001890BC /* MatrixSDKTestsSwiftHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MatrixSDKTestsSwiftHeader.h; sourceTree = ""; }; + 322985CE26FBAE7B001890BC /* TestObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestObserver.swift; sourceTree = ""; }; 322A51B41D9AB15900C8536D /* MXCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXCrypto.h; sourceTree = ""; }; 322A51B51D9AB15900C8536D /* MXCrypto.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXCrypto.m; sourceTree = ""; }; 322A51C11D9AC8FE00C8536D /* MXCryptoAlgorithms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXCryptoAlgorithms.h; sourceTree = ""; }; @@ -2636,6 +2642,15 @@ path = Trust; sourceTree = ""; }; + 322985C526FA66FD001890BC /* Utils */ = { + isa = PBXGroup; + children = ( + 322985CA26FAF898001890BC /* MXSession.swift */, + 322985CE26FBAE7B001890BC /* TestObserver.swift */, + ); + path = Utils; + sourceTree = ""; + }; 322A51B31D9AB13E00C8536D /* Crypto */ = { isa = PBXGroup; children = ( @@ -3410,6 +3425,7 @@ 32C6F93919DD814400EA4E9C /* MatrixSDKTests */ = { isa = PBXGroup; children = ( + 322985C526FA66FD001890BC /* Utils */, 3298ABD42637FA3100E40B06 /* TestPlans */, 32B477422638128700EA5800 /* MXAggregatedEditsUnitTests.m */, 32B477442638128700EA5800 /* MXAggregatedReferenceUnitTests.m */, @@ -5431,6 +5447,7 @@ files = ( 329E808F22512DF500A48C3A /* MXCryptoKeyVerificationTests.m in Sources */, 32B477822638133C00EA5800 /* MXFilterUnitTests.m in Sources */, + 322985CF26FBAE7B001890BC /* TestObserver.swift in Sources */, 32DC15D71A8DFF0D006F9AD3 /* MXNotificationCenterTests.m in Sources */, 329571991B024D2B00ABB3BA /* MXMockCallStack.m in Sources */, 3281E8A819E41A2000976E1A /* MatrixSDKTestsData.m in Sources */, @@ -5491,6 +5508,7 @@ 32D8CAC219DEE6ED002AF8A0 /* MXRestClientNoAuthAPITests.m in Sources */, 32FCAB4D19E578860049C555 /* MXRestClientTests.m in Sources */, 32C78BA7256D227D008130B1 /* MXCryptoMigrationTests.m in Sources */, + 322985CB26FAF898001890BC /* MXSession.swift in Sources */, 32EEA83F2603CA140041425B /* MXRestClientExtensionsTests.m in Sources */, 32C03CB62123076F00D92712 /* DirectRoomTests.m in Sources */, 329FB17C1A0A963700A5E88E /* MXRoomMemberTests.m in Sources */, @@ -5865,6 +5883,7 @@ files = ( B1E09A282397FD010057C069 /* MXMockCallStackCall.m in Sources */, B1E09A392397FD7D0057C069 /* MXMyUserTests.m in Sources */, + 322985D026FBAE7B001890BC /* TestObserver.swift in Sources */, B1E09A202397FCE90057C069 /* MXCryptoBackupTests.m in Sources */, B1E09A3B2397FD820057C069 /* MXStoreNoStoreTests.m in Sources */, 32B4778E2638133D00EA5800 /* MXFilterUnitTests.m in Sources */, @@ -5925,6 +5944,7 @@ B1E09A312397FD750057C069 /* MXSessionTests.m in Sources */, 32B477902638133D00EA5800 /* MXAggregatedReferenceUnitTests.m in Sources */, B1E09A322397FD750057C069 /* MXRoomTests.m in Sources */, + 322985CC26FAF898001890BC /* MXSession.swift in Sources */, 32C78BA8256D227D008130B1 /* MXCryptoMigrationTests.m in Sources */, B1E09A2F2397FD750057C069 /* MXErrorUnitTests.m in Sources */, B1660F1D260A20B900C3AA12 /* MXSpaceServiceTest.swift in Sources */, diff --git a/MatrixSDKTests/MatrixSDKTestsData.m b/MatrixSDKTests/MatrixSDKTestsData.m index 52996b7990..611311687b 100644 --- a/MatrixSDKTests/MatrixSDKTestsData.m +++ b/MatrixSDKTests/MatrixSDKTestsData.m @@ -21,6 +21,7 @@ #import "MXRestClient.h" #import "MXError.h" #import "MXNoStore.h" +#import "MatrixSDKTestsSwiftHeader.h" // Do not bother with retain cycles warnings in tests #pragma clang diagnostic push @@ -57,6 +58,12 @@ @interface MatrixSDKTestsData () @implementation MatrixSDKTestsData ++ (void)load +{ + // Be sure there is no open MXSession instances when ending a test + [TestObserver.shared trackMXSessions]; +} + - (id)init { if (self = [super init]) diff --git a/MatrixSDKTests/Utils/MXSession.swift b/MatrixSDKTests/Utils/MXSession.swift new file mode 100644 index 0000000000..16d03f5a05 --- /dev/null +++ b/MatrixSDKTests/Utils/MXSession.swift @@ -0,0 +1,128 @@ +// +// Copyright 2021 The Matrix.org Foundation C.I.C +// +// 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 + +// A structure that represents a tracked MXSession +struct TrackedMXSession { + /// A human readable id for the MXSession + let userDeviceId: String + + /// The call stack that instantiated it + let callStack: [String] +} + + +/// An extension to track alive MXSession instances in a static way. +/// A MXSession is considered alive between its init and close. +extension MXSession { + + // MARK: - Public + + /// Start tracking open MXSession instances. + @objc + class func trackOpenMXSessions() { + // Swizzle init and close methods to track active MXSessions + swizzleMethods(orignalSelector: #selector(MXSession.init(matrixRestClient:)), + swizzledSelector: #selector(MXSession.trackInit(matrixRestClient:))) + swizzleMethods(orignalSelector: #selector(MXSession.close), + swizzledSelector: #selector(MXSession.trackClose)) + } + + @objc + class var openMXSessionsCount: Int { + get { + trackedMXSessions.count + } + } + + /// Reset MXSession instances already tracked. + @objc + class func resetOpenMXSessions() { + trackedMXSessions.removeAll() + } + + /// Print all open MXSession instances. + @objc + class func logOpenMXSessions() { + for (trackId, trackedMXSession) in trackedMXSessions { + MXLog.error("MXSession(\(trackId)) for user \(trackedMXSession.userDeviceId) is not closed. It was created from:") + trackedMXSession.callStack.forEach { call in + MXLog.error(" - \(call)") + } + } + } + + // MARK: - Private + + // MARK: Properties + + /// All open sessions + private static var trackedMXSessions = Dictionary() + + /// Id that identifies the MXSession instance + private var trackId: String { + // Let's use the MXSession pointer to track it + "\(Unmanaged.passUnretained(self).toOpaque())" + } + + /// Human readable id + private var userDeviceId: String { + get { + // Manage string properties that are actually optional + [myUserId, myDeviceId] + .compactMap { $0 } + .joined(separator: ":") + } + } + + + // MARK: - Swizzling + + /// Exchange 2 methods implementations + /// - Parameters: + /// - orignalSelector: the original method + /// - swizzledSelector: the replacing method + private class func swizzleMethods(orignalSelector: Selector, swizzledSelector: Selector) { + guard + let originalMethod = class_getInstanceMethod(MXSession.self, orignalSelector), + let swizzledMethod = class_getInstanceMethod(MXSession.self, swizzledSelector) + else { return } + method_exchangeImplementations(originalMethod, swizzledMethod) + } + + /// Swizzled version of MXSession.init(matrixRestClient:) + @objc + private func trackInit(matrixRestClient: MXRestClient) -> MXSession { + // Call the original method. Note that implementations are exchanged + _ = self.trackInit(matrixRestClient: matrixRestClient) + + // And keep the call stack that created the session + let trackedMXSession = TrackedMXSession(userDeviceId: userDeviceId, callStack: Thread.callStackSymbols) + MXSession.trackedMXSessions.updateValue(trackedMXSession, forKey: self.trackId) + + return self + } + + /// Swizzled version of MXSession.close() + @objc + private func trackClose() { + // Call the original method. Note that implementations are exchanged + self.trackClose() + + MXSession.trackedMXSessions.removeValue(forKey: self.trackId) + } +} diff --git a/MatrixSDKTests/Utils/TestObserver.swift b/MatrixSDKTests/Utils/TestObserver.swift new file mode 100644 index 0000000000..5c28fa3b1c --- /dev/null +++ b/MatrixSDKTests/Utils/TestObserver.swift @@ -0,0 +1,51 @@ +// +// Copyright 2021 The Matrix.org Foundation C.I.C +// +// 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 XCTest + +/// TestObserver offers additional checks on tests +@objcMembers +class TestObserver: NSObject { + static let shared = TestObserver() + + var initialised: Bool = false + + /// Launch the tracking on open MXSessions + /// There will be `fatalError()` if there are still open MXSession at the end of a test + func trackMXSessions() { + if !initialised { + MXSession.trackOpenMXSessions() + XCTestObservationCenter.shared.addTestObserver(self) + initialised = true + } + } +} + +extension TestObserver: XCTestObservation { + func testCaseDidFinish(_ testCase: XCTestCase) { + // Crash in caa + let count = MXSession.openMXSessionsCount + if count > 0 { + MXSession.logOpenMXSessions() + + // All MXSessions must be closed at the end of the test + // Else, they will continue to run in background and affect tests performance + fatalError("Test \(testCase.name) did not close \(count) MXSession instances") + } + } +} From d8c9640c429620ecb5546ba3a41e8d00c0c6033a Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 23 Sep 2021 00:21:14 +0200 Subject: [PATCH 03/42] Enable Swift Header for MatrixSDKTests Forgot to commit those files --- .../xcshareddata/xcschemes/MatrixSDK-iOS.xcscheme | 4 ++-- .../xcshareddata/xcschemes/MatrixSDK-macOS.xcscheme | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/MatrixSDK.xcodeproj/xcshareddata/xcschemes/MatrixSDK-iOS.xcscheme b/MatrixSDK.xcodeproj/xcshareddata/xcschemes/MatrixSDK-iOS.xcscheme index f6ab6368f0..b2e100f011 100644 --- a/MatrixSDK.xcodeproj/xcshareddata/xcschemes/MatrixSDK-iOS.xcscheme +++ b/MatrixSDK.xcodeproj/xcshareddata/xcschemes/MatrixSDK-iOS.xcscheme @@ -29,7 +29,7 @@ @@ -57,7 +57,7 @@ diff --git a/MatrixSDK.xcodeproj/xcshareddata/xcschemes/MatrixSDK-macOS.xcscheme b/MatrixSDK.xcodeproj/xcshareddata/xcschemes/MatrixSDK-macOS.xcscheme index 17f1686fa1..84a69f6dba 100644 --- a/MatrixSDK.xcodeproj/xcshareddata/xcschemes/MatrixSDK-macOS.xcscheme +++ b/MatrixSDK.xcodeproj/xcshareddata/xcschemes/MatrixSDK-macOS.xcscheme @@ -29,7 +29,7 @@ @@ -64,6 +64,9 @@ + + From 009941116c8c5d1ed7dc8b902d5e1e789a9e6fee Mon Sep 17 00:00:00 2001 From: Doug Date: Thu, 23 Sep 2021 13:02:25 +0100 Subject: [PATCH 04/42] Combine ignoreMemberProfileChanges and eventsFilterForMessages into a single property called eventsFilterForLastMessage. --- MatrixSDK/Data/MXRoomSummaryUpdater.h | 9 +-------- MatrixSDK/Data/MXRoomSummaryUpdater.m | 10 +++------- changelog.d/4451.api | 1 + 3 files changed, 5 insertions(+), 15 deletions(-) create mode 100644 changelog.d/4451.api diff --git a/MatrixSDK/Data/MXRoomSummaryUpdater.h b/MatrixSDK/Data/MXRoomSummaryUpdater.h index 997764cda4..0ea2f7fc0f 100644 --- a/MatrixSDK/Data/MXRoomSummaryUpdater.h +++ b/MatrixSDK/Data/MXRoomSummaryUpdater.h @@ -43,14 +43,7 @@ Default is nil. All messages types are accepted. */ -@property (nonatomic) NSArray *eventsFilterForMessages; - -/** - If YES, ignore profile changes of room members as last message. - - Default is NO. - */ -@property (nonatomic) BOOL ignoreMemberProfileChanges; +@property (nonatomic) NSArray *eventsFilterForLastMessage; /** If YES, ignore redacted events as last message. diff --git a/MatrixSDK/Data/MXRoomSummaryUpdater.m b/MatrixSDK/Data/MXRoomSummaryUpdater.m index 546aad8bab..c57abbcec7 100644 --- a/MatrixSDK/Data/MXRoomSummaryUpdater.m +++ b/MatrixSDK/Data/MXRoomSummaryUpdater.m @@ -111,14 +111,10 @@ - (BOOL)session:(MXSession *)session updateRoomSummary:(MXRoomSummary *)summary BOOL updated = NO; // Accept event which type is in the filter list - if (event.eventId && (!_eventsFilterForMessages || (NSNotFound != [_eventsFilterForMessages indexOfObject:event.type]))) + if (event.eventId && (!_eventsFilterForLastMessage || (NSNotFound != [_eventsFilterForLastMessage indexOfObject:event.type]))) { - // Accept event related to profile change only if the flag is NO - if (!_ignoreMemberProfileChanges || !event.isUserProfileChange) - { - [summary updateLastMessage:[[MXRoomLastMessage alloc] initWithEvent:event]]; - updated = YES; - } + [summary updateLastMessage:[[MXRoomLastMessage alloc] initWithEvent:event]]; + updated = YES; } else if ([event.type isEqualToString:kRoomIsVirtualJSONKey]) { diff --git a/changelog.d/4451.api b/changelog.d/4451.api new file mode 100644 index 0000000000..e5e6f6b61c --- /dev/null +++ b/changelog.d/4451.api @@ -0,0 +1 @@ +MXRoomSummaryUpdater: Combine ignoreMemberProfileChanges and eventsFilterForMessages into a single property called eventsFilterForLastMessage. From 4820b569b6ce2cdd41cdf5e5036cd690a04262f6 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 23 Sep 2021 14:20:32 +0200 Subject: [PATCH 05/42] Tests: Refactor the MXSession leak detection --- MatrixSDK.xcodeproj/project.pbxproj | 6 ++ MatrixSDKTests/Utils/MXSession.swift | 97 ++++++++------------- MatrixSDKTests/Utils/MXSessionTracker.swift | 85 ++++++++++++++++++ MatrixSDKTests/Utils/TestObserver.swift | 17 ++-- 4 files changed, 134 insertions(+), 71 deletions(-) create mode 100644 MatrixSDKTests/Utils/MXSessionTracker.swift diff --git a/MatrixSDK.xcodeproj/project.pbxproj b/MatrixSDK.xcodeproj/project.pbxproj index d9fdce8146..9305a59534 100644 --- a/MatrixSDK.xcodeproj/project.pbxproj +++ b/MatrixSDK.xcodeproj/project.pbxproj @@ -111,6 +111,8 @@ 322985CC26FAF898001890BC /* MXSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322985CA26FAF898001890BC /* MXSession.swift */; }; 322985CF26FBAE7B001890BC /* TestObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322985CE26FBAE7B001890BC /* TestObserver.swift */; }; 322985D026FBAE7B001890BC /* TestObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322985CE26FBAE7B001890BC /* TestObserver.swift */; }; + 322985D226FC9E61001890BC /* MXSessionTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322985D126FC9E61001890BC /* MXSessionTracker.swift */; }; + 322985D326FC9E61001890BC /* MXSessionTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322985D126FC9E61001890BC /* MXSessionTracker.swift */; }; 322A51B61D9AB15900C8536D /* MXCrypto.h in Headers */ = {isa = PBXBuildFile; fileRef = 322A51B41D9AB15900C8536D /* MXCrypto.h */; settings = {ATTRIBUTES = (Public, ); }; }; 322A51B71D9AB15900C8536D /* MXCrypto.m in Sources */ = {isa = PBXBuildFile; fileRef = 322A51B51D9AB15900C8536D /* MXCrypto.m */; }; 322A51C31D9AC8FE00C8536D /* MXCryptoAlgorithms.h in Headers */ = {isa = PBXBuildFile; fileRef = 322A51C11D9AC8FE00C8536D /* MXCryptoAlgorithms.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -1661,6 +1663,7 @@ 322985CA26FAF898001890BC /* MXSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXSession.swift; sourceTree = ""; }; 322985CD26FAFC58001890BC /* MatrixSDKTestsSwiftHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MatrixSDKTestsSwiftHeader.h; sourceTree = ""; }; 322985CE26FBAE7B001890BC /* TestObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestObserver.swift; sourceTree = ""; }; + 322985D126FC9E61001890BC /* MXSessionTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXSessionTracker.swift; sourceTree = ""; }; 322A51B41D9AB15900C8536D /* MXCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXCrypto.h; sourceTree = ""; }; 322A51B51D9AB15900C8536D /* MXCrypto.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXCrypto.m; sourceTree = ""; }; 322A51C11D9AC8FE00C8536D /* MXCryptoAlgorithms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXCryptoAlgorithms.h; sourceTree = ""; }; @@ -2647,6 +2650,7 @@ children = ( 322985CA26FAF898001890BC /* MXSession.swift */, 322985CE26FBAE7B001890BC /* TestObserver.swift */, + 322985D126FC9E61001890BC /* MXSessionTracker.swift */, ); path = Utils; sourceTree = ""; @@ -5446,6 +5450,7 @@ buildActionMask = 2147483647; files = ( 329E808F22512DF500A48C3A /* MXCryptoKeyVerificationTests.m in Sources */, + 322985D226FC9E61001890BC /* MXSessionTracker.swift in Sources */, 32B477822638133C00EA5800 /* MXFilterUnitTests.m in Sources */, 322985CF26FBAE7B001890BC /* TestObserver.swift in Sources */, 32DC15D71A8DFF0D006F9AD3 /* MXNotificationCenterTests.m in Sources */, @@ -5882,6 +5887,7 @@ buildActionMask = 2147483647; files = ( B1E09A282397FD010057C069 /* MXMockCallStackCall.m in Sources */, + 322985D326FC9E61001890BC /* MXSessionTracker.swift in Sources */, B1E09A392397FD7D0057C069 /* MXMyUserTests.m in Sources */, 322985D026FBAE7B001890BC /* TestObserver.swift in Sources */, B1E09A202397FCE90057C069 /* MXCryptoBackupTests.m in Sources */, diff --git a/MatrixSDKTests/Utils/MXSession.swift b/MatrixSDKTests/Utils/MXSession.swift index 16d03f5a05..9b5435d25f 100644 --- a/MatrixSDKTests/Utils/MXSession.swift +++ b/MatrixSDKTests/Utils/MXSession.swift @@ -16,24 +16,21 @@ import Foundation -// A structure that represents a tracked MXSession -struct TrackedMXSession { - /// A human readable id for the MXSession - let userDeviceId: String - - /// The call stack that instantiated it - let callStack: [String] + +/// Delegate called on MXSession calls +protocol MXSessionInitCloseDelegate { + func didInit(mxSession: MXSession, callStack: [String]) + func willClose(mxSession: MXSession) } -/// An extension to track alive MXSession instances in a static way. -/// A MXSession is considered alive between its init and close. +/// An extension for reporting calls to `init(matrixRestClient:)` and `close()` on `MXSession` instances extension MXSession { // MARK: - Public + static var initCloseDelegate: MXSessionInitCloseDelegate? /// Start tracking open MXSession instances. - @objc class func trackOpenMXSessions() { // Swizzle init and close methods to track active MXSessions swizzleMethods(orignalSelector: #selector(MXSession.init(matrixRestClient:)), @@ -42,55 +39,9 @@ extension MXSession { swizzledSelector: #selector(MXSession.trackClose)) } - @objc - class var openMXSessionsCount: Int { - get { - trackedMXSessions.count - } - } - - /// Reset MXSession instances already tracked. - @objc - class func resetOpenMXSessions() { - trackedMXSessions.removeAll() - } - - /// Print all open MXSession instances. - @objc - class func logOpenMXSessions() { - for (trackId, trackedMXSession) in trackedMXSessions { - MXLog.error("MXSession(\(trackId)) for user \(trackedMXSession.userDeviceId) is not closed. It was created from:") - trackedMXSession.callStack.forEach { call in - MXLog.error(" - \(call)") - } - } - } - // MARK: - Private - // MARK: Properties - - /// All open sessions - private static var trackedMXSessions = Dictionary() - - /// Id that identifies the MXSession instance - private var trackId: String { - // Let's use the MXSession pointer to track it - "\(Unmanaged.passUnretained(self).toOpaque())" - } - - /// Human readable id - private var userDeviceId: String { - get { - // Manage string properties that are actually optional - [myUserId, myDeviceId] - .compactMap { $0 } - .joined(separator: ":") - } - } - - - // MARK: - Swizzling + // MARK: Swizzling /// Exchange 2 methods implementations /// - Parameters: @@ -109,20 +60,40 @@ extension MXSession { private func trackInit(matrixRestClient: MXRestClient) -> MXSession { // Call the original method. Note that implementations are exchanged _ = self.trackInit(matrixRestClient: matrixRestClient) - - // And keep the call stack that created the session - let trackedMXSession = TrackedMXSession(userDeviceId: userDeviceId, callStack: Thread.callStackSymbols) - MXSession.trackedMXSessions.updateValue(trackedMXSession, forKey: self.trackId) + if let initCloseDelegate = MXSession.initCloseDelegate { + initCloseDelegate.didInit(mxSession: self, callStack: Thread.callStackSymbols) + } return self } /// Swizzled version of MXSession.close() @objc private func trackClose() { + if let initCloseDelegate = MXSession.initCloseDelegate { + initCloseDelegate.willClose(mxSession: self) + } + // Call the original method. Note that implementations are exchanged self.trackClose() - - MXSession.trackedMXSessions.removeValue(forKey: self.trackId) + } +} + + +extension MXSession { + /// Id that identifies the MXSession instance + var trackId: String { + // Let's use the MXSession pointer to track it + "\(Unmanaged.passUnretained(self).toOpaque())" + } + + /// Human readable id + var userDeviceId: String { + get { + // Manage string properties that are actually optional + [myUserId, myDeviceId] + .compactMap { $0 } + .joined(separator: ":") + } } } diff --git a/MatrixSDKTests/Utils/MXSessionTracker.swift b/MatrixSDKTests/Utils/MXSessionTracker.swift new file mode 100644 index 0000000000..0e4c02bd1b --- /dev/null +++ b/MatrixSDKTests/Utils/MXSessionTracker.swift @@ -0,0 +1,85 @@ +// +// Copyright 2021 The Matrix.org Foundation C.I.C +// +// 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 + +/// A structure that represents a tracked MXSession +struct TrackedMXSession { + /// A human readable id for the MXSession + let userDeviceId: String + + /// The call stack that instantiated it + let callStack: [String] +} + +/// The singleton that tracks MXSessions life from init(matrixRestClient:) to close() +/// It can detect MXSession leaks that continue to run in background. +class MXSessionTracker { + + // MARK: - Public + + static let shared = MXSessionTracker() + + func trackMXSessions() { + MXSession.trackOpenMXSessions() + MXSession.initCloseDelegate = self + } + + var openMXSessionsCount: Int { + get { + trackedMXSessions.count + } + } + + func resetOpenMXSessions() { + trackedMXSessions.removeAll() + } + + func printOpenMXSessions() { + for (trackId, trackedMXSession) in trackedMXSessions { + MXLog.error("MXSession(\(trackId)) for user \(trackedMXSession.userDeviceId) is not closed. It was created from:") + trackedMXSession.callStack.forEach { call in + MXLog.error(" - \(call)") + } + } + } + + // MARK: - Private + + /// All open sessions + private var trackedMXSessions = Dictionary() + + func trackMXSession(mxSession: MXSession, callStack: [String]) { + let trackedMXSession = TrackedMXSession(userDeviceId: mxSession.userDeviceId, callStack: callStack) + trackedMXSessions.updateValue(trackedMXSession, forKey: mxSession.trackId) + } + + func untrackMXSession(mxSession: MXSession) { + trackedMXSessions.removeValue(forKey: mxSession.trackId) + } +} + +extension MXSessionTracker: MXSessionInitCloseDelegate { + + func didInit(mxSession: MXSession, callStack: [String]) { + trackMXSession(mxSession: mxSession, callStack: callStack) + } + + func willClose(mxSession: MXSession) { + untrackMXSession(mxSession: mxSession) + } +} + diff --git a/MatrixSDKTests/Utils/TestObserver.swift b/MatrixSDKTests/Utils/TestObserver.swift index 5c28fa3b1c..fac204ff58 100644 --- a/MatrixSDKTests/Utils/TestObserver.swift +++ b/MatrixSDKTests/Utils/TestObserver.swift @@ -23,25 +23,26 @@ import XCTest class TestObserver: NSObject { static let shared = TestObserver() - var initialised: Bool = false + var mxSessionTracker: MXSessionTracker { + get { + MXSessionTracker.shared + } + } /// Launch the tracking on open MXSessions /// There will be `fatalError()` if there are still open MXSession at the end of a test func trackMXSessions() { - if !initialised { - MXSession.trackOpenMXSessions() - XCTestObservationCenter.shared.addTestObserver(self) - initialised = true - } + mxSessionTracker.trackMXSessions() + XCTestObservationCenter.shared.addTestObserver(self) } } extension TestObserver: XCTestObservation { func testCaseDidFinish(_ testCase: XCTestCase) { // Crash in caa - let count = MXSession.openMXSessionsCount + let count = mxSessionTracker.openMXSessionsCount if count > 0 { - MXSession.logOpenMXSessions() + mxSessionTracker.printOpenMXSessions() // All MXSessions must be closed at the end of the test // Else, they will continue to run in background and affect tests performance From 95e22fe8df28fd2c6b5b45735af7381ff862fb1c Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 23 Sep 2021 14:51:26 +0200 Subject: [PATCH 06/42] Tests: Create autorelease for MXSession instances --- MatrixSDKTests/MatrixSDKTestsData.h | 7 +++++++ MatrixSDKTests/MatrixSDKTestsData.m | 24 +++++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/MatrixSDKTests/MatrixSDKTestsData.h b/MatrixSDKTests/MatrixSDKTestsData.h index 6b9ed0ca1f..f536e8eb8c 100644 --- a/MatrixSDKTests/MatrixSDKTestsData.h +++ b/MatrixSDKTests/MatrixSDKTestsData.h @@ -173,7 +173,14 @@ onUnrecognizedCertificateBlock:(MXHTTPClientOnUnrecognizedCertificate)onUnrecogn #pragma mark Reference keeping + +/// Close automatically MXSession instances created by MatrixSDKTestsData. +/// True by default. +/// Those instances are closed on MatrixSDKTestsData.deinit() +@property (nonatomic) BOOL autoCloseMXSessions; + // Retain an object for the life of this MatrixSDKTestsData instance - (void)retain:(NSObject*)object; +- (void)release:(NSObject*)object; @end diff --git a/MatrixSDKTests/MatrixSDKTestsData.m b/MatrixSDKTests/MatrixSDKTestsData.m index 611311687b..bf1cad5854 100644 --- a/MatrixSDKTests/MatrixSDKTestsData.m +++ b/MatrixSDKTests/MatrixSDKTestsData.m @@ -70,6 +70,7 @@ - (id)init { _startDate = [NSDate date]; _retainedObjects = [NSMutableArray array]; + _autoCloseMXSessions = YES; } return self; @@ -77,7 +78,7 @@ - (id)init - (void)dealloc { - _retainedObjects = [NSMutableArray array]; + [self releaseRetainedObjects]; } - (void)getBobCredentials:(XCTestCase*)testCase @@ -1025,6 +1026,27 @@ - (void)retain:(NSObject*)object [self.retainedObjects addObject:object]; } +- (void)release:(NSObject*)object +{ + [self.retainedObjects addObject:object]; +} + +- (void)releaseRetainedObjects +{ + if (_autoCloseMXSessions) + { + for (NSObject *object in _retainedObjects) + { + if ([object isKindOfClass:MXSession.class]) + { + MXSession *mxSession = (MXSession*)object; + [mxSession close]; + } + } + } + _retainedObjects = nil; +} + @end #pragma clang diagnostic pop From b0819f5534ebbdcd75eb04f401619c64912539c4 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 23 Sep 2021 15:09:32 +0200 Subject: [PATCH 07/42] Tests: Remove retain cycle on MatrixSDKTestsData --- MatrixSDKTests/MatrixSDKTestsE2EData.m | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/MatrixSDKTests/MatrixSDKTestsE2EData.m b/MatrixSDKTests/MatrixSDKTestsE2EData.m index f27ce3a1c9..5d2848a717 100644 --- a/MatrixSDKTests/MatrixSDKTestsE2EData.m +++ b/MatrixSDKTests/MatrixSDKTestsE2EData.m @@ -26,14 +26,13 @@ #import "MXNoStore.h" @interface MatrixSDKTestsE2EData () -{ - MatrixSDKTestsData *matrixSDKTestsData; -} + +@property (nonatomic, weak) MatrixSDKTestsData *matrixSDKTestsData; @end @implementation MatrixSDKTestsE2EData -@synthesize messagesFromAlice, messagesFromBob; +@synthesize matrixSDKTestsData, messagesFromAlice, messagesFromBob; - (instancetype)initWithMatrixSDKTestsData:(MatrixSDKTestsData *)theMatrixSDKTestsData { From c2d9926adbdbedf71fb073608867e3bd8bfa5a1b Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 23 Sep 2021 15:21:50 +0200 Subject: [PATCH 08/42] Tests: Make sure that all MXSessions are closed at the end of a test --- MatrixSDKTests/MXAccountDataTests.m | 4 ++ MatrixSDKTests/MXAggregatedEditsTests.m | 2 + MatrixSDKTests/MXAggregatedReactionTests.m | 3 ++ MatrixSDKTests/MXAggregatedReferenceTests.m | 1 + .../MXBackgroundSyncServiceTests.swift | 4 ++ MatrixSDKTests/MXCrossSigningTests.m | 1 + MatrixSDKTests/MXCryptoBackupTests.m | 2 + MatrixSDKTests/MXCryptoTests.m | 15 ++++++++ MatrixSDKTests/MXDehydrationTests.m | 1 + MatrixSDKTests/MXEventTests.m | 1 + MatrixSDKTests/MXLazyLoadingTests.m | 2 + MatrixSDKTests/MXMyUserTests.m | 3 ++ MatrixSDKTests/MXNotificationCenterTests.m | 5 +++ MatrixSDKTests/MXRoomStateDynamicTests.m | 4 ++ MatrixSDKTests/MXRoomStateTests.m | 37 +++++++++++++++++++ MatrixSDKTests/MXRoomSummaryTests.m | 6 +++ MatrixSDKTests/MXRoomTests.m | 15 ++++++++ MatrixSDKTests/MXSessionTests.m | 18 +++++++++ MatrixSDKTests/MXStoreTests.m | 24 ++++++++++++ MatrixSDKTests/MXUserTests.m | 6 +++ 20 files changed, 154 insertions(+) diff --git a/MatrixSDKTests/MXAccountDataTests.m b/MatrixSDKTests/MXAccountDataTests.m index e22b8f950a..51467f6ff4 100644 --- a/MatrixSDKTests/MXAccountDataTests.m +++ b/MatrixSDKTests/MXAccountDataTests.m @@ -81,6 +81,7 @@ - (void)testIgnoreUsersStorage [matrixSDKTestsData doMXRestClientTestWithBobAndAliceInARoom:self readyToTest:^(MXRestClient *bobRestClient, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { MXSession *bobSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:bobSession]; MXFileStore *store = [[MXFileStore alloc] init]; [bobSession setStore:store success:^{ @@ -100,6 +101,7 @@ - (void)testIgnoreUsersStorage // Check the information have been permanently stored MXSession *bobSession2 = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:bobSession2]; MXFileStore *store2 = [[MXFileStore alloc] init]; [bobSession2 setStore:store2 success:^{ @@ -144,6 +146,7 @@ - (void)testIgnoreUserUpdateHasNoCollateralDamageOnPushRules [matrixSDKTestsData doMXRestClientTestWithBobAndAliceInARoom:self readyToTest:^(MXRestClient *bobRestClient, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { MXSession *bobSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:bobSession]; MXFileStore *store = [[MXFileStore alloc] init]; [bobSession setStore:store success:^{ @@ -165,6 +168,7 @@ - (void)testIgnoreUserUpdateHasNoCollateralDamageOnPushRules // Check the information have been permanently stored MXSession *bobSession2 = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:bobSession2]; MXFileStore *store2 = [[MXFileStore alloc] init]; [bobSession2 setStore:store2 success:^{ diff --git a/MatrixSDKTests/MXAggregatedEditsTests.m b/MatrixSDKTests/MXAggregatedEditsTests.m index 3760508ca1..1c786c2644 100644 --- a/MatrixSDKTests/MXAggregatedEditsTests.m +++ b/MatrixSDKTests/MXAggregatedEditsTests.m @@ -293,6 +293,7 @@ - (void)testEditsFromInitialSync // - Do an initial sync mxSession = [[MXSession alloc] initWithMatrixRestClient:restClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession setStore:[[MXMemoryStore alloc] init] success:^{ [mxSession start:^{ @@ -340,6 +341,7 @@ - (void)testFormatedEditsFromInitialSync // - Do an initial sync mxSession = [[MXSession alloc] initWithMatrixRestClient:restClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession setStore:[[MXMemoryStore alloc] init] success:^{ [mxSession start:^{ diff --git a/MatrixSDKTests/MXAggregatedReactionTests.m b/MatrixSDKTests/MXAggregatedReactionTests.m index 828e4fe763..e523a1bdb3 100644 --- a/MatrixSDKTests/MXAggregatedReactionTests.m +++ b/MatrixSDKTests/MXAggregatedReactionTests.m @@ -126,6 +126,7 @@ - (void)createScenarioWithAGappyInitialSync:(void(^)(MXSession *mxSession, MXRoo // - Do an initial sync MXSession *mxSession2 = [[MXSession alloc] initWithMatrixRestClient:restClient]; + [matrixSDKTestsData retain:mxSession2]; [mxSession2 setStore:[[MXMemoryStore alloc] init] success:^{ [mxSession2 start:^{ @@ -227,6 +228,7 @@ - (void)testAggregationsFromInitialSync // - Do an initial sync mxSession = [[MXSession alloc] initWithMatrixRestClient:restClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession setStore:[[MXMemoryStore alloc] init] success:^{ [mxSession start:^{ @@ -377,6 +379,7 @@ - (void)testUnreactAfterInitialSync // - Do an initial sync mxSession = [[MXSession alloc] initWithMatrixRestClient:restClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession setStore:[[MXMemoryStore alloc] init] success:^{ [mxSession start:^{ diff --git a/MatrixSDKTests/MXAggregatedReferenceTests.m b/MatrixSDKTests/MXAggregatedReferenceTests.m index 6cd37e40d0..e9fec4bc3b 100644 --- a/MatrixSDKTests/MXAggregatedReferenceTests.m +++ b/MatrixSDKTests/MXAggregatedReferenceTests.m @@ -134,6 +134,7 @@ - (void)testReferenceFromInitialSync // - Do an initial sync mxSession = [[MXSession alloc] initWithMatrixRestClient:restClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession setStore:[[MXMemoryStore alloc] init] success:^{ [mxSession start:^{ diff --git a/MatrixSDKTests/MXBackgroundSyncServiceTests.swift b/MatrixSDKTests/MXBackgroundSyncServiceTests.swift index 3b4457de4a..3492cb2065 100644 --- a/MatrixSDKTests/MXBackgroundSyncServiceTests.swift +++ b/MatrixSDKTests/MXBackgroundSyncServiceTests.swift @@ -109,6 +109,7 @@ class MXBackgroundSyncServiceTests: XCTestCase { // - Bob restarts their MXSession let newBobSession = MXSession(matrixRestClient: MXRestClient(credentials: bobCredentials, unrecognizedCertificateHandler: nil)) + self.testData.retain(newBobSession) newBobSession?.setStore(bobStore, completion: { (_) in newBobSession?.start(withSyncFilterId: bobStore.syncFilterId, completion: { (_) in @@ -198,6 +199,7 @@ class MXBackgroundSyncServiceTests: XCTestCase { // - Bob restarts their MXSession let newBobSession = MXSession(matrixRestClient: MXRestClient(credentials: bobCredentials, unrecognizedCertificateHandler: nil)) + self.testData.retain(newBobSession) newBobSession?.setStore(bobStore, completion: { (_) in newBobSession?.start(withSyncFilterId: bobStore.syncFilterId, completion: { (_) in @@ -306,6 +308,7 @@ class MXBackgroundSyncServiceTests: XCTestCase { // - Bob restarts their MXSession let newBobSession = MXSession(matrixRestClient: MXRestClient(credentials: bobCredentials, unrecognizedCertificateHandler: nil)) + self.testData.retain(newBobSession) newBobSession?.setStore(bobStore, completion: { (_) in newBobSession?.start(withSyncFilterId: bobStore.syncFilterId, completion: { (_) in // -> The message is available from MXSession and no more from MXBackgroundSyncService @@ -1315,6 +1318,7 @@ class MXBackgroundSyncServiceTests: XCTestCase { expectation.fulfill() return } + self.testData.retain(bobSession2) bobSession2.setStore(MXFileStore(), completion: { _ in bobSession2.start(completion: { (_) in diff --git a/MatrixSDKTests/MXCrossSigningTests.m b/MatrixSDKTests/MXCrossSigningTests.m index 2f2cf483fd..c5fbb2b04f 100644 --- a/MatrixSDKTests/MXCrossSigningTests.m +++ b/MatrixSDKTests/MXCrossSigningTests.m @@ -1239,6 +1239,7 @@ - (void)testMXCrossSigningResetDetectionAfterRestart // - Stop Alice first device MXSession *aliceSession2 = [[MXSession alloc] initWithMatrixRestClient:aliceSession.matrixRestClient]; + [matrixSDKTestsData retain:aliceSession2]; [aliceSession close]; // - Reset XS on this new device diff --git a/MatrixSDKTests/MXCryptoBackupTests.m b/MatrixSDKTests/MXCryptoBackupTests.m index a55d7eef8a..6b3b9b1c83 100644 --- a/MatrixSDKTests/MXCryptoBackupTests.m +++ b/MatrixSDKTests/MXCryptoBackupTests.m @@ -944,6 +944,7 @@ - (void)testCheckAndStartKeyBackupWhenRestartingAMatrixSession // - Restart alice session MXSession *aliceSession2 = [[MXSession alloc] initWithMatrixRestClient:aliceSession.matrixRestClient]; + [matrixSDKTestsData retain:aliceSession2]; [aliceSession close]; [aliceSession2 start:nil failure:^(NSError * _Nonnull error) { XCTFail(@"The request should not fail - NSError: %@", error); @@ -1445,6 +1446,7 @@ - (void)testLocalPrivateKey // - Restart the session MXSession *aliceSession2 = [[MXSession alloc] initWithMatrixRestClient:aliceSession.matrixRestClient]; + [matrixSDKTestsData retain:aliceSession2]; [aliceSession close]; [aliceSession2 start:^{ XCTAssertTrue(aliceSession2.crypto.backup.hasPrivateKeyInCryptoStore); diff --git a/MatrixSDKTests/MXCryptoTests.m b/MatrixSDKTests/MXCryptoTests.m index 05b84210cd..8cc0b04a03 100644 --- a/MatrixSDKTests/MXCryptoTests.m +++ b/MatrixSDKTests/MXCryptoTests.m @@ -221,6 +221,8 @@ - (void)testCryptoPersistenceInStore MXFileStore *store = [[MXFileStore alloc] init]; mxSession2 = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession2]; + [mxSession2 setStore:store success:^{ XCTAssert(mxSession2.crypto, @"MXSession must recall that it has crypto engaged"); @@ -484,6 +486,7 @@ - (void)testAliceInACryptedRoomAfterInitialSync aliceSession = nil; MXSession *aliceSession2 = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + [matrixSDKTestsData retain:aliceSession2]; aliceSessionToClose = aliceSession2; @@ -646,6 +649,7 @@ - (void)testAliceAndBobInACryptedRoomFromInitialSync bobSession = nil; bobSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:bobSession]; aliceSessionToClose = aliceSession; bobSessionToClose = bobSession; @@ -2034,6 +2038,7 @@ - (void)testOlmSessionUnwedging // This forces her to use a new megolm session for sending message "11" // This will move the olm session ratchet to share this new megolm session MXSession *aliceSession1 = [[MXSession alloc] initWithMatrixRestClient:aliceSession.matrixRestClient]; + [aliceSession close]; [aliceSession1 setStore:[[MXFileStore alloc] init] success:^{ [aliceSession1 start:^{ @@ -2047,6 +2052,8 @@ - (void)testOlmSessionUnwedging // - Simulate Alice using a backup of her OS and make her crypto state like after the first message // Relaunch again alice MXSession *aliceSession2 = [[MXSession alloc] initWithMatrixRestClient:aliceSession1.matrixRestClient]; + [matrixSDKTestsData retain:aliceSession2]; + [aliceSession1 close]; [aliceSession2 setStore:[[MXFileStore alloc] init] success:^{ [aliceSession2 start:^{ @@ -2507,6 +2514,8 @@ - (void)testEnableEncryptionAfterNonCryptedMessages // [aliceSession close]; // // aliceSession2 = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; +// [matrixSDKTestsData retain:aliceSession2]; +// // [aliceSession2 start:^{ // // aliceSession2.crypto.warnOnUnknowDevices = NO; @@ -2537,6 +2546,8 @@ - (void)testEnableEncryptionAfterNonCryptedMessages // [aliceSession2 close]; // // aliceSession3 = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; +// [matrixSDKTestsData retain:aliceSession3]; +// // [aliceSession3 start:^{ // // aliceSession3.crypto.warnOnUnknowDevices = NO; @@ -3055,6 +3066,8 @@ - (void)testRestoreOlmOutboundKey // - Restart the session MXSession *aliceSession2 = [[MXSession alloc] initWithMatrixRestClient:aliceSession.matrixRestClient]; + [matrixSDKTestsData retain:aliceSession2] + ; [aliceSession close]; [aliceSession2 start:^{ MXOlmOutboundGroupSession *outboundSession = [aliceSession2.crypto.store outboundGroupSessionWithRoomId:roomId]; @@ -3088,6 +3101,8 @@ - (void)testDiscardAndRestoreOlmOutboundKey // - Restart the session MXSession *aliceSession2 = [[MXSession alloc] initWithMatrixRestClient:aliceSession.matrixRestClient]; + [matrixSDKTestsData retain:aliceSession2]; + [aliceSession close]; [aliceSession2 start:^{ MXOlmOutboundGroupSession *outboundSession = [aliceSession2.crypto.store outboundGroupSessionWithRoomId:roomId]; diff --git a/MatrixSDKTests/MXDehydrationTests.m b/MatrixSDKTests/MXDehydrationTests.m index bba8e3027f..fd64a271ea 100644 --- a/MatrixSDKTests/MXDehydrationTests.m +++ b/MatrixSDKTests/MXDehydrationTests.m @@ -289,6 +289,7 @@ -(void)testReceiveLiveMessageAfterDeviceRehydration MXRestClient *aliceRestClient = aliceSession2.matrixRestClient; MXSession *aliceSession3 = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + [self.matrixSDKTestsData retain:aliceSession3]; [aliceSession2 close]; diff --git a/MatrixSDKTests/MXEventTests.m b/MatrixSDKTests/MXEventTests.m index efee0a34f1..c2c8f46dc5 100644 --- a/MatrixSDKTests/MXEventTests.m +++ b/MatrixSDKTests/MXEventTests.m @@ -101,6 +101,7 @@ - (void)testIsState [matrixSDKTestsData doMXRestClientTestWithBobAndARoomWithMessages:self readyToTest:^(MXRestClient *bobRestClient, NSString *roomId, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ diff --git a/MatrixSDKTests/MXLazyLoadingTests.m b/MatrixSDKTests/MXLazyLoadingTests.m index 498d62e5bf..2d6e8d5597 100644 --- a/MatrixSDKTests/MXLazyLoadingTests.m +++ b/MatrixSDKTests/MXLazyLoadingTests.m @@ -884,6 +884,7 @@ - (void)checkRoomAfterLeavingWithLazyLoading:(BOOL)lazyLoading MXFileStore *store = [[MXFileStore alloc] init]; __block MXSession *aliceSession2 = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + [matrixSDKTestsData retain:aliceSession2]; [aliceSession2 setStore:store success:^{ [aliceSession2 start:^{ @@ -948,6 +949,7 @@ - (void)checkRoomAfterLeavingWithLazyLoading:(BOOL)lazyLoading MXFileStore *store = [[MXFileStore alloc] init]; MXSession *aliceSession3 = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + [matrixSDKTestsData retain:aliceSession3]; [aliceSession3 setStore:store success:^{ [aliceSession3 start:^{ diff --git a/MatrixSDKTests/MXMyUserTests.m b/MatrixSDKTests/MXMyUserTests.m index eb04e1f728..02a7411a1c 100644 --- a/MatrixSDKTests/MXMyUserTests.m +++ b/MatrixSDKTests/MXMyUserTests.m @@ -71,6 +71,7 @@ - (void)testSetDisplayName [matrixSDKTestsData doMXRestClientTestWithAlice:self readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + [matrixSDKTestsData retain:mxSession]; XCTAssertNil(mxSession.myUser, @"There should be no myUser while initialSync is not done"); @@ -108,6 +109,7 @@ - (void)testSetAvatarURL [matrixSDKTestsData doMXRestClientTestWithAlice:self readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -144,6 +146,7 @@ - (void)testSetPresence [matrixSDKTestsData doMXRestClientTestWithAlice:self readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ diff --git a/MatrixSDKTests/MXNotificationCenterTests.m b/MatrixSDKTests/MXNotificationCenterTests.m index aaf296bf7a..bf77c551e0 100644 --- a/MatrixSDKTests/MXNotificationCenterTests.m +++ b/MatrixSDKTests/MXNotificationCenterTests.m @@ -59,6 +59,7 @@ - (void)testNotificationCenterRulesReady [matrixSDKTestsData doMXRestClientTestWithBob:self readyToTest:^(MXRestClient *bobRestClient, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; XCTAssertNotNil(mxSession.notificationCenter); XCTAssertNil(mxSession.notificationCenter.rules); @@ -246,6 +247,8 @@ - (void)testDefaultDisplayNameCondition mxSession = bobSession; MXSession *aliceSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + [matrixSDKTestsData retain:aliceSession]; + [aliceSession start:^{ // Change alice name @@ -362,6 +365,8 @@ - (void)testRuleMatchingEvent mxSession = bobSession; MXSession *aliceSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + [matrixSDKTestsData retain:aliceSession]; + [aliceSession start:^{ // Change alice name diff --git a/MatrixSDKTests/MXRoomStateDynamicTests.m b/MatrixSDKTests/MXRoomStateDynamicTests.m index 0012d46768..4b9a75fa8a 100644 --- a/MatrixSDKTests/MXRoomStateDynamicTests.m +++ b/MatrixSDKTests/MXRoomStateDynamicTests.m @@ -112,6 +112,7 @@ - (void)testBackPaginationForScenario1 [self createScenario1:bobRestClient inRoom:roomId expectation:expectation onComplete:^{ mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -198,6 +199,7 @@ - (void)testLiveEventsForScenario1 [matrixSDKTestsData doMXRestClientTestWithBobAndARoom:self readyToTest:^(MXRestClient *bobRestClient, NSString *roomId, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -385,6 +387,7 @@ - (void)testBackPaginationForScenario2 [self createScenario2:bobRestClient inRoom:roomId expectation:expectation onComplete:^(MXRestClient *aliceRestClient) { mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -565,6 +568,7 @@ - (void)testLiveEventsForScenario2 [matrixSDKTestsData doMXRestClientTestWithBobAndARoom:self readyToTest:^(MXRestClient *bobRestClient, NSString *roomId, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ diff --git a/MatrixSDKTests/MXRoomStateTests.m b/MatrixSDKTests/MXRoomStateTests.m index d837814032..0be253ea10 100644 --- a/MatrixSDKTests/MXRoomStateTests.m +++ b/MatrixSDKTests/MXRoomStateTests.m @@ -95,6 +95,8 @@ - (void)testRoomTopicProvidedByInitialSync [bobRestClient setRoomTopic:roomId topic:@"My topic" success:^{ mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:roomId]; @@ -126,6 +128,8 @@ - (void)testRoomTopicLive MXRestClient *bobRestClient2 = bobRestClient; mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:roomId]; @@ -174,6 +178,8 @@ - (void)testRoomAvatarProvidedByInitialSync [bobRestClient setRoomAvatar:roomId avatar:@"http://matrix.org/matrix.png" success:^{ mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:roomId]; @@ -205,6 +211,8 @@ - (void)testRoomAvatarLive MXRestClient *bobRestClient2 = bobRestClient; mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:roomId]; @@ -251,6 +259,8 @@ - (void)testRoomNameProvidedByInitialSync [bobRestClient setRoomName:roomId name:@"My room name" success:^{ mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:roomId]; @@ -283,6 +293,8 @@ - (void)testRoomNameLive MXRestClient *bobRestClient2 = bobRestClient; mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:roomId]; @@ -329,6 +341,8 @@ - (void)testRoomHistoryVisibilityProvidedByInitialSync [bobRestClient setRoomHistoryVisibility:roomId historyVisibility:kMXRoomHistoryVisibilityWorldReadable success:^{ mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:roomId]; @@ -361,6 +375,8 @@ - (void)testRoomHistoryVisibilityLive MXRestClient *bobRestClient2 = bobRestClient; mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:roomId]; @@ -408,6 +424,8 @@ - (void)testRoomJoinRuleProvidedByInitialSync [bobRestClient setRoomJoinRule:roomId joinRule:kMXRoomJoinRulePublic success:^{ mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:roomId]; @@ -439,6 +457,8 @@ - (void)testRoomJoinRuleLive MXRestClient *bobRestClient2 = bobRestClient; mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:roomId]; @@ -486,6 +506,8 @@ - (void)testRoomGuestAccessProvidedByInitialSync [bobRestClient setRoomGuestAccess:roomId guestAccess:kMXRoomGuestAccessCanJoin success:^{ mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:roomId]; @@ -517,6 +539,8 @@ - (void)testRoomGuestAccessLive MXRestClient *bobRestClient2 = bobRestClient; mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:roomId]; @@ -569,6 +593,8 @@ - (void)testRoomCanonicalAliasProvidedByInitialSync [bobRestClient2 setRoomCanonicalAlias:roomId canonicalAlias:roomAlias success:^{ mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:roomId]; @@ -611,6 +637,8 @@ - (void)testRoomCanonicalAliasLive MXRestClient *bobRestClient2 = bobRestClient; mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:roomId]; @@ -676,6 +704,8 @@ - (void)testMembers [matrixSDKTestsData doMXRestClientTestInABobRoomAndANewTextMessage:self newTextMessage:@"This is a text message for recents" onReadyToTest:^(MXRestClient *bobRestClient, NSString *roomId, NSString *new_text_message_eventId, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:roomId]; @@ -969,6 +999,7 @@ - (void)testMXRoomJoin [matrixSDKTestsData doMXRestClientTestWithAlice:nil readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation2) { mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -1050,6 +1081,7 @@ - (void)testMXSessionJoinOnPublicRoom [matrixSDKTestsData doMXRestClientTestWithAlice:nil readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation2) { mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -1111,6 +1143,7 @@ - (void)testPowerLevels [matrixSDKTestsData doMXRestClientTestWithBobAndAliceInARoom:self readyToTest:^(MXRestClient *bobRestClient, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -1175,6 +1208,8 @@ - (void)testRoomStateWhenARoomHasBeenJoinedOnAnotherMatrixClient [matrixSDKTestsData doMXRestClientTestWithAlice:self readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ __block NSString *newRoomId; @@ -1229,6 +1264,8 @@ - (void)testRoomStateWhenARoomHasBeenJoinedOnAnotherMatrixClientAndNotifications [matrixSDKTestsData doMXRestClientTestWithAlice:self readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ __block NSString *newRoomId; diff --git a/MatrixSDKTests/MXRoomSummaryTests.m b/MatrixSDKTests/MXRoomSummaryTests.m index 71551736c4..edb8dc9c45 100644 --- a/MatrixSDKTests/MXRoomSummaryTests.m +++ b/MatrixSDKTests/MXRoomSummaryTests.m @@ -286,6 +286,7 @@ - (void)testGetLastMessageFromPagination [mxSession close]; MXSession *mxSession2 = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession2]; [mxSession2 setStore:[[MXMemoryStore alloc] init] success:^{ // Start a new session by loading no message @@ -344,6 +345,7 @@ - (void)testGetLastMessageFromSeveralPaginations [mxSession close]; MXSession *mxSession2 = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession2]; // Configure the updater so that it refuses room messages as last message mxSession2.roomSummaryUpdateDelegate = self; @@ -410,6 +412,7 @@ - (void)testFixRoomsSummariesLastMessage [mxSession close]; MXSession *mxSession2 = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession2]; [mxSession2 setStore:[[MXMemoryStore alloc] init] success:^{ // Start a new session by loading no message @@ -1040,6 +1043,7 @@ - (void)testClearCacheAfterStateEventRedaction // Restarting the session with a new MXMemoryStore is equivalent to // clearing the cache of MXFileStore MXSession *mxSession2 = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession2]; [mxSession2 setStore:[[MXMemoryStore alloc] init] success:^{ MXRoomSummaryUpdater *defaultUpdater = [MXRoomSummaryUpdater roomSummaryUpdaterForSession:mxSession2]; @@ -1187,6 +1191,7 @@ - (void)testDoNotStoreDecryptedData // Then reopen a session on this store MXSession *aliceSession2 = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + [matrixSDKTestsData retain:aliceSession2]; [aliceSession2 setStore:[[MXFileStore alloc] init] success:^{ [aliceSession2 start:^{ @@ -1270,6 +1275,7 @@ - (void)testEncryptedLastMessageEvent // Then reopen a session MXSession *aliceSession2 = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + [matrixSDKTestsData retain:aliceSession2]; [aliceSession2 setStore:[[MXFileStore alloc] init] success:^{ [aliceSession2 start:^{ diff --git a/MatrixSDKTests/MXRoomTests.m b/MatrixSDKTests/MXRoomTests.m index 77c6f8d0ff..620d78756f 100644 --- a/MatrixSDKTests/MXRoomTests.m +++ b/MatrixSDKTests/MXRoomTests.m @@ -212,6 +212,7 @@ - (void)testJoin [matrixSDKTestsData doMXRestClientTestWithAlice:nil readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation2) { mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + [matrixSDKTestsData retain:mxSession]; [bobRestClient inviteUser:aliceRestClient.credentials.userId toRoom:roomId success:^{ @@ -255,6 +256,7 @@ - (void)testSetPowerLevelOfUser [matrixSDKTestsData doMXRestClientTestWithBobAndAliceInARoom:self readyToTest:^(MXRestClient *bobRestClient, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:roomId]; @@ -287,6 +289,7 @@ - (void)testPaginateBackMessagesCancel [matrixSDKTestsData doMXRestClientTestWithBobAndARoomWithMessages:self readyToTest:^(MXRestClient *bobRestClient, NSString *roomId, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession startWithSyncFilter:[MXFilterJSONModel syncFilterWithMessageLimit:0] onServerSyncDone:^{ @@ -330,6 +333,8 @@ - (void)testTypingUsersNotifications [matrixSDKTestsData doMXRestClientTestWithBobAndARoom:self readyToTest:^(MXRestClient *bobRestClient, NSString *roomId, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:roomId]; @@ -454,6 +459,8 @@ - (void)testTagEvent [matrixSDKTestsData doMXRestClientTestInABobRoomAndANewTextMessage:self newTextMessage:@"This is a text message for tagged events" onReadyToTest:^(MXRestClient *bobRestClient, NSString *roomId, NSString *new_text_message_eventId, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:roomId]; @@ -495,6 +502,8 @@ - (void)testUntagEvent [matrixSDKTestsData doMXRestClientTestInABobRoomAndANewTextMessage:self newTextMessage:@"This is a text message for tagged events" onReadyToTest:^(MXRestClient *bobRestClient, NSString *roomId, NSString *new_text_message_eventId, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:roomId]; @@ -550,6 +559,8 @@ - (void)testGetTaggedEvent [matrixSDKTestsData doMXRestClientTestInABobRoomAndANewTextMessage:self newTextMessage:@"This is a text message for tagged events" onReadyToTest:^(MXRestClient *bobRestClient, NSString *roomId, NSString *new_text_message_eventId, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:roomId]; @@ -610,6 +621,8 @@ - (void)testRoomDirectoryVisibilityProvidedByInitialSync [bobRestClient setRoomDirectoryVisibility:roomId directoryVisibility:kMXRoomDirectoryVisibilityPublic success:^{ mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:roomId]; @@ -646,6 +659,8 @@ - (void)tesRoomDirectoryVisibilityLive MXRestClient *bobRestClient2 = bobRestClient; mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + [matrixSDKTestsData retain:mxSession]; + [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:roomId]; diff --git a/MatrixSDKTests/MXSessionTests.m b/MatrixSDKTests/MXSessionTests.m index 06411a3c69..b63b87d963 100644 --- a/MatrixSDKTests/MXSessionTests.m +++ b/MatrixSDKTests/MXSessionTests.m @@ -134,6 +134,7 @@ - (void)testInitialSyncFailure // 3. recreate the session mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession setStore:store success:^{ [mxSession start:^{ @@ -186,6 +187,7 @@ - (void)testRoomWithAlias [bobRestClient createRoom:nil visibility:kMXRoomDirectoryVisibilityPrivate roomAlias:alias topic:nil success:^(MXCreateRoomResponse *response) { mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ MXRoom *room = [mxSession roomWithRoomId:response.roomId]; @@ -226,6 +228,7 @@ - (void)testListenerForAllLiveEvents [matrixSDKTestsData doMXRestClientTestWihBobAndSeveralRoomsAndMessages:self readyToTest:^(MXRestClient *bobRestClient, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; // The listener must catch at least these events __block NSMutableArray *expectedEvents = @@ -302,6 +305,7 @@ - (void)testListenerForRoomMessageOnly [matrixSDKTestsData doMXRestClientTestWihBobAndSeveralRoomsAndMessages:self readyToTest:^(MXRestClient *bobRestClient, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; // Listen to m.room.message only // We should not see events coming before (m.room.create, and all state events) @@ -343,6 +347,7 @@ - (void)testListenerForPresence [matrixSDKTestsData doMXRestClientTestWithBobAndAliceInARoom:self readyToTest:^(MXRestClient *bobRestClient, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; __block MXSession *mxSession2 = mxSession; __block NSUInteger lastAliceActivity = -1; @@ -401,6 +406,7 @@ - (void)testClose [matrixSDKTestsData doMXRestClientTestWithBobAndAliceInARoom:self readyToTest:^(MXRestClient *bobRestClient, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -462,6 +468,7 @@ - (void)testCloseWithMXMemoryStore MXMemoryStore *store = [[MXMemoryStore alloc] init]; mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession setStore:store success:^{ @@ -506,6 +513,7 @@ - (void)testPauseResume [matrixSDKTestsData doMXRestClientTestWithBobAndAliceInARoom:self readyToTest:^(MXRestClient *bobRestClient, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -577,6 +585,7 @@ - (void)testPauseResumeOnNothingNew [matrixSDKTestsData doMXRestClientTestWithBobAndAliceInARoom:self readyToTest:^(MXRestClient *bobRestClient, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -653,6 +662,7 @@ - (void)testState }]; mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; XCTAssertEqual(MXSessionStateInitialised, mxSession.state); [mxSession start:^{ @@ -954,6 +964,7 @@ - (void)testNewRoomNotificationOnInvite [matrixSDKTestsData doMXRestClientTestWithAlice:nil readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation2) { mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ // Listen to Alice's MXSessionNewRoomNotification event @@ -980,6 +991,7 @@ - (void)testNewRoomNotificationOnCreatingPublicRoom [matrixSDKTestsData doMXRestClientTestWithBob:self readyToTest:^(MXRestClient *bobRestClient, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ observer = [[NSNotificationCenter defaultCenter] addObserverForName:kMXSessionNewRoomNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { @@ -1015,6 +1027,7 @@ - (void)testNewRoomNotificationOnJoiningPublicRoom [matrixSDKTestsData doMXRestClientTestWithAlice:nil readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation2) { mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ // Listen to Alice's MXSessionNewRoomNotification event @@ -1051,6 +1064,7 @@ - (void)testMXRoomInitialSyncNotificationOnJoiningPublicRoom [matrixSDKTestsData doMXRestClientTestWithAlice:nil readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation2) { mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ // Listen to Alice's kMXRoomInitialSyncNotification event @@ -1106,6 +1120,7 @@ - (void)doRoomByTagsOrderTest:(XCTestCase*)testCase withOrder1:(NSString*)order1 // Do the test mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ NSDictionary*> *roomByTags = [mxSession roomsByTags]; @@ -1197,6 +1212,7 @@ - (void)testTagRoomsWithSameOrder // Do the tests mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ NSArray *roomsWithTag = [mxSession roomsWithTag:tag]; @@ -1244,6 +1260,7 @@ - (void)testRoomByTagsAndNoRoomTag // Do the test mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ NSDictionary*> *roomByTags = [mxSession roomsByTags]; @@ -1303,6 +1320,7 @@ - (void)testTagOrderToBeAtIndex // Do the tests mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ NSString *orderForFirstPosition = [mxSession tagOrderToBeAtIndex:0 from:NSNotFound withTag:tag]; diff --git a/MatrixSDKTests/MXStoreTests.m b/MatrixSDKTests/MXStoreTests.m index 837f8aa122..73b9eef007 100644 --- a/MatrixSDKTests/MXStoreTests.m +++ b/MatrixSDKTests/MXStoreTests.m @@ -83,6 +83,8 @@ - (void)doTestWithStore:(id)store } mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; + [mxSession setStore:store success:^{ [mxSession start:^{ @@ -123,6 +125,7 @@ - (void)doTestWithTwoUsersAndStore:(id)store } mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession setStore:store success:^{ [mxSession start:^{ @@ -163,6 +166,7 @@ - (void)doTestWithStore:(id)store } mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession setStore:store success:^{ @@ -1022,6 +1026,7 @@ - (void)checkUserDisplaynameAndAvatarUrl:(Class)mxStoreClass // Let's (and verify) MXSession start update the store with user information mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession setStore:store success:^{ @@ -1093,6 +1098,7 @@ - (void)checkUpdateUserDisplaynameAndAvatarUrl:(Class)mxStoreClass // Let's (and verify) MXSession start update the store with user information mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession setStore:store success:^{ @@ -1181,6 +1187,8 @@ - (void)checkMXSessionOnStoreDataReady:(Class)mxStoreClass // Do a 1st [mxSession start] to fill the store mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; + [mxSession setStore:store success:^{ [mxSession start:^{ @@ -1202,6 +1210,7 @@ - (void)checkMXSessionOnStoreDataReady:(Class)mxStoreClass __block BOOL onStoreDataReadyCalled; MXSession *mxSession2 = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession2]; [mxSession2 setStore:store2 success:^{ onStoreDataReadyCalled = YES; @@ -1268,6 +1277,8 @@ - (void)checkRoomDeletion:(Class)mxStoreClass id store = [[mxStoreClass alloc] init]; mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; + [mxSession setStore:store success:^{ [mxSession start:^{ @@ -1326,6 +1337,8 @@ - (void)checkEventAge:(Class)mxStoreClass id store = [[mxStoreClass alloc] init]; mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; + [mxSession setStore:store success:^{ [mxSession start:^{ @@ -1391,6 +1404,8 @@ - (void)checkMXRoomPaginationToken:(Class)mxStoreClass // Do a 1st [mxSession start] to fill the store mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; + [mxSession setStore:store success:^{ [mxSession startWithSyncFilter:[MXFilterJSONModel syncFilterWithMessageLimit:5] onServerSyncDone:^{ @@ -1410,6 +1425,7 @@ - (void)checkMXRoomPaginationToken:(Class)mxStoreClass id store2 = [[mxStoreClass alloc] init]; mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; [mxSession setStore:store2 success:^{ XCTAssertEqualObjects(roomPaginationToken, [store2 paginationTokenOfRoom:roomId], @"The store must keep the pagination token"); @@ -1454,6 +1470,8 @@ - (void)checkMultiAccount:(Class)mxStoreClass id bobStore1 = [[mxStoreClass alloc] init]; mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; + [mxSession setStore:bobStore1 success:^{ [mxSession start:^{ @@ -1545,6 +1563,8 @@ - (void)checkRoomAccountDataTags:(Class)mxStoreClass // Do a 1st [mxSession start] to fill the store mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; + [mxSession setStore:store success:^{ [mxSession start:^{ @@ -1555,6 +1575,8 @@ - (void)checkRoomAccountDataTags:(Class)mxStoreClass id store2 = [[mxStoreClass alloc] init]; mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; + [mxSession setStore:store2 success:^{ NSArray *roomsWithTagTag1 = [mxSession roomsWithTag:tag1]; @@ -1643,6 +1665,8 @@ - (void)checkRoomSummary:(Class)mxStoreClass // Do a 1st [mxSession start] to fill the store mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; + [mxSession setStore:store success:^{ [mxSession start:^{ diff --git a/MatrixSDKTests/MXUserTests.m b/MatrixSDKTests/MXUserTests.m index 971aef27fd..f8d01359b4 100644 --- a/MatrixSDKTests/MXUserTests.m +++ b/MatrixSDKTests/MXUserTests.m @@ -60,6 +60,7 @@ - (void)doTestWithBobAndAliceActiveInARoom:(void (^)(MXRestClient *bobRestClient [aliceRestClient sendTextMessageToRoom:roomId text:@"Hi Bob!" success:^(NSString *eventId) { mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + [matrixSDKTestsData retain:mxSession]; // Start the session [mxSession start:^{ @@ -216,6 +217,7 @@ - (void)testMyUserAvailability [matrixSDKTestsData doMXRestClientTestWithAlice:self readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation) { mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + [matrixSDKTestsData retain:mxSession]; XCTAssertNil(mxSession.myUser); @@ -266,6 +268,8 @@ - (void)testMyUserLastActiveUpdate // [mxSession close]; // // mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; +// [matrixSDKTestsData retain:mxSession]; +// // [mxSession start:^{ // // [mxSession.myUser listenToUserUpdate:^(MXEvent *event) { @@ -302,6 +306,8 @@ - (void)testMyUserLastActiveUpdate // [mxSession close]; // // mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; +// [matrixSDKTestsData retain:mxSession]; +// // [mxSession start:^{ // // [mxSession.myUser listenToUserUpdate:^(MXEvent *event) { From 2f370ac4948ed87fea66304b193bb2e9a48132a0 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 23 Sep 2021 22:51:50 +0200 Subject: [PATCH 09/42] MXCrypto: Fix retain cycles --- MatrixSDK/Crypto/MXCrypto.m | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/MatrixSDK/Crypto/MXCrypto.m b/MatrixSDK/Crypto/MXCrypto.m index 45687c2a98..5110382def 100644 --- a/MatrixSDK/Crypto/MXCrypto.m +++ b/MatrixSDK/Crypto/MXCrypto.m @@ -426,7 +426,14 @@ - (void)close:(BOOL)deleteStore [self->roomDecryptors removeAllObjects]; self->roomDecryptors = nil; - + + self->_backup = nil; + self->_keyVerificationManager = nil; + self->_recoveryService = nil; + self->_secretStorage = nil; + self->_secretShareManager = nil; + self->_crossSigning = nil; + self->_myDevice = nil; MXLogDebug(@"[MXCrypto] close: done"); From 003e1777aab767a4142534b8445d123116033143 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 23 Sep 2021 23:51:26 +0200 Subject: [PATCH 10/42] Tests: Use the "new" way to close MXSession everywhere --- MatrixSDKTests/MXCryptoTests.m | 115 +-------------------- MatrixSDKTests/MXEventTests.m | 10 +- MatrixSDKTests/MXEventTimelineTests.m | 11 +- MatrixSDKTests/MXMyUserTests.m | 22 +--- MatrixSDKTests/MXNotificationCenterTests.m | 34 ++---- MatrixSDKTests/MXPeekingRoomTests.m | 24 +---- MatrixSDKTests/MXRoomMemberTests.m | 8 -- MatrixSDKTests/MXRoomStateDynamicTests.m | 12 +-- MatrixSDKTests/MXRoomStateTests.m | 88 ++++++---------- MatrixSDKTests/MXRoomTests.m | 44 +++----- MatrixSDKTests/MXSessionTests.m | 80 +++++--------- MatrixSDKTests/MXVoIPTests.m | 19 +--- 12 files changed, 98 insertions(+), 369 deletions(-) diff --git a/MatrixSDKTests/MXCryptoTests.m b/MatrixSDKTests/MXCryptoTests.m index 8cc0b04a03..c7a2d0e206 100644 --- a/MatrixSDKTests/MXCryptoTests.m +++ b/MatrixSDKTests/MXCryptoTests.m @@ -44,9 +44,6 @@ @interface MXCryptoTests : XCTestCase MatrixSDKTestsData *matrixSDKTestsData; MatrixSDKTestsE2EData *matrixSDKTestsE2EData; - MXSession *aliceSessionToClose; - MXSession *bobSessionToClose; - id observer; } @end @@ -69,12 +66,6 @@ - (void)tearDown observer = nil; } - [aliceSessionToClose close]; - aliceSessionToClose = nil; - - [bobSessionToClose close]; - bobSessionToClose = nil; - matrixSDKTestsData = nil; matrixSDKTestsE2EData = nil; @@ -114,8 +105,6 @@ - (void)testEnableCrypto { [matrixSDKTestsData doMXSessionTestWithBob:self readyToTest:^(MXSession *mxSession, XCTestExpectation *expectation) { - bobSessionToClose = mxSession; - XCTAssertNil(mxSession.crypto, @"Crypto is disabled by default"); XCTAssertFalse([mxSession.crypto.store.class hasDataForCredentials:mxSession.matrixRestClient.credentials]); @@ -149,9 +138,6 @@ - (void)testMXSDKOptionsEnableCryptoWhenOpeningMXSession [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = YES; [matrixSDKTestsData doMXSessionTestWithBob:self readyToTest:^(MXSession *mxSession, XCTestExpectation *expectation) { - - bobSessionToClose = mxSession; - // Reset the option to not disturb other tests [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = NO; @@ -176,9 +162,6 @@ - (void)testMXSDKOptionsEnableCryptoWhenOpeningMXSession - (void)testCryptoNoDeviceId { [matrixSDKTestsData doMXSessionTestWithBob:self readyToTest:^(MXSession *mxSession, XCTestExpectation *expectation) { - - bobSessionToClose = mxSession; - // Simulate no device id provided by the home server mxSession.matrixRestClient.credentials.deviceId = nil; @@ -242,8 +225,6 @@ - (void)testCryptoPersistenceInStore [expectation fulfill]; }]; - bobSessionToClose = mxSession2; - } failure:^(NSError *error) { XCTFail(@"The request should not fail - NSError: %@", error); [expectation fulfill]; @@ -320,10 +301,6 @@ - (void)testDownloadKeysForUserWithNoDevice // No device = non-e2e-capable device [matrixSDKTestsE2EData doE2ETestWithAliceAndBobInARoom:self cryptedBob:NO warnOnUnknowDevices:NO readyToTest:^(MXSession *aliceSession, MXSession *bobSession, NSString *roomId, XCTestExpectation *expectation) { - - aliceSessionToClose = aliceSession; - bobSessionToClose = bobSession; - [aliceSession.crypto.deviceList downloadKeys:@[bobSession.myUser.userId] forceDownload:NO success:^(MXUsersDevicesMap *usersDevicesInfoMap, NSDictionary *crossSigningKeysMap) { NSArray *bobDevices = [usersDevicesInfoMap deviceIdsForUser:bobSession.myUser.userId]; @@ -349,10 +326,6 @@ - (void)testDownloadKeysForUserWithNoDevice - (void)testDownloadKeysWithUnreachableHS { [matrixSDKTestsE2EData doE2ETestWithBobAndAlice:self readyToTest:^(MXSession *bobSession, MXSession *aliceSession, XCTestExpectation *expectation) { - - aliceSessionToClose = aliceSession; - bobSessionToClose = bobSession; - // Try to get info from a user on matrix.org. // The local hs we use for tests is not federated and is not able to talk with matrix.org [aliceSession.crypto.deviceList downloadKeys:@[bobSession.myUser.userId, @"@auser:matrix.org"] forceDownload:NO success:^(MXUsersDevicesMap *usersDevicesInfoMap, NSDictionary *crossSigningKeysMap) { @@ -415,8 +388,6 @@ - (void)testRoomIsEncrypted [matrixSDKTestsData doMXSessionTestWithBob:self readyToTest:^(MXSession *mxSession, XCTestExpectation *expectation) { - bobSessionToClose = mxSession; - [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = NO; [mxSession createRoom:@{} success:^(MXRoom *room) { @@ -450,8 +421,6 @@ - (void)testAliceInACryptedRoom { [matrixSDKTestsE2EData doE2ETestWithAliceInARoom:self readyToTest:^(MXSession *aliceSession, NSString *roomId, XCTestExpectation *expectation) { - aliceSessionToClose = aliceSession; - NSString *message = @"Hello myself!"; MXRoom *roomFromAlicePOV = [aliceSession roomWithRoomId:roomId]; @@ -488,8 +457,6 @@ - (void)testAliceInACryptedRoomAfterInitialSync MXSession *aliceSession2 = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; [matrixSDKTestsData retain:aliceSession2]; - aliceSessionToClose = aliceSession2; - [aliceSession2 setStore:[[MXMemoryStore alloc] init] success:^{ [aliceSession2 start:^{ @@ -537,9 +504,6 @@ - (void)testAliceAndBobInACryptedRoom { [matrixSDKTestsE2EData doE2ETestWithAliceAndBobInARoom:self cryptedBob:YES warnOnUnknowDevices:NO readyToTest:^(MXSession *aliceSession, MXSession *bobSession, NSString *roomId, XCTestExpectation *expectation) { - aliceSessionToClose = aliceSession; - bobSessionToClose = bobSession; - NSString *messageFromAlice = @"Hello I'm Alice!"; MXRoom *roomFromBobPOV = [bobSession roomWithRoomId:roomId]; @@ -570,9 +534,6 @@ - (void)testAliceAndBobInACryptedRoom2 { [matrixSDKTestsE2EData doE2ETestWithAliceAndBobInARoom:self cryptedBob:YES warnOnUnknowDevices:NO readyToTest:^(MXSession *aliceSession, MXSession *bobSession, NSString *roomId, XCTestExpectation *expectation) { - aliceSessionToClose = aliceSession; - bobSessionToClose = bobSession; - __block NSUInteger receivedMessagesFromAlice = 0; __block NSUInteger receivedMessagesFromBob = 0; @@ -651,9 +612,6 @@ - (void)testAliceAndBobInACryptedRoomFromInitialSync bobSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:bobSession]; - aliceSessionToClose = aliceSession; - bobSessionToClose = bobSession; - [bobSession setStore:[[MXMemoryStore alloc] init] success:^{ XCTAssert(bobSession.crypto, @"MXSession must recall that it has crypto engaged"); @@ -729,9 +687,6 @@ - (void)testAliceAndBobInACryptedRoomBackPaginationFromMemoryStore { [matrixSDKTestsE2EData doE2ETestWithAliceAndBobInARoomWithCryptedMessages:self cryptedBob:YES readyToTest:^(MXSession *aliceSession, MXSession *bobSession, NSString *roomId, XCTestExpectation *expectation) { - aliceSessionToClose = aliceSession; - bobSessionToClose = bobSession; - __block NSUInteger paginatedMessagesCount = 0; MXRoom *roomFromBobPOV = [bobSession roomWithRoomId:roomId]; @@ -792,9 +747,6 @@ - (void)testAliceAndBobInACryptedRoomBackPaginationFromHomeServer { [matrixSDKTestsE2EData doE2ETestWithAliceAndBobInARoomWithCryptedMessages:self cryptedBob:YES readyToTest:^(MXSession *aliceSession, MXSession *bobSession, NSString *roomId, XCTestExpectation *expectation) { - aliceSessionToClose = aliceSession; - bobSessionToClose = bobSession; - __block NSUInteger paginatedMessagesCount = 0; MXRoom *roomFromBobPOV = [bobSession roomWithRoomId:roomId]; @@ -858,9 +810,6 @@ - (void)testAliceAndNotCryptedBobInACryptedRoom { [matrixSDKTestsE2EData doE2ETestWithAliceAndBobInARoom:self cryptedBob:NO warnOnUnknowDevices:NO readyToTest:^(MXSession *aliceSession, MXSession *bobSession, NSString *roomId, XCTestExpectation *expectation) { - aliceSessionToClose = aliceSession; - bobSessionToClose = bobSession; - NSString *messageFromAlice = @"Hello I'm Alice!"; MXRoom *roomFromBobPOV = [bobSession roomWithRoomId:roomId]; @@ -935,8 +884,6 @@ - (void)testAliceDecryptOldMessageWithANewDeviceInACryptedRoom [matrixSDKTestsData relogUserSession:self session:aliceSession withPassword:MXTESTS_ALICE_PWD onComplete:^(MXSession *aliceSession2) { [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = NO; - aliceSessionToClose = aliceSession2; - MXRoom *roomFromAlicePOV2 = [aliceSession2 roomWithRoomId:roomId]; XCTAssert(roomFromAlicePOV2.summary.isEncrypted, @"The room must still appear as encrypted"); @@ -976,9 +923,6 @@ - (void)testAliceWithNewDeviceAndBob [matrixSDKTestsData relogUserSession:self session:aliceSession withPassword:MXTESTS_ALICE_PWD onComplete:^(MXSession *aliceSession2) { [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = NO; - aliceSessionToClose = aliceSession2; - bobSessionToClose = bobSession; - aliceSession2.crypto.warnOnUnknowDevices = NO; MXRoom *roomFromBobPOV = [bobSession roomWithRoomId:roomId]; @@ -1023,9 +967,6 @@ - (void)testAliceAndBobWithNewDevice [matrixSDKTestsData relogUserSession:self session:bobSession withPassword:MXTESTS_BOB_PWD onComplete:^(MXSession *bobSession2) { [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = NO; - aliceSessionToClose = aliceSession; - bobSessionToClose = bobSession2; - MXRoom *roomFromBob2POV = [bobSession2 roomWithRoomId:roomId]; [roomFromBob2POV liveTimeline:^(MXEventTimeline *liveTimeline) { @@ -1075,9 +1016,6 @@ - (void)testAliceWithNewDeviceAndBobWithNewDevice [matrixSDKTestsData relogUserSession:self session:bobSession withPassword:MXTESTS_BOB_PWD onComplete:^(MXSession *bobSession2) { [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = NO; - aliceSessionToClose = aliceSession2; - bobSessionToClose = bobSession2; - aliceSession2.crypto.warnOnUnknowDevices = NO; bobSession2.crypto.warnOnUnknowDevices = NO; @@ -1130,9 +1068,6 @@ - (void)testAliceAndBlockedBob { [matrixSDKTestsE2EData doE2ETestWithAliceAndBobInARoom:self cryptedBob:YES warnOnUnknowDevices:NO readyToTest:^(MXSession *aliceSession, MXSession *bobSession, NSString *roomId, XCTestExpectation *expectation) { - aliceSessionToClose = aliceSession; - bobSessionToClose = bobSession; - MXRoom *roomFromAlicePOV = [aliceSession roomWithRoomId:roomId]; MXRoom *roomFromBobPOV = [bobSession roomWithRoomId:roomId]; @@ -1260,9 +1195,6 @@ - (void)testBlackListUnverifiedDevices [matrixSDKTestsE2EData doE2ETestWithAliceAndBobAndSamInARoom:self cryptedBob:YES cryptedSam:YES warnOnUnknowDevices:YES readyToTest:^(MXSession *aliceSession, MXSession *bobSession, MXSession *samSession, NSString *roomId, XCTestExpectation *expectation) { - aliceSessionToClose = aliceSession; - bobSessionToClose = bobSession; - MXRoom *roomFromAlicePOV = [aliceSession roomWithRoomId:roomId]; MXRoom *roomFromBobPOV = [bobSession roomWithRoomId:roomId]; MXRoom *roomFromSamPOV = [samSession roomWithRoomId:roomId]; @@ -1618,9 +1550,6 @@ - (void)testInvitedMemberInACryptedRoom { [matrixSDKTestsE2EData doE2ETestWithAliceByInvitingBobInARoom:self cryptedBob:YES warnOnUnknowDevices:NO readyToTest:^(MXSession *aliceSession, MXSession *bobSession, NSString *roomId, XCTestExpectation *expectation) { - aliceSessionToClose = aliceSession; - bobSessionToClose = bobSession; - NSString *messageFromAlice = @"Hello I'm Alice!"; MXRoom *roomFromAlicePOV = [aliceSession roomWithRoomId:roomId]; @@ -1662,9 +1591,6 @@ - (void)testInvitedMemberInACryptedRoom2 { [matrixSDKTestsE2EData doE2ETestWithAliceByInvitingBobInARoom:self cryptedBob:YES warnOnUnknowDevices:NO readyToTest:^(MXSession *aliceSession, MXSession *bobSession, NSString *roomId, XCTestExpectation *expectation) { - aliceSessionToClose = aliceSession; - bobSessionToClose = bobSession; - NSString *messageFromAlice = @"Hello I'm Alice!"; NSString *message2FromAlice = @"I'm still Alice!"; @@ -1841,9 +1767,6 @@ - (void)testReplayAttack { [matrixSDKTestsE2EData doE2ETestWithAliceAndBobInARoom:self cryptedBob:YES warnOnUnknowDevices:NO readyToTest:^(MXSession *aliceSession, MXSession *bobSession, NSString *roomId, XCTestExpectation *expectation) { - aliceSessionToClose = aliceSession; - bobSessionToClose = bobSession; - NSString *messageFromAlice = @"Hello I'm Alice!"; MXRoom *roomFromBobPOV = [bobSession roomWithRoomId:roomId]; @@ -1887,9 +1810,6 @@ - (void)testRoomKeyReshare { [matrixSDKTestsE2EData doE2ETestWithAliceAndBobInARoom:self cryptedBob:YES warnOnUnknowDevices:NO readyToTest:^(MXSession *aliceSession, MXSession *bobSession, NSString *roomId, XCTestExpectation *expectation) { - aliceSessionToClose = aliceSession; - bobSessionToClose = bobSession; - NSString *messageFromAlice = @"Hello I'm Alice!"; MXRoom *roomFromBobPOV = [bobSession roomWithRoomId:roomId]; @@ -1948,9 +1868,6 @@ - (void)testLateRoomKey { [matrixSDKTestsE2EData doE2ETestWithAliceAndBobInARoom:self cryptedBob:YES warnOnUnknowDevices:NO readyToTest:^(MXSession *aliceSession, MXSession *bobSession, NSString *roomId, XCTestExpectation *expectation) { - aliceSessionToClose = aliceSession; - bobSessionToClose = bobSession; - NSString *messageFromAlice = @"Hello I'm Alice!"; MXRoom *roomFromBobPOV = [bobSession roomWithRoomId:roomId]; @@ -2146,9 +2063,6 @@ - (void)testFirstMessageSentWhileSessionWasPaused { [matrixSDKTestsE2EData doE2ETestWithAliceAndBobInARoom:self cryptedBob:YES warnOnUnknowDevices:NO readyToTest:^(MXSession *aliceSession, MXSession *bobSession, NSString *roomId, XCTestExpectation *expectation) { - aliceSessionToClose = aliceSession; - bobSessionToClose = bobSession; - NSString *messageFromAlice = @"Hello I'm Alice!"; MXRoom *roomFromBobPOV = [bobSession roomWithRoomId:roomId]; @@ -2192,9 +2106,6 @@ - (void)testLeftAndJoinedBob [matrixSDKTestsE2EData doE2ETestWithBobAndAlice:self readyToTest:^(MXSession *bobSession, MXSession *aliceSession, XCTestExpectation *expectation) { - aliceSessionToClose = aliceSession; - bobSessionToClose = bobSession; - aliceSession.crypto.warnOnUnknowDevices = NO; bobSession.crypto.warnOnUnknowDevices = NO; @@ -2305,9 +2216,6 @@ - (void)testLeftBobAndAliceWithNewDevice [matrixSDKTestsData relogUserSession:self session:aliceSession withPassword:MXTESTS_ALICE_PWD onComplete:^(MXSession *aliceSession2) { [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = NO; - aliceSessionToClose = aliceSession2; - bobSessionToClose = bobSession; - aliceSession2.crypto.warnOnUnknowDevices = NO; // - Alice and Bob start sharing a room again @@ -2403,9 +2311,6 @@ - (void)testEnableEncryptionAfterNonCryptedMessages [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = YES; [matrixSDKTestsData relogUserSession:self session:bobSession withPassword:MXTESTS_BOB_PWD onComplete:^(MXSession *newBobSession) { - aliceSessionToClose = aliceSession; - bobSessionToClose = newBobSession; - [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = NO; MXRoom *roomFromNewBobPOV = [newBobSession roomWithRoomId:roomFromAlicePOV.roomId]; @@ -2572,9 +2477,6 @@ - (void)testEnableEncryptionAfterNonCryptedMessages // // XCTAssertEqual(0, [self checkEncryptedEvent:event roomId:roomId clearMessage:aliceMessages[2] senderSession:aliceSession3]); // -// aliceSessionToClose = aliceSession3; -// bobSessionToClose = bobSession; -// // [expectation fulfill]; // break; // } @@ -2595,9 +2497,6 @@ - (void)testExportRoomKeys { [matrixSDKTestsE2EData doE2ETestWithAliceAndBobInARoomWithCryptedMessages:self cryptedBob:YES readyToTest:^(MXSession *aliceSession, MXSession *bobSession, NSString *roomId, XCTestExpectation *expectation) { - aliceSessionToClose = aliceSession; - bobSessionToClose = bobSession; - [bobSession.crypto exportRoomKeys:^(NSArray *keys) { XCTAssert(keys); @@ -2617,10 +2516,7 @@ - (void)testExportRoomKeys - (void)testImportRoomKeys { [matrixSDKTestsE2EData doE2ETestWithAliceAndBobInARoomWithCryptedMessages:self cryptedBob:YES readyToTest:^(MXSession *aliceSession, MXSession *bobSession, NSString *roomId, XCTestExpectation *expectation) { - - aliceSessionToClose = aliceSession; - bobSessionToClose = bobSession; - + [bobSession.crypto exportRoomKeys:^(NSArray *keys) { // Clear bob crypto data @@ -2700,9 +2596,6 @@ - (void)testExportImportRoomKeysWithPassword { [matrixSDKTestsE2EData doE2ETestWithAliceAndBobInARoomWithCryptedMessages:self cryptedBob:YES readyToTest:^(MXSession *aliceSession, MXSession *bobSession, NSString *roomId, XCTestExpectation *expectation) { - aliceSessionToClose = aliceSession; - bobSessionToClose = bobSession; - NSString *password = @"motdepasse"; [bobSession.crypto exportRoomKeysWithPassword:password success:^(NSData *keyFile) { @@ -2783,9 +2676,6 @@ - (void)testImportRoomKeysWithWrongPassword { [matrixSDKTestsE2EData doE2ETestWithAliceAndBobInARoomWithCryptedMessages:self cryptedBob:YES readyToTest:^(MXSession *aliceSession, MXSession *bobSession, NSString *roomId, XCTestExpectation *expectation) { - aliceSessionToClose = aliceSession; - bobSessionToClose = bobSession; - [bobSession.crypto exportRoomKeysWithPassword:@"APassword" success:^(NSData *keyFile) { [bobSession.crypto importRoomKeys:keyFile withPassword:@"AnotherPassword" success:^(NSUInteger total, NSUInteger imported) { @@ -2840,7 +2730,6 @@ - (void)testIncomingRoomKeyRequest [matrixSDKTestsData relogUserSessionWithNewDevice:self session:aliceSession withPassword:MXTESTS_ALICE_PWD onComplete:^(MXSession *aliceSession2) { [MXSDKOptions sharedInstance].enableCryptoWhenStartingMXSession = NO; - aliceSessionToClose = aliceSession2; aliceSession2.crypto.warnOnUnknowDevices = NO; MXRoom *roomFromAlice2POV = [aliceSession2 roomWithRoomId:roomId]; @@ -2960,8 +2849,6 @@ - (void)testDeviceInvalidationWhileSending { [matrixSDKTestsE2EData doE2ETestWithAliceInARoom:self readyToTest:^(MXSession *aliceSession, NSString *roomId, XCTestExpectation *expectation) { - aliceSessionToClose = aliceSession; - NSString *message = @"message"; NSString *message2 = @"message2"; NSString *message3 = @"message3"; diff --git a/MatrixSDKTests/MXEventTests.m b/MatrixSDKTests/MXEventTests.m index c2c8f46dc5..d554df25e5 100644 --- a/MatrixSDKTests/MXEventTests.m +++ b/MatrixSDKTests/MXEventTests.m @@ -23,8 +23,6 @@ @interface MXEventTests : XCTestCase { MatrixSDKTestsData *matrixSDKTestsData; - - MXSession *mxSession; } @end @@ -40,12 +38,6 @@ - (void)setUp - (void)tearDown { - if (mxSession) - { - [mxSession close]; - mxSession = nil; - } - matrixSDKTestsData = nil; [super tearDown]; @@ -100,7 +92,7 @@ - (void)testIsState { [matrixSDKTestsData doMXRestClientTestWithBobAndARoomWithMessages:self readyToTest:^(MXRestClient *bobRestClient, NSString *roomId, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ diff --git a/MatrixSDKTests/MXEventTimelineTests.m b/MatrixSDKTests/MXEventTimelineTests.m index db6fa149fe..5beea67b60 100644 --- a/MatrixSDKTests/MXEventTimelineTests.m +++ b/MatrixSDKTests/MXEventTimelineTests.m @@ -24,8 +24,6 @@ @interface MXEventTimelineTests : XCTestCase { MatrixSDKTestsData *matrixSDKTestsData; - - MXSession *mxSession; } @end @@ -42,12 +40,6 @@ - (void)setUp - (void)tearDown { - if (mxSession) - { - [mxSession close]; - mxSession = nil; - } - matrixSDKTestsData = nil; [super tearDown]; @@ -55,8 +47,7 @@ - (void)tearDown - (void)doTestWithARoomOf41Messages:(XCTestCase*)testCase readyToTest:(void (^)(MXRoom *room, XCTestExpectation *expectation, NSString *initialEventId))readyToTest { - [matrixSDKTestsData doMXSessionTestWithBobAndARoomWithMessages:self readyToTest:^(MXSession *mxSession2, MXRoom *room, XCTestExpectation *expectation) { - mxSession = mxSession2; + [matrixSDKTestsData doMXSessionTestWithBobAndARoomWithMessages:self readyToTest:^(MXSession *mxSession, MXRoom *room, XCTestExpectation *expectation) { // Add 20 messages to the room [matrixSDKTestsData for:mxSession.matrixRestClient andRoom:room.roomId sendMessages:20 testCase:testCase success:^{ diff --git a/MatrixSDKTests/MXMyUserTests.m b/MatrixSDKTests/MXMyUserTests.m index 02a7411a1c..3969258c6b 100644 --- a/MatrixSDKTests/MXMyUserTests.m +++ b/MatrixSDKTests/MXMyUserTests.m @@ -24,8 +24,6 @@ @interface MXMyUserTests : XCTestCase { MatrixSDKTestsData *matrixSDKTestsData; - - MXSession *mxSession; } @end @@ -40,12 +38,6 @@ - (void)setUp - (void)tearDown { - if (mxSession) - { - [mxSession close]; - mxSession = nil; - } - matrixSDKTestsData = nil; [super tearDown]; @@ -53,9 +45,7 @@ - (void)tearDown - (void)testMXSessionMyUser { - [matrixSDKTestsData doMXSessionTestWithBobAndARoomWithMessages:self readyToTest:^(MXSession *mxSession2, MXRoom *room, XCTestExpectation *expectation) { - - mxSession = mxSession2; + [matrixSDKTestsData doMXSessionTestWithBobAndARoomWithMessages:self readyToTest:^(MXSession *mxSession, MXRoom *room, XCTestExpectation *expectation) { XCTAssertNotNil(mxSession.myUser); @@ -70,7 +60,7 @@ - (void)testSetDisplayName { [matrixSDKTestsData doMXRestClientTestWithAlice:self readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; [matrixSDKTestsData retain:mxSession]; XCTAssertNil(mxSession.myUser, @"There should be no myUser while initialSync is not done"); @@ -108,7 +98,7 @@ - (void)testSetAvatarURL { [matrixSDKTestsData doMXRestClientTestWithAlice:self readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -145,7 +135,7 @@ - (void)testSetPresence { [matrixSDKTestsData doMXRestClientTestWithAlice:self readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -181,9 +171,7 @@ - (void)testSetPresence - (void)testIdenticon { - [matrixSDKTestsData doMXSessionTestWithBobAndARoomWithMessages:self readyToTest:^(MXSession *mxSession2, MXRoom *room, XCTestExpectation *expectation) { - - mxSession = mxSession2; + [matrixSDKTestsData doMXSessionTestWithBobAndARoomWithMessages:self readyToTest:^(MXSession *mxSession, MXRoom *room, XCTestExpectation *expectation) { MXUser *myUser = [mxSession userWithUserId:mxSession.matrixRestClient.credentials.userId]; diff --git a/MatrixSDKTests/MXNotificationCenterTests.m b/MatrixSDKTests/MXNotificationCenterTests.m index bf77c551e0..27c720a8f7 100644 --- a/MatrixSDKTests/MXNotificationCenterTests.m +++ b/MatrixSDKTests/MXNotificationCenterTests.m @@ -26,8 +26,6 @@ @interface MXNotificationCenterTests : XCTestCase { MatrixSDKTestsData *matrixSDKTestsData; - - MXSession *mxSession; } @end @@ -43,12 +41,6 @@ - (void)setUp - (void)tearDown { - if (mxSession) - { - [mxSession close]; - mxSession = nil; - } - matrixSDKTestsData = nil; [super tearDown]; @@ -58,7 +50,7 @@ - (void)testNotificationCenterRulesReady { [matrixSDKTestsData doMXRestClientTestWithBob:self readyToTest:^(MXRestClient *bobRestClient, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; XCTAssertNotNil(mxSession.notificationCenter); @@ -84,9 +76,7 @@ - (void)testNotificationCenterRulesReady - (void)testNoNotificationsOnUserEvents { - [matrixSDKTestsData doMXSessionTestWithBobAndARoomWithMessages:self readyToTest:^(MXSession *mxSession2, MXRoom *room, XCTestExpectation *expectation) { - - mxSession = mxSession2; + [matrixSDKTestsData doMXSessionTestWithBobAndARoomWithMessages:self readyToTest:^(MXSession *mxSession, MXRoom *room, XCTestExpectation *expectation) { [mxSession.notificationCenter listenToNotifications:^(MXEvent *event, MXRoomState *roomState, MXPushRule *rule) { @@ -115,8 +105,6 @@ - (void)testNoNotificationsOnPresenceOrTypingEvents { [matrixSDKTestsData doMXSessionTestWithBobAndAliceInARoom:self readyToTest:^(MXSession *bobSession, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { - mxSession = bobSession; - [bobSession.notificationCenter listenToNotifications:^(MXEvent *event, MXRoomState *roomState, MXPushRule *rule) { XCTFail(@"Presence and typing events should not be notified with default push rules. event: %@\n rule: %@", event, rule); @@ -153,16 +141,14 @@ - (void)testNoNotificationsOnPresenceOrTypingEvents // While this ticket is not fixed, make sure the SDK workrounds it - (void)testDefaultPushOnAllNonYouMessagesRule { - [matrixSDKTestsData doMXSessionTestWithBobAndAliceInARoom:self readyToTest:^(MXSession *bobSession, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { - - mxSession = bobSession; + [matrixSDKTestsData doMXSessionTestWithBobAndAliceInARoom:self readyToTest:^(MXSession *mxSession, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { MXRoom *room = [mxSession roomWithRoomId:roomId]; [room liveTimeline:^(MXEventTimeline *liveTimeline) { [liveTimeline listenToEventsOfTypes:@[kMXEventTypeStringRoomMember] onEvent:^(MXEvent *event, MXTimelineDirection direction, MXRoomState *roomState) { - [bobSession.notificationCenter listenToNotifications:^(MXEvent *event, MXRoomState *roomState, MXPushRule *rule) { + [mxSession.notificationCenter listenToNotifications:^(MXEvent *event, MXRoomState *roomState, MXPushRule *rule) { // We must be alerted by the default content HS rule on any message XCTAssertEqual(rule.kind, MXPushRuleKindUnderride); @@ -244,8 +230,6 @@ - (void)testDefaultDisplayNameCondition { [matrixSDKTestsData doMXSessionTestWithBobAndAliceInARoom:self readyToTest:^(MXSession *bobSession, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { - mxSession = bobSession; - MXSession *aliceSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; [matrixSDKTestsData retain:aliceSession]; @@ -270,7 +254,7 @@ - (void)testDefaultDisplayNameCondition }]; - MXRoom *roomBobSide = [mxSession roomWithRoomId:roomId]; + MXRoom *roomBobSide = [bobSession roomWithRoomId:roomId]; [roomBobSide sendTextMessage:messageFromBob success:^(NSString *eventId) { } failure:^(NSError *error) { @@ -295,8 +279,6 @@ - (void)testDefaultRoomMemberCountCondition { [matrixSDKTestsData doMXSessionTestWithBobAndAliceInARoom:self readyToTest:^(MXSession *bobSession, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { - mxSession = bobSession; - NSString *messageFromAlice = @"We are two peoples in this room"; [bobSession.notificationCenter listenToNotifications:^(MXEvent *event, MXRoomState *roomState, MXPushRule *rule) { @@ -329,8 +311,6 @@ - (void)testRemoveListener { [matrixSDKTestsData doMXSessionTestWithBobAndAliceInARoom:self readyToTest:^(MXSession *bobSession, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { - mxSession = bobSession; - NSString *messageFromAlice = @"We are two peoples in this room"; id listener = [bobSession.notificationCenter listenToNotifications:^(MXEvent *event, MXRoomState *roomState, MXPushRule *rule) { @@ -362,8 +342,6 @@ - (void)testRuleMatchingEvent { [matrixSDKTestsData doMXSessionTestWithBobAndAliceInARoom:self readyToTest:^(MXSession *bobSession, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { - mxSession = bobSession; - MXSession *aliceSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; [matrixSDKTestsData retain:aliceSession]; @@ -398,7 +376,7 @@ - (void)testRuleMatchingEvent } }]; - MXRoom *roomBobSide = [mxSession roomWithRoomId:roomId]; + MXRoom *roomBobSide = [bobSession roomWithRoomId:roomId]; [roomBobSide sendTextMessage:messageFromBob success:^(NSString *eventId) { } failure:^(NSError *error) { diff --git a/MatrixSDKTests/MXPeekingRoomTests.m b/MatrixSDKTests/MXPeekingRoomTests.m index 7761296553..66d8820f70 100644 --- a/MatrixSDKTests/MXPeekingRoomTests.m +++ b/MatrixSDKTests/MXPeekingRoomTests.m @@ -29,8 +29,6 @@ @interface MXPeekingRoomTests : XCTestCase { MatrixSDKTestsData *matrixSDKTestsData; - - MXSession *mxSession; } @end @@ -45,12 +43,6 @@ - (void)setUp - (void)tearDown { - if (mxSession) - { - [mxSession close]; - mxSession = nil; - } - matrixSDKTestsData = nil; [super tearDown]; @@ -62,9 +54,7 @@ - (void)testPeeking [room setHistoryVisibility:kMXRoomHistoryVisibilityWorldReadable success:^{ - [matrixSDKTestsData doMXSessionTestWithAlice:nil readyToTest:^(MXSession *aliceSession, XCTestExpectation *expectation2) { - - mxSession = aliceSession; + [matrixSDKTestsData doMXSessionTestWithAlice:nil readyToTest:^(MXSession *mxSession, XCTestExpectation *expectation2) { XCTAssertEqual(mxSession.rooms.count, 0); @@ -103,9 +93,7 @@ - (void)testPeekingSummary [room setHistoryVisibility:kMXRoomHistoryVisibilityWorldReadable success:^{ - [matrixSDKTestsData doMXSessionTestWithAlice:nil readyToTest:^(MXSession *aliceSession, XCTestExpectation *expectation2) { - - mxSession = aliceSession; + [matrixSDKTestsData doMXSessionTestWithAlice:nil readyToTest:^(MXSession *mxSession, XCTestExpectation *expectation2) { XCTAssertEqual(mxSession.rooms.count, 0); @@ -142,9 +130,7 @@ - (void)testPeekingOnNonWorldReadable { [matrixSDKTestsData doMXSessionTestWithBobAndThePublicRoom:self readyToTest:^(MXSession *mxSession2, MXRoom *room, XCTestExpectation *expectation) { - [matrixSDKTestsData doMXSessionTestWithAlice:nil readyToTest:^(MXSession *aliceSession, XCTestExpectation *expectation2) { - - mxSession = aliceSession; + [matrixSDKTestsData doMXSessionTestWithAlice:nil readyToTest:^(MXSession *mxSession, XCTestExpectation *expectation2) { XCTAssertEqual(mxSession.rooms.count, 0); @@ -166,9 +152,7 @@ - (void)testPeekingOnNonWorldReadable - (void)testPeekingWithMemberAlreadyInRoom { - [matrixSDKTestsData doMXSessionTestWithBobAndThePublicRoom:self readyToTest:^(MXSession *mxSession2, MXRoom *room, XCTestExpectation *expectation) { - - mxSession = mxSession2; + [matrixSDKTestsData doMXSessionTestWithBobAndThePublicRoom:self readyToTest:^(MXSession *mxSession, MXRoom *room, XCTestExpectation *expectation) { XCTAssertEqual(mxSession.rooms.count, 1); XCTAssertEqual(room.summary.membersCount.members, 1); diff --git a/MatrixSDKTests/MXRoomMemberTests.m b/MatrixSDKTests/MXRoomMemberTests.m index 0433b5333a..61c39c792a 100644 --- a/MatrixSDKTests/MXRoomMemberTests.m +++ b/MatrixSDKTests/MXRoomMemberTests.m @@ -23,8 +23,6 @@ @interface MXRoomMemberTests : XCTestCase { MatrixSDKTestsData *matrixSDKTestsData; - - MXSession *mxSession; } @end @@ -39,12 +37,6 @@ - (void)setUp - (void)tearDown { - if (mxSession) - { - [mxSession close]; - mxSession = nil; - } - matrixSDKTestsData = nil; [super tearDown]; diff --git a/MatrixSDKTests/MXRoomStateDynamicTests.m b/MatrixSDKTests/MXRoomStateDynamicTests.m index 4b9a75fa8a..a1c8fd9742 100644 --- a/MatrixSDKTests/MXRoomStateDynamicTests.m +++ b/MatrixSDKTests/MXRoomStateDynamicTests.m @@ -23,8 +23,6 @@ @interface MXRoomStateDynamicTests : XCTestCase { MatrixSDKTestsData *matrixSDKTestsData; - - MXSession *mxSession; } @end @@ -39,12 +37,6 @@ - (void)setUp - (void)tearDown { - if (mxSession) - { - [mxSession close]; - mxSession = nil; - } - matrixSDKTestsData = nil; [super tearDown]; @@ -111,7 +103,7 @@ - (void)testBackPaginationForScenario1 [self createScenario1:bobRestClient inRoom:roomId expectation:expectation onComplete:^{ - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -198,7 +190,7 @@ - (void)testLiveEventsForScenario1 { [matrixSDKTestsData doMXRestClientTestWithBobAndARoom:self readyToTest:^(MXRestClient *bobRestClient, NSString *roomId, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ diff --git a/MatrixSDKTests/MXRoomStateTests.m b/MatrixSDKTests/MXRoomStateTests.m index 0be253ea10..88f2d41b44 100644 --- a/MatrixSDKTests/MXRoomStateTests.m +++ b/MatrixSDKTests/MXRoomStateTests.m @@ -30,8 +30,6 @@ @interface MXRoomStateTests : XCTestCase { MatrixSDKTestsData *matrixSDKTestsData; - - MXSession *mxSession; } @end @@ -46,12 +44,6 @@ - (void)setUp - (void)tearDown { - if (mxSession) - { - [mxSession close]; - mxSession = nil; - } - matrixSDKTestsData = nil; [super tearDown]; @@ -59,9 +51,7 @@ - (void)tearDown - (void)testIsJoinRulePublic { - [matrixSDKTestsData doMXSessionTestWithBobAndThePublicRoom:self readyToTest:^(MXSession *mxSession2, MXRoom *room, XCTestExpectation *expectation) { - - mxSession = mxSession2; + [matrixSDKTestsData doMXSessionTestWithBobAndThePublicRoom:self readyToTest:^(MXSession *mxSession, MXRoom *room, XCTestExpectation *expectation) { [room state:^(MXRoomState *roomState) { @@ -74,9 +64,7 @@ - (void)testIsJoinRulePublic - (void)testIsJoinRulePublicForAPrivateRoom { - [matrixSDKTestsData doMXSessionTestWithBobAndARoomWithMessages:self readyToTest:^(MXSession *mxSession2, MXRoom *room, XCTestExpectation *expectation) { - - mxSession = mxSession2; + [matrixSDKTestsData doMXSessionTestWithBobAndARoomWithMessages:self readyToTest:^(MXSession *mxSession, MXRoom *room, XCTestExpectation *expectation) { [room state:^(MXRoomState *roomState) { XCTAssertFalse(roomState.isJoinRulePublic, @"This room join rule must be private"); @@ -94,7 +82,7 @@ - (void)testRoomTopicProvidedByInitialSync [bobRestClient setRoomTopic:roomId topic:@"My topic" success:^{ - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -127,7 +115,7 @@ - (void)testRoomTopicLive MXRestClient *bobRestClient2 = bobRestClient; - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -177,7 +165,7 @@ - (void)testRoomAvatarProvidedByInitialSync [bobRestClient setRoomAvatar:roomId avatar:@"http://matrix.org/matrix.png" success:^{ - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -210,7 +198,7 @@ - (void)testRoomAvatarLive MXRestClient *bobRestClient2 = bobRestClient; - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -258,7 +246,7 @@ - (void)testRoomNameProvidedByInitialSync [bobRestClient setRoomName:roomId name:@"My room name" success:^{ - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -292,7 +280,7 @@ - (void)testRoomNameLive MXRestClient *bobRestClient2 = bobRestClient; - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -340,7 +328,7 @@ - (void)testRoomHistoryVisibilityProvidedByInitialSync [bobRestClient setRoomHistoryVisibility:roomId historyVisibility:kMXRoomHistoryVisibilityWorldReadable success:^{ - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -374,7 +362,7 @@ - (void)testRoomHistoryVisibilityLive MXRestClient *bobRestClient2 = bobRestClient; - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -423,7 +411,7 @@ - (void)testRoomJoinRuleProvidedByInitialSync [bobRestClient setRoomJoinRule:roomId joinRule:kMXRoomJoinRulePublic success:^{ - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -456,7 +444,7 @@ - (void)testRoomJoinRuleLive MXRestClient *bobRestClient2 = bobRestClient; - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -505,7 +493,7 @@ - (void)testRoomGuestAccessProvidedByInitialSync [bobRestClient setRoomGuestAccess:roomId guestAccess:kMXRoomGuestAccessCanJoin success:^{ - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -538,7 +526,7 @@ - (void)testRoomGuestAccessLive MXRestClient *bobRestClient2 = bobRestClient; - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -592,7 +580,7 @@ - (void)testRoomCanonicalAliasProvidedByInitialSync // Use this alias as the canonical alias [bobRestClient2 setRoomCanonicalAlias:roomId canonicalAlias:roomAlias success:^{ - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -636,7 +624,7 @@ - (void)testRoomCanonicalAliasLive MXRestClient *bobRestClient2 = bobRestClient; - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -703,7 +691,7 @@ - (void)testMembers { [matrixSDKTestsData doMXRestClientTestInABobRoomAndANewTextMessage:self newTextMessage:@"This is a text message for recents" onReadyToTest:^(MXRestClient *bobRestClient, NSString *roomId, NSString *new_text_message_eventId, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -741,9 +729,7 @@ - (void)testMembers - (void)testMemberName { - [matrixSDKTestsData doMXSessionTestWithBobAndThePublicRoom:self readyToTest:^(MXSession *mxSession2, MXRoom *room, XCTestExpectation *expectation) { - - mxSession = mxSession2; + [matrixSDKTestsData doMXSessionTestWithBobAndThePublicRoom:self readyToTest:^(MXSession *mxSession, MXRoom *room, XCTestExpectation *expectation) { NSString *bobUserId = matrixSDKTestsData.bobCredentials.userId; @@ -766,9 +752,7 @@ - (void)testMemberName - (void)testStateEvents { - [matrixSDKTestsData doMXSessionTestWithBobAndARoomWithMessages:self readyToTest:^(MXSession *mxSession2, MXRoom *room, XCTestExpectation *expectation) { - - mxSession = mxSession2; + [matrixSDKTestsData doMXSessionTestWithBobAndARoomWithMessages:self readyToTest:^(MXSession *mxSession, MXRoom *room, XCTestExpectation *expectation) { [room state:^(MXRoomState *roomState) { XCTAssertNotNil(roomState.stateEvents); @@ -781,9 +765,7 @@ - (void)testStateEvents - (void)testAliases { - [matrixSDKTestsData doMXSessionTestWithBobAndThePublicRoom:self readyToTest:^(MXSession *mxSession2, MXRoom *room, XCTestExpectation *expectation) { - - mxSession = mxSession2; + [matrixSDKTestsData doMXSessionTestWithBobAndThePublicRoom:self readyToTest:^(MXSession *mxSession, MXRoom *room, XCTestExpectation *expectation) { [room state:^(MXRoomState *roomState) { XCTAssertNotNil(roomState.aliases); @@ -868,9 +850,7 @@ - (void)testInviteByOtherInInitialSync [self createInviteByUserScenario:bobRestClient inRoom:roomId inviteAlice:YES expectation:expectation onComplete:^{ - [matrixSDKTestsData doMXSessionTestWithAlice:nil andStore:[MXMemoryStore new] readyToTest:^(MXSession *aliceSession, XCTestExpectation *expectation2) { - - mxSession = aliceSession; + [matrixSDKTestsData doMXSessionTestWithAlice:nil andStore:[MXMemoryStore new] readyToTest:^(MXSession *mxSession, XCTestExpectation *expectation2) { MXRoom *newRoom = [mxSession roomWithRoomId:roomId]; @@ -883,7 +863,7 @@ - (void)testInviteByOtherInInitialSync [newRoom members:^(MXRoomMembers *roomMembers) { - MXRoomMember *alice = [roomMembers memberWithUserId:aliceSession.myUserId]; + MXRoomMember *alice = [roomMembers memberWithUserId:mxSession.myUserId]; XCTAssertNotNil(alice); XCTAssertEqual(alice.membership, MXMembershipInvite); XCTAssert([alice.originUserId isEqualToString:bobRestClient.credentials.userId], @"Wrong inviter: %@", alice.originUserId); @@ -918,9 +898,7 @@ - (void)testInviteByOtherInLive { [matrixSDKTestsData doMXRestClientTestWithBobAndARoom:self readyToTest:^(MXRestClient *bobRestClient, NSString *roomId, XCTestExpectation *expectation) { - [matrixSDKTestsData doMXSessionTestWithAlice:nil andStore:[MXMemoryStore new] readyToTest:^(MXSession *aliceSession, XCTestExpectation *expectation2) { - - mxSession = aliceSession; + [matrixSDKTestsData doMXSessionTestWithAlice:nil andStore:[MXMemoryStore new] readyToTest:^(MXSession *mxSession, XCTestExpectation *expectation2) { __block MXRoom *newRoom; __block id listener; @@ -943,7 +921,7 @@ - (void)testInviteByOtherInLive [newRoom members:^(MXRoomMembers *roomMembers) { - MXRoomMember *alice = [roomMembers memberWithUserId:aliceSession.myUserId]; + MXRoomMember *alice = [roomMembers memberWithUserId:mxSession.myUserId]; XCTAssertNotNil(alice); XCTAssertEqual(alice.membership, MXMembershipInvite); XCTAssert([alice.originUserId isEqualToString:bobRestClient.credentials.userId], @"Wrong inviter: %@", alice.originUserId); @@ -998,7 +976,7 @@ - (void)testMXRoomJoin [matrixSDKTestsData doMXRestClientTestWithAlice:nil readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation2) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -1080,7 +1058,7 @@ - (void)testMXSessionJoinOnPublicRoom [matrixSDKTestsData doMXRestClientTestWithAlice:nil readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation2) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -1142,7 +1120,7 @@ - (void)testPowerLevels { [matrixSDKTestsData doMXRestClientTestWithBobAndAliceInARoom:self readyToTest:^(MXRestClient *bobRestClient, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -1207,7 +1185,7 @@ - (void)testRoomStateWhenARoomHasBeenJoinedOnAnotherMatrixClient { [matrixSDKTestsData doMXRestClientTestWithAlice:self readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -1263,7 +1241,7 @@ - (void)testRoomStateWhenARoomHasBeenJoinedOnAnotherMatrixClient - (void)testRoomStateWhenARoomHasBeenJoinedOnAnotherMatrixClientAndNotifications { [matrixSDKTestsData doMXRestClientTestWithAlice:self readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -1314,22 +1292,20 @@ - (void)testRoomStateWhenARoomHasBeenJoinedOnAnotherMatrixClientAndNotifications - (void)testDeallocation { __weak __block MXRoomState *weakState; - [matrixSDKTestsData doMXSessionTestWithBobAndThePublicRoom:self readyToTest:^(MXSession *mxSession2, MXRoom *room, XCTestExpectation *expectation) { - mxSession = mxSession2; + [matrixSDKTestsData doMXSessionTestWithBobAndThePublicRoom:self readyToTest:^(MXSession *mxSession, MXRoom *room, XCTestExpectation *expectation) { [room state:^(MXRoomState *roomState) { weakState = roomState; XCTAssertNotNil(weakState); [expectation fulfill]; }]; - [mxSession2 close]; // Force room deallocation }]; XCTAssertNil(weakState); } - (void)testCopying { - [matrixSDKTestsData doMXSessionTestWithBobAndThePublicRoom:self readyToTest:^(MXSession *mxSession2, MXRoom *room, XCTestExpectation *expectation) { - mxSession = mxSession2; + [matrixSDKTestsData doMXSessionTestWithBobAndThePublicRoom:self readyToTest:^(MXSession *mxSession, MXRoom *room, XCTestExpectation *expectation) { + [room state:^(MXRoomState *roomState) { MXRoomState *roomStateCopy = [roomState copy]; XCTAssertEqual(roomStateCopy.members.members.count, roomState.members.members.count); diff --git a/MatrixSDKTests/MXRoomTests.m b/MatrixSDKTests/MXRoomTests.m index 620d78756f..17a40b9a77 100644 --- a/MatrixSDKTests/MXRoomTests.m +++ b/MatrixSDKTests/MXRoomTests.m @@ -29,8 +29,6 @@ @interface MXRoomTests : XCTestCase { MatrixSDKTestsData *matrixSDKTestsData; - - MXSession *mxSession; } @end @@ -46,12 +44,6 @@ - (void)setUp - (void)tearDown { - if (mxSession) - { - [mxSession close]; - mxSession = nil; - } - matrixSDKTestsData = nil; [super tearDown]; @@ -60,9 +52,7 @@ - (void)tearDown - (void)testListenerForAllLiveEvents { - [matrixSDKTestsData doMXSessionTestWithBobAndThePublicRoom:self readyToTest:^(MXSession *mxSession2, MXRoom *room, XCTestExpectation *expectation) { - - mxSession = mxSession2; + [matrixSDKTestsData doMXSessionTestWithBobAndThePublicRoom:self readyToTest:^(MXSession *mxSession, MXRoom *room, XCTestExpectation *expectation) { __block NSString *sentMessageEventID; __block NSString *receivedMessageEventID; @@ -117,9 +107,7 @@ - (void)testListenerForAllLiveEvents - (void)testListenerForRoomMessageLiveEvents { - [matrixSDKTestsData doMXSessionTestWithBobAndThePublicRoom:self readyToTest:^(MXSession *mxSession2, MXRoom *room, XCTestExpectation *expectation) { - - mxSession = mxSession2; + [matrixSDKTestsData doMXSessionTestWithBobAndThePublicRoom:self readyToTest:^(MXSession *mxSession, MXRoom *room, XCTestExpectation *expectation) { __block NSString *sentMessageEventID; __block NSString *receivedMessageEventID; @@ -174,9 +162,7 @@ - (void)testListenerForRoomMessageLiveEvents - (void)testLeave { - [matrixSDKTestsData doMXSessionTestWithBobAndARoomWithMessages:self readyToTest:^(MXSession *mxSession2, MXRoom *room, XCTestExpectation *expectation) { - - mxSession = mxSession2; + [matrixSDKTestsData doMXSessionTestWithBobAndARoomWithMessages:self readyToTest:^(MXSession *mxSession, MXRoom *room, XCTestExpectation *expectation) { NSString *roomId = room.roomId; @@ -211,7 +197,7 @@ - (void)testJoin [matrixSDKTestsData doMXRestClientTestWithAlice:nil readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation2) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; [matrixSDKTestsData retain:mxSession]; [bobRestClient inviteUser:aliceRestClient.credentials.userId toRoom:roomId success:^{ @@ -255,7 +241,7 @@ - (void)testSetPowerLevelOfUser { [matrixSDKTestsData doMXRestClientTestWithBobAndAliceInARoom:self readyToTest:^(MXRestClient *bobRestClient, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -288,7 +274,7 @@ - (void)testPaginateBackMessagesCancel { [matrixSDKTestsData doMXRestClientTestWithBobAndARoomWithMessages:self readyToTest:^(MXRestClient *bobRestClient, NSString *roomId, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession startWithSyncFilter:[MXFilterJSONModel syncFilterWithMessageLimit:0] onServerSyncDone:^{ @@ -332,7 +318,7 @@ - (void)testTypingUsersNotifications { [matrixSDKTestsData doMXRestClientTestWithBobAndARoom:self readyToTest:^(MXRestClient *bobRestClient, NSString *roomId, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -367,8 +353,7 @@ - (void)testTypingUsersNotifications - (void)testAddAndRemoveTag { - [matrixSDKTestsData doMXSessionTestWithBobAndARoomWithMessages:self readyToTest:^(MXSession *mxSession2, MXRoom *room, XCTestExpectation *expectation) { - mxSession = mxSession2; + [matrixSDKTestsData doMXSessionTestWithBobAndARoomWithMessages:self readyToTest:^(MXSession *mxSession, MXRoom *room, XCTestExpectation *expectation) { NSString *tag = @"aTag"; NSString *order = @"0.5"; @@ -415,8 +400,7 @@ - (void)testAddAndRemoveTag - (void)testReplaceTag { - [matrixSDKTestsData doMXSessionTestWithBobAndARoomWithMessages:self readyToTest:^(MXSession *mxSession2, MXRoom *room, XCTestExpectation *expectation) { - mxSession = mxSession2; + [matrixSDKTestsData doMXSessionTestWithBobAndARoomWithMessages:self readyToTest:^(MXSession *mxSession, MXRoom *room, XCTestExpectation *expectation) { NSString *tag = @"aTag"; NSString *order = @"0.5"; @@ -458,7 +442,7 @@ - (void)testTagEvent { [matrixSDKTestsData doMXRestClientTestInABobRoomAndANewTextMessage:self newTextMessage:@"This is a text message for tagged events" onReadyToTest:^(MXRestClient *bobRestClient, NSString *roomId, NSString *new_text_message_eventId, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -501,7 +485,7 @@ - (void)testUntagEvent { [matrixSDKTestsData doMXRestClientTestInABobRoomAndANewTextMessage:self newTextMessage:@"This is a text message for tagged events" onReadyToTest:^(MXRestClient *bobRestClient, NSString *roomId, NSString *new_text_message_eventId, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -558,7 +542,7 @@ - (void)testGetTaggedEvent { [matrixSDKTestsData doMXRestClientTestInABobRoomAndANewTextMessage:self newTextMessage:@"This is a text message for tagged events" onReadyToTest:^(MXRestClient *bobRestClient, NSString *roomId, NSString *new_text_message_eventId, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -620,7 +604,7 @@ - (void)testRoomDirectoryVisibilityProvidedByInitialSync [bobRestClient setRoomDirectoryVisibility:roomId directoryVisibility:kMXRoomDirectoryVisibilityPublic success:^{ - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -658,7 +642,7 @@ - (void)tesRoomDirectoryVisibilityLive MXRestClient *bobRestClient2 = bobRestClient; - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient2]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ diff --git a/MatrixSDKTests/MXSessionTests.m b/MatrixSDKTests/MXSessionTests.m index b63b87d963..ddd4af7711 100644 --- a/MatrixSDKTests/MXSessionTests.m +++ b/MatrixSDKTests/MXSessionTests.m @@ -36,8 +36,6 @@ @interface MXSessionTests : XCTestCase { MatrixSDKTestsData *matrixSDKTestsData; - MXSession *mxSession; - id observer; } @end @@ -53,12 +51,6 @@ - (void)setUp - (void)tearDown { - if (mxSession) - { - [mxSession close]; - mxSession = nil; - } - if (observer) { [[NSNotificationCenter defaultCenter] removeObserver:observer]; @@ -114,7 +106,7 @@ - (void)testInitialSyncFailure MXCredentials *credentials = [MXCredentials initialSyncCacheCredentialsFrom:matrixSDKTestsData.bobCredentials]; id cache = [[MXSyncResponseFileStore alloc] initWithCredentials:credentials]; - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + __block MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; // listen for session state change notification __block id observer = [[NSNotificationCenter defaultCenter] addObserverForName:kMXSessionStateDidChangeNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) { @@ -126,7 +118,6 @@ - (void)testInitialSyncFailure // 2. simulate an unexpected session close (like a crash) [mxSession close]; - mxSession = nil; XCTAssertGreaterThan(cache.syncResponseIds.count, 0, @@ -186,7 +177,7 @@ - (void)testRoomWithAlias // Room with a tag with "oranges" order [bobRestClient createRoom:nil visibility:kMXRoomDirectoryVisibilityPrivate roomAlias:alias topic:nil success:^(MXCreateRoomResponse *response) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -227,7 +218,7 @@ - (void)testListenerForAllLiveEvents { [matrixSDKTestsData doMXRestClientTestWihBobAndSeveralRoomsAndMessages:self readyToTest:^(MXRestClient *bobRestClient, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; // The listener must catch at least these events @@ -304,7 +295,7 @@ - (void)testListenerForRoomMessageOnly { [matrixSDKTestsData doMXRestClientTestWihBobAndSeveralRoomsAndMessages:self readyToTest:^(MXRestClient *bobRestClient, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; // Listen to m.room.message only @@ -346,7 +337,7 @@ - (void)testListenerForPresence // Make sure Alice and Bob have activities [matrixSDKTestsData doMXRestClientTestWithBobAndAliceInARoom:self readyToTest:^(MXRestClient *bobRestClient, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; __block MXSession *mxSession2 = mxSession; @@ -405,7 +396,7 @@ - (void)testClose // Make sure Alice and Bob have activities [matrixSDKTestsData doMXRestClientTestWithBobAndAliceInARoom:self readyToTest:^(MXRestClient *bobRestClient, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -467,7 +458,7 @@ - (void)testCloseWithMXMemoryStore MXMemoryStore *store = [[MXMemoryStore alloc] init]; - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession setStore:store success:^{ @@ -479,7 +470,6 @@ - (void)testCloseWithMXMemoryStore XCTAssertGreaterThan(storeRoomsCount, 0); [mxSession close]; - mxSession = nil; // Create another random room to create more data server side [bobRestClient createRoom:nil visibility:kMXRoomDirectoryVisibilityPrivate roomAlias:nil topic:nil success:^(MXCreateRoomResponse *response) { @@ -512,7 +502,7 @@ - (void)testPauseResume // Make sure Alice and Bob have activities [matrixSDKTestsData doMXRestClientTestWithBobAndAliceInARoom:self readyToTest:^(MXRestClient *bobRestClient, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -584,7 +574,7 @@ - (void)testPauseResumeOnNothingNew // Make sure Alice and Bob have activities [matrixSDKTestsData doMXRestClientTestWithBobAndAliceInARoom:self readyToTest:^(MXRestClient *bobRestClient, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -650,6 +640,7 @@ - (void)testState { [matrixSDKTestsData doMXRestClientTestInABobRoomAndANewTextMessage:self newTextMessage:@"This is a text message for recents" onReadyToTest:^(MXRestClient *bobRestClient, NSString *roomId, NSString *new_text_message_eventId, XCTestExpectation *expectation) { + MXSession *mxSession; __block MXSessionState previousSessionState = MXSessionStateInitialised; [[NSNotificationCenter defaultCenter] addObserverForName:kMXSessionStateDidChangeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { @@ -682,7 +673,6 @@ - (void)testState [mxSession close]; XCTAssertEqual(MXSessionStateClosed, mxSession.state); - mxSession = nil; [expectation fulfill]; }); @@ -704,9 +694,7 @@ - (void)testState - (void)testCreateRoom { - [matrixSDKTestsData doMXSessionTestWithBob:self readyToTest:^(MXSession *mxSession2, XCTestExpectation *expectation) { - - mxSession = mxSession2; + [matrixSDKTestsData doMXSessionTestWithBob:self readyToTest:^(MXSession *mxSession, XCTestExpectation *expectation) { // Create a random room with no params [mxSession createRoom:nil visibility:nil roomAlias:nil topic:nil success:^(MXRoom *room) { @@ -729,9 +717,7 @@ - (void)testCreateRoom - (void)testDidSyncNotification { - [matrixSDKTestsData doMXSessionTestWithBobAndARoom:self andStore:[[MXMemoryStore alloc] init] readyToTest:^(MXSession *mxSession2, MXRoom *room, XCTestExpectation *expectation) { - - mxSession = mxSession2; + [matrixSDKTestsData doMXSessionTestWithBobAndARoom:self andStore:[[MXMemoryStore alloc] init] readyToTest:^(MXSession *mxSession, MXRoom *room, XCTestExpectation *expectation) { observer = [[NSNotificationCenter defaultCenter] addObserverForName:kMXSessionDidSyncNotification object:mxSession queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { @@ -759,8 +745,7 @@ - (void)testDidSyncNotification // -> Check latter sync response does not contain anything but the event stream token - (void)testEmptySyncResponse { - [matrixSDKTestsData doMXSessionTestWithBob:self readyToTest:^(MXSession *mxSession2, XCTestExpectation *expectation) { - mxSession = mxSession2; + [matrixSDKTestsData doMXSessionTestWithBob:self readyToTest:^(MXSession *mxSession, XCTestExpectation *expectation) { __block BOOL isFirst = YES; @@ -794,12 +779,10 @@ - (void)testEmptySyncResponse - (void)testCreateRoomWithInvite { - [matrixSDKTestsData doMXSessionTestWithBob:self readyToTest:^(MXSession *mxSession2, XCTestExpectation *expectation) { + [matrixSDKTestsData doMXSessionTestWithBob:self readyToTest:^(MXSession *mxSession, XCTestExpectation *expectation) { [matrixSDKTestsData doMXRestClientTestWithAlice:nil readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation2) { - mxSession = mxSession2; - // Create a random room with no params MXRoomCreationParameters *parameters = [MXRoomCreationParameters new]; parameters.inviteArray = @[matrixSDKTestsData.aliceCredentials.userId]; @@ -849,12 +832,10 @@ - (void)testCreateRoomWithInvite - (void)testCreateDirectRoom { - [matrixSDKTestsData doMXSessionTestWithBob:self readyToTest:^(MXSession *mxSession2, XCTestExpectation *expectation) { + [matrixSDKTestsData doMXSessionTestWithBob:self readyToTest:^(MXSession *mxSession, XCTestExpectation *expectation) { [matrixSDKTestsData doMXRestClientTestWithAlice:nil readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation2) { - mxSession = mxSession2; - // Create a random room with no params MXRoomCreationParameters *parameters = [MXRoomCreationParameters parametersForDirectRoomWithUser:matrixSDKTestsData.aliceCredentials.userId]; [mxSession createRoomWithParameters:parameters success:^(MXRoom *room) { @@ -884,6 +865,7 @@ - (void)testCreateDirectRoom XCTAssertTrue(succeed); // Force sync to get direct rooms list + // CRASH [mxSession startWithSyncFilter:[MXFilterJSONModel syncFilterWithMessageLimit:0] onServerSyncDone:^{ @@ -924,9 +906,7 @@ - (void)testCreateDirectRoom - (void)testPrivateDirectRoomWithUserId { - [matrixSDKTestsData doMXSessionTestWithBobAndAliceInARoom:self readyToTest:^(MXSession *bobSession, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { - - mxSession = bobSession; + [matrixSDKTestsData doMXSessionTestWithBobAndAliceInARoom:self readyToTest:^(MXSession *mxSession, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { MXRoom *room = [mxSession roomWithRoomId:roomId]; [room setIsDirect:YES withUserId:aliceRestClient.credentials.userId success:^{ @@ -963,7 +943,7 @@ - (void)testNewRoomNotificationOnInvite [matrixSDKTestsData doMXRestClientTestWithAlice:nil readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation2) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -990,7 +970,7 @@ - (void)testNewRoomNotificationOnCreatingPublicRoom { [matrixSDKTestsData doMXRestClientTestWithBob:self readyToTest:^(MXRestClient *bobRestClient, XCTestExpectation *expectation) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -1026,7 +1006,7 @@ - (void)testNewRoomNotificationOnJoiningPublicRoom [matrixSDKTestsData doMXRestClientTestWithAlice:nil readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation2) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -1063,7 +1043,7 @@ - (void)testMXRoomInitialSyncNotificationOnJoiningPublicRoom [matrixSDKTestsData doMXRestClientTestWithAlice:nil readyToTest:^(MXRestClient *aliceRestClient, XCTestExpectation *expectation2) { - mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:aliceRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -1119,7 +1099,7 @@ - (void)doRoomByTagsOrderTest:(XCTestCase*)testCase withOrder1:(NSString*)order1 // Do the test - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -1211,7 +1191,7 @@ - (void)testTagRoomsWithSameOrder [bobRestClient addTag:tag withOrder:@"0.2" toRoom:response.roomId success:^{ // Do the tests - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -1259,7 +1239,7 @@ - (void)testRoomByTagsAndNoRoomTag [bobRestClient createRoom:nil visibility:kMXRoomDirectoryVisibilityPrivate roomAlias:nil topic:@"Not tagged" success:^(MXCreateRoomResponse *response) { // Do the test - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -1319,7 +1299,7 @@ - (void)testTagOrderToBeAtIndex [bobRestClient addTag:tag withOrder:@"0.3" toRoom:response.roomId success:^{ // Do the tests - mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; + MXSession *mxSession = [[MXSession alloc] initWithMatrixRestClient:bobRestClient]; [matrixSDKTestsData retain:mxSession]; [mxSession start:^{ @@ -1384,9 +1364,7 @@ - (void)testTagOrderToBeAtIndex - (void)testInvitedRooms { - [matrixSDKTestsData doMXSessionTestWithBobAndAliceInARoom:self readyToTest:^(MXSession *bobSession, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { - - mxSession = bobSession; + [matrixSDKTestsData doMXSessionTestWithBobAndAliceInARoom:self readyToTest:^(MXSession *mxSession, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { NSUInteger prevInviteCount = mxSession.invitedRooms.count; @@ -1437,7 +1415,7 @@ - (void)testInvitedRooms testRoomId = response.roomId; - [aliceRestClient inviteUser:bobSession.matrixRestClient.credentials.userId toRoom:testRoomId success:^{ + [aliceRestClient inviteUser:mxSession.matrixRestClient.credentials.userId toRoom:testRoomId success:^{ } failure:^(NSError *error) { XCTFail(@"Cannot set up intial test conditions - error: %@", error); @@ -1453,9 +1431,7 @@ - (void)testInvitedRooms - (void)testToDeviceEvents { - [matrixSDKTestsData doMXSessionTestWithBobAndAliceInARoom:self readyToTest:^(MXSession *bobSession, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { - - mxSession = bobSession; + [matrixSDKTestsData doMXSessionTestWithBobAndAliceInARoom:self readyToTest:^(MXSession *mxSession, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { observer = [[NSNotificationCenter defaultCenter] addObserverForName:kMXSessionOnToDeviceEventNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { diff --git a/MatrixSDKTests/MXVoIPTests.m b/MatrixSDKTests/MXVoIPTests.m index 40ddb2f767..20efdb9d7b 100644 --- a/MatrixSDKTests/MXVoIPTests.m +++ b/MatrixSDKTests/MXVoIPTests.m @@ -25,8 +25,6 @@ @interface MXVoIPTests : XCTestCase { MatrixSDKTestsData *matrixSDKTestsData; - - MXSession *mxSession; } @end @@ -42,12 +40,6 @@ - (void)setUp - (void)tearDown { - if (mxSession) - { - [mxSession close]; - mxSession = nil; - } - matrixSDKTestsData = nil; [super tearDown]; @@ -57,9 +49,8 @@ - (void)tearDown #pragma mark - Tests with no call stack - (void)testNoVoIPStackMXRoomCall { - [matrixSDKTestsData doMXSessionTestWithBobAndAliceInARoom:self readyToTest:^(MXSession *bobSession, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { + [matrixSDKTestsData doMXSessionTestWithBobAndAliceInARoom:self readyToTest:^(MXSession *mxSession, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { - mxSession = bobSession; MXRoom *room = [mxSession roomWithRoomId:roomId]; // Make sure there is no VoIP stack @@ -79,9 +70,7 @@ - (void)testNoVoIPStackMXRoomCall - (void)testNoVoIPStackOnCallInvite { - [matrixSDKTestsData doMXSessionTestWithBobAndAliceInARoom:self readyToTest:^(MXSession *bobSession, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { - - mxSession = bobSession; + [matrixSDKTestsData doMXSessionTestWithBobAndAliceInARoom:self readyToTest:^(MXSession *mxSession, MXRestClient *aliceRestClient, NSString *roomId, XCTestExpectation *expectation) { // Make sure there is no VoIP stack mxSession.callManager.callStack = nil; @@ -98,8 +87,8 @@ - (void)testNoVoIPStackOnCallInvite }, @"version": kMXCallVersion, @"lifetime": @(30 * 1000), - @"invitee": bobSession.myUserId, - @"party_id": bobSession.myDeviceId + @"invitee": mxSession.myUserId, + @"party_id": mxSession.myDeviceId }; From 1bf93b796ca41297e8a4c639047cb6f4edaf2f61 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 24 Sep 2021 09:01:24 +0200 Subject: [PATCH 11/42] change file --- changelog.d/4875.change | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/4875.change diff --git a/changelog.d/4875.change b/changelog.d/4875.change new file mode 100644 index 0000000000..c80c1cdf1c --- /dev/null +++ b/changelog.d/4875.change @@ -0,0 +1 @@ +Tests: Improve tests suites execution time by fixing leaked MXSession instances that continued to run in background. \ No newline at end of file From 74b11a746e59bd1ae4325b5944fd836747c7e035 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 24 Sep 2021 09:15:18 +0200 Subject: [PATCH 12/42] Tests: some cleaning after review --- .../xcshareddata/xcschemes/MatrixSDK-macOS.xcscheme | 3 --- MatrixSDKTests/Utils/TestObserver.swift | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/MatrixSDK.xcodeproj/xcshareddata/xcschemes/MatrixSDK-macOS.xcscheme b/MatrixSDK.xcodeproj/xcshareddata/xcschemes/MatrixSDK-macOS.xcscheme index 84a69f6dba..51cd937315 100644 --- a/MatrixSDK.xcodeproj/xcshareddata/xcschemes/MatrixSDK-macOS.xcscheme +++ b/MatrixSDK.xcodeproj/xcshareddata/xcschemes/MatrixSDK-macOS.xcscheme @@ -64,9 +64,6 @@ - - 0 { mxSessionTracker.printOpenMXSessions() // All MXSessions must be closed at the end of the test - // Else, they will continue to run in background and affect tests performance + // Else, they will continue to run in background and affect tests execution performance fatalError("Test \(testCase.name) did not close \(count) MXSession instances") } } From 372dbf013bc335b197d89e03978619b43ad7b442 Mon Sep 17 00:00:00 2001 From: manuroe Date: Tue, 28 Sep 2021 18:33:45 +0200 Subject: [PATCH 13/42] Prepare for new sprint From e77e630889f410f105d0f60c7eb0e7a0dcea4107 Mon Sep 17 00:00:00 2001 From: Doug Date: Wed, 29 Sep 2021 12:57:14 +0100 Subject: [PATCH 14/42] Fix tests. Rename eventsFilterForLastMessage to lastMessageEventTypesAllowList. --- MatrixSDK/Data/MXRoomSummaryUpdater.h | 4 ++-- MatrixSDK/Data/MXRoomSummaryUpdater.m | 2 +- MatrixSDKTests/MXRoomSummaryTests.m | 7 ++++--- MatrixSDKTests/MXStoreTests.m | 6 +++--- changelog.d/4451.api | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/MatrixSDK/Data/MXRoomSummaryUpdater.h b/MatrixSDK/Data/MXRoomSummaryUpdater.h index 0ea2f7fc0f..bc623ece57 100644 --- a/MatrixSDK/Data/MXRoomSummaryUpdater.h +++ b/MatrixSDK/Data/MXRoomSummaryUpdater.h @@ -39,11 +39,11 @@ #pragma mark - Configuration /** - The type of events allowed as last message. + An allow list of event types that should be used as the last message. Default is nil. All messages types are accepted. */ -@property (nonatomic) NSArray *eventsFilterForLastMessage; +@property (nonatomic) NSArray *lastMessageEventTypesAllowList; /** If YES, ignore redacted events as last message. diff --git a/MatrixSDK/Data/MXRoomSummaryUpdater.m b/MatrixSDK/Data/MXRoomSummaryUpdater.m index 6a605b5683..9287b413b9 100644 --- a/MatrixSDK/Data/MXRoomSummaryUpdater.m +++ b/MatrixSDK/Data/MXRoomSummaryUpdater.m @@ -111,7 +111,7 @@ - (BOOL)session:(MXSession *)session updateRoomSummary:(MXRoomSummary *)summary BOOL updated = NO; // Accept event which type is in the filter list - if (event.eventId && (!_eventsFilterForLastMessage || (NSNotFound != [_eventsFilterForLastMessage indexOfObject:event.type]))) + if (event.eventId && (_lastMessageEventTypesAllowList == nil || [_lastMessageEventTypesAllowList containsObject:event.type])) { [summary updateLastMessage:[[MXRoomLastMessage alloc] initWithEvent:event]]; updated = YES; diff --git a/MatrixSDKTests/MXRoomSummaryTests.m b/MatrixSDKTests/MXRoomSummaryTests.m index 71551736c4..42ad978dfb 100644 --- a/MatrixSDKTests/MXRoomSummaryTests.m +++ b/MatrixSDKTests/MXRoomSummaryTests.m @@ -650,13 +650,14 @@ - (void)testMemberProfileChange }]; } -- (void)testIgnoreMemberProfileChanges +- (void)testLastMessageEventTypesAllowList { // Need a store for this test [matrixSDKTestsData doMXSessionTestWithBobAndARoom:self andStore:[[MXMemoryStore alloc] init] readyToTest:^(MXSession *mxSession, MXRoom *room, XCTestExpectation *expectation) { + // Retrieve the summary updater and only allow message events to become the last message. MXRoomSummaryUpdater *defaultUpdater = [MXRoomSummaryUpdater roomSummaryUpdaterForSession:mxSession]; - defaultUpdater.ignoreMemberProfileChanges = YES; + defaultUpdater.lastMessageEventTypesAllowList = @[kMXEventTypeStringRoomMessage]; MXRoomSummary *summary = room.summary; @@ -664,7 +665,7 @@ - (void)testIgnoreMemberProfileChanges observer = [[NSNotificationCenter defaultCenter] addObserverForName:kMXRoomSummaryDidChangeNotification object:summary queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { - XCTFail(@"The last message should not change if ignoreMemberProfileChanges == YES"); + XCTFail(@"The last message should not change when eventTypesFilterForLastMessage == @[kMXEventTypeStringRoomMessage]"); [expectation fulfill]; }]; diff --git a/MatrixSDKTests/MXStoreTests.m b/MatrixSDKTests/MXStoreTests.m index 837f8aa122..98134021cd 100644 --- a/MatrixSDKTests/MXStoreTests.m +++ b/MatrixSDKTests/MXStoreTests.m @@ -728,7 +728,7 @@ - (void)checkLastMessageProfileChange:(MXRoom*)room } -- (void)checkLastMessageIgnoreProfileChange:(MXRoom*)room +- (void)checkLastMessageEventTypesAllowList:(MXRoom*)room { [room.mxSession eventWithEventId:room.summary.lastMessage.eventId inRoom:room.roomId @@ -736,9 +736,9 @@ - (void)checkLastMessageIgnoreProfileChange:(MXRoom*)room XCTAssertEqual(lastMessage.eventType, MXEventTypeRoomMessage); - // Ignore profile change + // Only allow message events to become the last message. MXRoomSummaryUpdater *updater = [MXRoomSummaryUpdater roomSummaryUpdaterForSession:room.mxSession]; - updater.ignoreMemberProfileChanges = YES; + updater.lastMessageEventTypesAllowList = @[kMXEventTypeStringRoomMessage]; [room liveTimeline:^(MXEventTimeline *liveTimeline) { [liveTimeline listenToEventsOfTypes:@[kMXEventTypeStringRoomMember] onEvent:^(MXEvent *event, MXTimelineDirection direction, MXRoomState *roomState) { diff --git a/changelog.d/4451.api b/changelog.d/4451.api index e5e6f6b61c..013ad01148 100644 --- a/changelog.d/4451.api +++ b/changelog.d/4451.api @@ -1 +1 @@ -MXRoomSummaryUpdater: Combine ignoreMemberProfileChanges and eventsFilterForMessages into a single property called eventsFilterForLastMessage. +MXRoomSummaryUpdater: Combine ignoreMemberProfileChanges and eventsFilterForMessages into a single property called allowedLastMessageEventTypes. From 6e0caf97750ac332e316dc394097306396bb8ec9 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Tue, 28 Sep 2021 10:33:25 +0300 Subject: [PATCH 15/42] vector-im/element-ios/issues/4899 - Added dynamism and compile time safety to room name and send reply event localizable strings. --- MatrixSDK.xcodeproj/project.pbxproj | 136 +++++++++--------- MatrixSDK/Contrib/Swift/Data/MXRoom.swift | 6 +- MatrixSDK/Data/MXRoom.h | 6 +- MatrixSDK/Data/MXRoom.m | 36 ++--- .../MXRoomNameDefaultStringLocalizations.m | 43 ------ ...s.h => MXRoomNameDefaultStringLocalizer.h} | 8 +- .../Data/MXRoomNameDefaultStringLocalizer.m | 41 ++++++ ....h => MXRoomNameStringLocalizerProtocol.h} | 18 ++- MatrixSDK/Data/MXRoomSummaryUpdater.h | 6 +- MatrixSDK/Data/MXRoomSummaryUpdater.m | 36 ++--- ...SendReplyEventDefaultStringLocalizations.h | 32 ----- .../MXSendReplyEventDefaultStringLocalizer.h | 25 ++++ ... MXSendReplyEventDefaultStringLocalizer.m} | 15 +- ...MXSendReplyEventStringLocalizerProtocol.h} | 22 +-- MatrixSDKTests/MXCryptoTests.m | 8 +- MatrixSDKTests/MXRoomTests.m | 8 +- changelog.d/4899.api | 1 + changelog.d/4899.change | 1 + 18 files changed, 225 insertions(+), 223 deletions(-) delete mode 100644 MatrixSDK/Data/MXRoomNameDefaultStringLocalizations.m rename MatrixSDK/Data/{MXRoomNameDefaultStringLocalizations.h => MXRoomNameDefaultStringLocalizer.h} (69%) create mode 100644 MatrixSDK/Data/MXRoomNameDefaultStringLocalizer.m rename MatrixSDK/Data/{MXRoomNameStringsLocalizable.h => MXRoomNameStringLocalizerProtocol.h} (64%) delete mode 100644 MatrixSDK/Data/MXSendReplyEventDefaultStringLocalizations.h create mode 100644 MatrixSDK/Data/MXSendReplyEventDefaultStringLocalizer.h rename MatrixSDK/Data/{MXSendReplyEventDefaultStringLocalizations.m => MXSendReplyEventDefaultStringLocalizer.m} (64%) rename MatrixSDK/Data/{MXSendReplyEventStringsLocalizable.h => MXSendReplyEventStringLocalizerProtocol.h} (54%) create mode 100644 changelog.d/4899.api create mode 100644 changelog.d/4899.change diff --git a/MatrixSDK.xcodeproj/project.pbxproj b/MatrixSDK.xcodeproj/project.pbxproj index e54900dca0..83e2487b15 100644 --- a/MatrixSDK.xcodeproj/project.pbxproj +++ b/MatrixSDK.xcodeproj/project.pbxproj @@ -21,6 +21,18 @@ 181FD5D52660C791008EC084 /* MXLogObjcWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 181FD5D22660C791008EC084 /* MXLogObjcWrapper.h */; settings = {ATTRIBUTES = (Public, ); }; }; 181FD5D62660C791008EC084 /* MXLogObjcWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 181FD5D32660C791008EC084 /* MXLogObjcWrapper.m */; }; 181FD5D72660C791008EC084 /* MXLogObjcWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 181FD5D32660C791008EC084 /* MXLogObjcWrapper.m */; }; + 183892762702F553003F0C4F /* MXRoomNameDefaultStringLocalizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 1838926F2702F552003F0C4F /* MXRoomNameDefaultStringLocalizer.h */; }; + 183892772702F553003F0C4F /* MXRoomNameDefaultStringLocalizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 1838926F2702F552003F0C4F /* MXRoomNameDefaultStringLocalizer.h */; }; + 1838927A2702F553003F0C4F /* MXSendReplyEventDefaultStringLocalizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 183892712702F553003F0C4F /* MXSendReplyEventDefaultStringLocalizer.m */; }; + 1838927B2702F553003F0C4F /* MXSendReplyEventDefaultStringLocalizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 183892712702F553003F0C4F /* MXSendReplyEventDefaultStringLocalizer.m */; }; + 1838927E2702F553003F0C4F /* MXSendReplyEventDefaultStringLocalizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 183892732702F553003F0C4F /* MXSendReplyEventDefaultStringLocalizer.h */; }; + 1838927F2702F553003F0C4F /* MXSendReplyEventDefaultStringLocalizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 183892732702F553003F0C4F /* MXSendReplyEventDefaultStringLocalizer.h */; }; + 183892802702F553003F0C4F /* MXRoomNameDefaultStringLocalizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 183892742702F553003F0C4F /* MXRoomNameDefaultStringLocalizer.m */; }; + 183892812702F553003F0C4F /* MXRoomNameDefaultStringLocalizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 183892742702F553003F0C4F /* MXRoomNameDefaultStringLocalizer.m */; }; + 1838928627031D1D003F0C4F /* MXRoomNameStringLocalizerProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 1838928427031D1D003F0C4F /* MXRoomNameStringLocalizerProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1838928727031D1D003F0C4F /* MXRoomNameStringLocalizerProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 1838928427031D1D003F0C4F /* MXRoomNameStringLocalizerProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1838928827031D1D003F0C4F /* MXSendReplyEventStringLocalizerProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 1838928527031D1D003F0C4F /* MXSendReplyEventStringLocalizerProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1838928927031D1D003F0C4F /* MXSendReplyEventStringLocalizerProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 1838928527031D1D003F0C4F /* MXSendReplyEventStringLocalizerProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; 189CC081265E361C00BE1FD8 /* MXLog.h in Headers */ = {isa = PBXBuildFile; fileRef = 189CC07F265E361500BE1FD8 /* MXLog.h */; settings = {ATTRIBUTES = (Public, ); }; }; 189CC082265E361D00BE1FD8 /* MXLog.h in Headers */ = {isa = PBXBuildFile; fileRef = 189CC07F265E361500BE1FD8 /* MXLog.h */; settings = {ATTRIBUTES = (Public, ); }; }; 189CC083265E362600BE1FD8 /* MXLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 189CC080265E361500BE1FD8 /* MXLog.swift */; }; @@ -507,9 +519,6 @@ 32B94E02228EDEBC00716A26 /* MXReactionRelation.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B94E00228EDEBC00716A26 /* MXReactionRelation.m */; }; 32B94E05228EE90300716A26 /* MXRealmReactionRelation.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B94E03228EE90300716A26 /* MXRealmReactionRelation.h */; }; 32B94E06228EE90300716A26 /* MXRealmReactionRelation.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B94E04228EE90300716A26 /* MXRealmReactionRelation.m */; }; - 32BA86AC21529E29008F277E /* MXRoomNameStringsLocalizable.h in Headers */ = {isa = PBXBuildFile; fileRef = 32BA86AB21529AE3008F277E /* MXRoomNameStringsLocalizable.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 32BA86AF2152A79E008F277E /* MXRoomNameDefaultStringLocalizations.h in Headers */ = {isa = PBXBuildFile; fileRef = 32BA86AD2152A79E008F277E /* MXRoomNameDefaultStringLocalizations.h */; }; - 32BA86B02152A79E008F277E /* MXRoomNameDefaultStringLocalizations.m in Sources */ = {isa = PBXBuildFile; fileRef = 32BA86AE2152A79E008F277E /* MXRoomNameDefaultStringLocalizations.m */; }; 32BBAE6C2178E99100D85F46 /* MXKeyBackupData.m in Sources */ = {isa = PBXBuildFile; fileRef = 32BBAE662178E99100D85F46 /* MXKeyBackupData.m */; }; 32BBAE6D2178E99100D85F46 /* MXKeyBackupVersion.h in Headers */ = {isa = PBXBuildFile; fileRef = 32BBAE672178E99100D85F46 /* MXKeyBackupVersion.h */; settings = {ATTRIBUTES = (Public, ); }; }; 32BBAE6F2178E99100D85F46 /* MXKeyBackupVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = 32BBAE692178E99100D85F46 /* MXKeyBackupVersion.m */; }; @@ -874,7 +883,6 @@ B14EF2462397E90400758AF0 /* MXRoomMembers.m in Sources */ = {isa = PBXBuildFile; fileRef = 32618E7A20EFA45B00E1D2EA /* MXRoomMembers.m */; }; B14EF2472397E90400758AF0 /* MXContentScanEncryptedBody.m in Sources */ = {isa = PBXBuildFile; fileRef = 02CAD436217DD12F0074700B /* MXContentScanEncryptedBody.m */; }; B14EF2482397E90400758AF0 /* MXEncryptedAttachments.m in Sources */ = {isa = PBXBuildFile; fileRef = F03EF5071DF071D5009DF592 /* MXEncryptedAttachments.m */; }; - B14EF2492397E90400758AF0 /* MXSendReplyEventDefaultStringLocalizations.m in Sources */ = {isa = PBXBuildFile; fileRef = B172857B2100D4F60052C51E /* MXSendReplyEventDefaultStringLocalizations.m */; }; B14EF24A2397E90400758AF0 /* NSArray+MatrixSDK.m in Sources */ = {isa = PBXBuildFile; fileRef = 321CFDED225264C4004D31DF /* NSArray+MatrixSDK.m */; }; B14EF24B2397E90400758AF0 /* MXServiceTermsRestClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 3294FD9922F321B0007F1E60 /* MXServiceTermsRestClient.m */; }; B14EF24C2397E90400758AF0 /* MXCredentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 323547DB2226FC5700F15F94 /* MXCredentials.m */; }; @@ -919,7 +927,6 @@ B14EF2732397E90400758AF0 /* MXRealmEventScan.m in Sources */ = {isa = PBXBuildFile; fileRef = B146D4ED21A5AF7F00D8C2C6 /* MXRealmEventScan.m */; }; B14EF2742397E90400758AF0 /* MXDeviceListOperationsPool.m in Sources */ = {isa = PBXBuildFile; fileRef = 322691351E5EFF8700966A6E /* MXDeviceListOperationsPool.m */; }; B14EF2752397E90400758AF0 /* MXResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6F9357E1E5B3ACA00FC34BF /* MXResponse.swift */; }; - B14EF2762397E90400758AF0 /* MXRoomNameDefaultStringLocalizations.m in Sources */ = {isa = PBXBuildFile; fileRef = 32BA86AE2152A79E008F277E /* MXRoomNameDefaultStringLocalizations.m */; }; B14EF2772397E90400758AF0 /* MXDecryptionResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 32F9FA7C1DBA0CF0009D98A6 /* MXDecryptionResult.m */; }; B14EF2782397E90400758AF0 /* MXTransactionCancelCode.m in Sources */ = {isa = PBXBuildFile; fileRef = 321CFDF82254E720004D31DF /* MXTransactionCancelCode.m */; }; B14EF2792397E90400758AF0 /* MXEventListener.m in Sources */ = {isa = PBXBuildFile; fileRef = 3220093719EFA4C9008DE41D /* MXEventListener.m */; }; @@ -987,7 +994,6 @@ B14EF2BD2397E90400758AF0 /* MXAggregationPaginatedResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 327E9AE52285A8C400A98BC1 /* MXAggregationPaginatedResponse.h */; settings = {ATTRIBUTES = (Public, ); }; }; B14EF2BE2397E90400758AF0 /* MXEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 323E0C591A306D7A00A31D73 /* MXEvent.h */; settings = {ATTRIBUTES = (Public, ); }; }; B14EF2BF2397E90400758AF0 /* MXRoomThirdPartyInvite.h in Headers */ = {isa = PBXBuildFile; fileRef = 327F8DB01C6112BA00581CA3 /* MXRoomThirdPartyInvite.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B14EF2C02397E90400758AF0 /* MXRoomNameStringsLocalizable.h in Headers */ = {isa = PBXBuildFile; fileRef = 32BA86AB21529AE3008F277E /* MXRoomNameStringsLocalizable.h */; settings = {ATTRIBUTES = (Public, ); }; }; B14EF2C12397E90400758AF0 /* MXKeyBackup.h in Headers */ = {isa = PBXBuildFile; fileRef = 32BBAE722179CF4000D85F46 /* MXKeyBackup.h */; settings = {ATTRIBUTES = (Public, ); }; }; B14EF2C22397E90400758AF0 /* MXCallKitConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 92634B801EF2E3C400DB9F60 /* MXCallKitConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; B14EF2C32397E90400758AF0 /* MXFilterJSONModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 32618E6F20ED2DF500E1D2EA /* MXFilterJSONModel.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -1022,10 +1028,8 @@ B14EF2E22397E90400758AF0 /* MX3PidAddManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 32D2CC0023422462002BD8CA /* MX3PidAddManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; B14EF2E32397E90400758AF0 /* MXDecrypting.h in Headers */ = {isa = PBXBuildFile; fileRef = 3271877C1DA7CB2F0071C818 /* MXDecrypting.h */; settings = {ATTRIBUTES = (Public, ); }; }; B14EF2E42397E90400758AF0 /* MXStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 32114A841A262CE000FF2EC4 /* MXStore.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B14EF2E52397E90400758AF0 /* MXRoomNameDefaultStringLocalizations.h in Headers */ = {isa = PBXBuildFile; fileRef = 32BA86AD2152A79E008F277E /* MXRoomNameDefaultStringLocalizations.h */; }; B14EF2E62397E90400758AF0 /* MXMegolmEncryption.h in Headers */ = {isa = PBXBuildFile; fileRef = 32A151371DAD292400400192 /* MXMegolmEncryption.h */; }; B14EF2E72397E90400758AF0 /* MXLRUCache.h in Headers */ = {isa = PBXBuildFile; fileRef = F03EF5021DF01596009DF592 /* MXLRUCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B14EF2E82397E90400758AF0 /* MXSendReplyEventDefaultStringLocalizations.h in Headers */ = {isa = PBXBuildFile; fileRef = B172857A2100D4F60052C51E /* MXSendReplyEventDefaultStringLocalizations.h */; }; B14EF2E92397E90400758AF0 /* MXTools.h in Headers */ = {isa = PBXBuildFile; fileRef = 329FB1771A0A74B100A5E88E /* MXTools.h */; settings = {ATTRIBUTES = (Public, ); }; }; B14EF2EA2397E90400758AF0 /* MXDeviceListOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 322691301E5EF77D00966A6E /* MXDeviceListOperation.h */; }; B14EF2EB2397E90400758AF0 /* MXRoomAccountData.h in Headers */ = {isa = PBXBuildFile; fileRef = 32481A821C03572900782AD3 /* MXRoomAccountData.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -1048,7 +1052,6 @@ B14EF2FC2397E90400758AF0 /* MXAggregatedReactionsUpdater.h in Headers */ = {isa = PBXBuildFile; fileRef = 32792BD22295A86600F4FC9D /* MXAggregatedReactionsUpdater.h */; }; B14EF2FD2397E90400758AF0 /* MXScanRealmInMemoryProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = B146D4C521A5A44E00D8C2C6 /* MXScanRealmInMemoryProvider.h */; }; B14EF2FE2397E90400758AF0 /* MXReplyEventBodyParts.h in Headers */ = {isa = PBXBuildFile; fileRef = B11BD45222CB583E0064D8B0 /* MXReplyEventBodyParts.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B14EF2FF2397E90400758AF0 /* MXSendReplyEventStringsLocalizable.h in Headers */ = {isa = PBXBuildFile; fileRef = B17285782100C88A0052C51E /* MXSendReplyEventStringsLocalizable.h */; settings = {ATTRIBUTES = (Public, ); }; }; B14EF3002397E90400758AF0 /* MXQueuedEncryption.h in Headers */ = {isa = PBXBuildFile; fileRef = 32A151501DAF8A7200400192 /* MXQueuedEncryption.h */; }; B14EF3012397E90400758AF0 /* MXIncomingRoomKeyRequestManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 32A30B161FB4813400C8309E /* MXIncomingRoomKeyRequestManager.h */; }; B14EF3022397E90400758AF0 /* MXEncryptedAttachments.h in Headers */ = {isa = PBXBuildFile; fileRef = F03EF5061DF071D5009DF592 /* MXEncryptedAttachments.h */; }; @@ -1160,9 +1163,6 @@ B16F35A325F916A00029AE98 /* MXRoomTypeMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B16F35A125F9169F0029AE98 /* MXRoomTypeMapper.swift */; }; B1710B1F2613D01400A9B429 /* MXSpaceChildrenRequestParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1710B1E2613D01400A9B429 /* MXSpaceChildrenRequestParameters.swift */; }; B1710B202613D01400A9B429 /* MXSpaceChildrenRequestParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1710B1E2613D01400A9B429 /* MXSpaceChildrenRequestParameters.swift */; }; - B17285792100C8EA0052C51E /* MXSendReplyEventStringsLocalizable.h in Headers */ = {isa = PBXBuildFile; fileRef = B17285782100C88A0052C51E /* MXSendReplyEventStringsLocalizable.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B172857C2100D4F60052C51E /* MXSendReplyEventDefaultStringLocalizations.h in Headers */ = {isa = PBXBuildFile; fileRef = B172857A2100D4F60052C51E /* MXSendReplyEventDefaultStringLocalizations.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B172857D2100D4F60052C51E /* MXSendReplyEventDefaultStringLocalizations.m in Sources */ = {isa = PBXBuildFile; fileRef = B172857B2100D4F60052C51E /* MXSendReplyEventDefaultStringLocalizations.m */; }; B176B25123EB03E4001879C6 /* MXAggregationPaginatedResponse_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = B176B25023EB03E3001879C6 /* MXAggregationPaginatedResponse_Private.h */; }; B176B25223EB03E4001879C6 /* MXAggregationPaginatedResponse_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = B176B25023EB03E3001879C6 /* MXAggregationPaginatedResponse_Private.h */; }; B17982F52119E4A2001FD722 /* MXRoomCreateContent.h in Headers */ = {isa = PBXBuildFile; fileRef = B17982ED2119E49E001FD722 /* MXRoomCreateContent.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -1585,6 +1585,12 @@ 15D7F292D95EB58AEE801C4E /* libPods-MatrixSDKTests-macOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-MatrixSDKTests-macOS.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 181FD5D22660C791008EC084 /* MXLogObjcWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXLogObjcWrapper.h; sourceTree = ""; }; 181FD5D32660C791008EC084 /* MXLogObjcWrapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MXLogObjcWrapper.m; sourceTree = ""; }; + 1838926F2702F552003F0C4F /* MXRoomNameDefaultStringLocalizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXRoomNameDefaultStringLocalizer.h; sourceTree = ""; }; + 183892712702F553003F0C4F /* MXSendReplyEventDefaultStringLocalizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXSendReplyEventDefaultStringLocalizer.m; sourceTree = ""; }; + 183892732702F553003F0C4F /* MXSendReplyEventDefaultStringLocalizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXSendReplyEventDefaultStringLocalizer.h; sourceTree = ""; }; + 183892742702F553003F0C4F /* MXRoomNameDefaultStringLocalizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXRoomNameDefaultStringLocalizer.m; sourceTree = ""; }; + 1838928427031D1D003F0C4F /* MXRoomNameStringLocalizerProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXRoomNameStringLocalizerProtocol.h; sourceTree = ""; }; + 1838928527031D1D003F0C4F /* MXSendReplyEventStringLocalizerProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXSendReplyEventStringLocalizerProtocol.h; sourceTree = ""; }; 189CC07F265E361500BE1FD8 /* MXLog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXLog.h; sourceTree = ""; }; 189CC080265E361500BE1FD8 /* MXLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXLog.swift; sourceTree = ""; }; 19B6947FC794531CEEDCFA7F /* Pods-MatrixSDKTests-macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MatrixSDKTests-macOS.release.xcconfig"; path = "Target Support Files/Pods-MatrixSDKTests-macOS/Pods-MatrixSDKTests-macOS.release.xcconfig"; sourceTree = ""; }; @@ -1973,9 +1979,6 @@ 32B94E00228EDEBC00716A26 /* MXReactionRelation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MXReactionRelation.m; path = MatrixSDK/Aggregations/Data/MXReactionRelation.m; sourceTree = SOURCE_ROOT; }; 32B94E03228EE90300716A26 /* MXRealmReactionRelation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXRealmReactionRelation.h; sourceTree = ""; }; 32B94E04228EE90300716A26 /* MXRealmReactionRelation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MXRealmReactionRelation.m; sourceTree = ""; }; - 32BA86AB21529AE3008F277E /* MXRoomNameStringsLocalizable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXRoomNameStringsLocalizable.h; sourceTree = ""; }; - 32BA86AD2152A79E008F277E /* MXRoomNameDefaultStringLocalizations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXRoomNameDefaultStringLocalizations.h; sourceTree = ""; }; - 32BA86AE2152A79E008F277E /* MXRoomNameDefaultStringLocalizations.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MXRoomNameDefaultStringLocalizations.m; sourceTree = ""; }; 32BBAE662178E99100D85F46 /* MXKeyBackupData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXKeyBackupData.m; sourceTree = ""; }; 32BBAE672178E99100D85F46 /* MXKeyBackupVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXKeyBackupVersion.h; sourceTree = ""; }; 32BBAE692178E99100D85F46 /* MXKeyBackupVersion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXKeyBackupVersion.m; sourceTree = ""; }; @@ -2181,9 +2184,6 @@ B16C56E1261D0A9D00604765 /* MXSpaceChildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXSpaceChildInfo.swift; sourceTree = ""; }; B16F35A125F9169F0029AE98 /* MXRoomTypeMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXRoomTypeMapper.swift; sourceTree = ""; }; B1710B1E2613D01400A9B429 /* MXSpaceChildrenRequestParameters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXSpaceChildrenRequestParameters.swift; sourceTree = ""; }; - B17285782100C88A0052C51E /* MXSendReplyEventStringsLocalizable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MXSendReplyEventStringsLocalizable.h; path = ../MXSendReplyEventStringsLocalizable.h; sourceTree = ""; }; - B172857A2100D4F60052C51E /* MXSendReplyEventDefaultStringLocalizations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MXSendReplyEventDefaultStringLocalizations.h; path = ../MXSendReplyEventDefaultStringLocalizations.h; sourceTree = ""; }; - B172857B2100D4F60052C51E /* MXSendReplyEventDefaultStringLocalizations.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MXSendReplyEventDefaultStringLocalizations.m; path = ../MXSendReplyEventDefaultStringLocalizations.m; sourceTree = ""; }; B176B25023EB03E3001879C6 /* MXAggregationPaginatedResponse_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXAggregationPaginatedResponse_Private.h; sourceTree = ""; }; B17982ED2119E49E001FD722 /* MXRoomCreateContent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXRoomCreateContent.h; sourceTree = ""; }; B17982EE2119E49F001FD722 /* MXRoomTombStoneContent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXRoomTombStoneContent.m; sourceTree = ""; }; @@ -2506,60 +2506,63 @@ 32720D98222EAA6F0086FFF5 /* AutoDiscovery */, 320BBF3A1D6C7D9D0079890E /* EventsEnumerator */, 323F3F9020D3F0C700D26D6A /* Filters */, - 32114A831A262CE000FF2EC4 /* Store */, B11BD45122CB57BD0064D8B0 /* ReplyEvent */, + 32114A831A262CE000FF2EC4 /* Store */, + 3264DB8F1CEC528D00B99881 /* MXAccountData.h */, + 3264DB901CEC528D00B99881 /* MXAccountData.m */, 323547DA2226FC5700F15F94 /* MXCredentials.h */, 323547DB2226FC5700F15F94 /* MXCredentials.m */, + 3220093619EFA4C9008DE41D /* MXEventListener.h */, + 3220093719EFA4C9008DE41D /* MXEventListener.m */, + 326056831C76FDF1009D44AD /* MXEventTimeline.h */, + 326056841C76FDF1009D44AD /* MXEventTimeline.m */, F0173EAA1FCF0E8800B5F6A3 /* MXGroup.h */, F0173EAB1FCF0E8900B5F6A3 /* MXGroup.m */, - B1C854ED25E7B492005867D0 /* MXRoomType.h */, - B16F35A125F9169F0029AE98 /* MXRoomTypeMapper.swift */, - 320DFDCA19DD99B60068622A /* MXRoom.h */, - 320DFDCB19DD99B60068622A /* MXRoom.m */, - 32C235701F827F3800E38FC5 /* MXRoomOperation.h */, - 32C235711F827F3800E38FC5 /* MXRoomOperation.m */, - 321B413D1E09937E009EEEC7 /* MXRoomSummary.h */, - 321B413E1E09937E009EEEC7 /* MXRoomSummary.m */, - EC2EACFB266625170038B61F /* MXRoomLastMessage.h */, - EC2EACFC266625170038B61F /* MXRoomLastMessage.m */, - 329D3E601E251027002E2F1E /* MXRoomSummaryUpdater.h */, - 329D3E611E251027002E2F1E /* MXRoomSummaryUpdater.m */, + F082946B1DB66C3D00CEAB63 /* MXInvite3PID.h */, + F082946C1DB66C3D00CEAB63 /* MXInvite3PID.m */, + 327137251A24D50A00DB6757 /* MXMyUser.h */, + 327137261A24D50A00DB6757 /* MXMyUser.m */, 32E226A41D06AC9F00E6CA54 /* MXPeekingRoom.h */, 32E226A51D06AC9F00E6CA54 /* MXPeekingRoom.m */, 3293C6FE214BBA4F009B3DDB /* MXPeekingRoomSummary.h */, 3293C6FF214BBA4F009B3DDB /* MXPeekingRoomSummary.m */, - 3265CB361A14C43E00E24B2F /* MXRoomState.h */, - 3265CB371A14C43E00E24B2F /* MXRoomState.m */, - 32618E7920EFA45B00E1D2EA /* MXRoomMembers.h */, - 32618E7A20EFA45B00E1D2EA /* MXRoomMembers.m */, - 32B76EA220FDE2BE00B095F6 /* MXRoomMembersCount.h */, - 32B76EA420FDE85100B095F6 /* MXRoomMembersCount.m */, + 320DFDCA19DD99B60068622A /* MXRoom.h */, + 320DFDCB19DD99B60068622A /* MXRoom.m */, 32481A821C03572900782AD3 /* MXRoomAccountData.h */, 32481A831C03572900782AD3 /* MXRoomAccountData.m */, - EC054972260123BE0047ECD7 /* MXRoomAccountDataUpdating.h */, EC05478025FF99450047ECD7 /* MXRoomAccountDataUpdater.h */, EC05478125FF99450047ECD7 /* MXRoomAccountDataUpdater.m */, - 3220093619EFA4C9008DE41D /* MXEventListener.h */, - 3220093719EFA4C9008DE41D /* MXEventListener.m */, - 326056831C76FDF1009D44AD /* MXEventTimeline.h */, - 326056841C76FDF1009D44AD /* MXEventTimeline.m */, - F082946B1DB66C3D00CEAB63 /* MXInvite3PID.h */, - F082946C1DB66C3D00CEAB63 /* MXInvite3PID.m */, - 3220094319EFBF30008DE41D /* MXSessionEventListener.h */, - 3220094419EFBF30008DE41D /* MXSessionEventListener.m */, + EC054972260123BE0047ECD7 /* MXRoomAccountDataUpdating.h */, + EC2EACFB266625170038B61F /* MXRoomLastMessage.h */, + EC2EACFC266625170038B61F /* MXRoomLastMessage.m */, 329FB1731A0A3A1600A5E88E /* MXRoomMember.h */, 329FB1741A0A3A1600A5E88E /* MXRoomMember.m */, + 32618E7920EFA45B00E1D2EA /* MXRoomMembers.h */, + 32618E7A20EFA45B00E1D2EA /* MXRoomMembers.m */, + 32B76EA220FDE2BE00B095F6 /* MXRoomMembersCount.h */, + 32B76EA420FDE85100B095F6 /* MXRoomMembersCount.m */, + 1838926F2702F552003F0C4F /* MXRoomNameDefaultStringLocalizer.h */, + 183892742702F553003F0C4F /* MXRoomNameDefaultStringLocalizer.m */, + 1838928427031D1D003F0C4F /* MXRoomNameStringLocalizerProtocol.h */, + 32C235701F827F3800E38FC5 /* MXRoomOperation.h */, + 32C235711F827F3800E38FC5 /* MXRoomOperation.m */, + 3265CB361A14C43E00E24B2F /* MXRoomState.h */, + 3265CB371A14C43E00E24B2F /* MXRoomState.m */, + 321B413D1E09937E009EEEC7 /* MXRoomSummary.h */, + 321B413E1E09937E009EEEC7 /* MXRoomSummary.m */, + 329D3E601E251027002E2F1E /* MXRoomSummaryUpdater.h */, + 329D3E611E251027002E2F1E /* MXRoomSummaryUpdater.m */, 327F8DB01C6112BA00581CA3 /* MXRoomThirdPartyInvite.h */, 327F8DB11C6112BA00581CA3 /* MXRoomThirdPartyInvite.m */, - 3264DB8F1CEC528D00B99881 /* MXAccountData.h */, - 3264DB901CEC528D00B99881 /* MXAccountData.m */, + B1C854ED25E7B492005867D0 /* MXRoomType.h */, + B16F35A125F9169F0029AE98 /* MXRoomTypeMapper.swift */, + 183892732702F553003F0C4F /* MXSendReplyEventDefaultStringLocalizer.h */, + 183892712702F553003F0C4F /* MXSendReplyEventDefaultStringLocalizer.m */, + 1838928527031D1D003F0C4F /* MXSendReplyEventStringLocalizerProtocol.h */, + 3220094319EFBF30008DE41D /* MXSessionEventListener.h */, + 3220094419EFBF30008DE41D /* MXSessionEventListener.m */, 329FB17D1A0B665800A5E88E /* MXUser.h */, 329FB17E1A0B665800A5E88E /* MXUser.m */, - 327137251A24D50A00DB6757 /* MXMyUser.h */, - 327137261A24D50A00DB6757 /* MXMyUser.m */, - 32BA86AB21529AE3008F277E /* MXRoomNameStringsLocalizable.h */, - 32BA86AD2152A79E008F277E /* MXRoomNameDefaultStringLocalizations.h */, - 32BA86AE2152A79E008F277E /* MXRoomNameDefaultStringLocalizations.m */, ); path = Data; sourceTree = ""; @@ -3724,9 +3727,6 @@ isa = PBXGroup; children = ( B142317522CCA2D300FFA96A /* Parser */, - B17285782100C88A0052C51E /* MXSendReplyEventStringsLocalizable.h */, - B172857A2100D4F60052C51E /* MXSendReplyEventDefaultStringLocalizations.h */, - B172857B2100D4F60052C51E /* MXSendReplyEventDefaultStringLocalizations.m */, ); path = ReplyEvent; sourceTree = ""; @@ -4219,7 +4219,6 @@ 323F8773255460B5009E9E67 /* MXProfiler.h in Headers */, 327A5F4B239805F600ED6329 /* MXKeyVerificationCancel.h in Headers */, 327F8DB21C6112BA00581CA3 /* MXRoomThirdPartyInvite.h in Headers */, - 32BA86AC21529E29008F277E /* MXRoomNameStringsLocalizable.h in Headers */, B19A309E240424BD00FB6F35 /* MXQRCodeTransaction_Private.h in Headers */, 32BBAE742179CF4000D85F46 /* MXKeyBackup.h in Headers */, 181FD5D42660C791008EC084 /* MXLogObjcWrapper.h in Headers */, @@ -4274,13 +4273,11 @@ 32114A851A262CE000FF2EC4 /* MXStore.h in Headers */, EC60ED67265CFC7200B39A4E /* MXPresenceSyncResponse.h in Headers */, 3AC13802264482A100EE1E74 /* MXExportedOlmDevice.h in Headers */, - 32BA86AF2152A79E008F277E /* MXRoomNameDefaultStringLocalizations.h in Headers */, 32A151391DAD292400400192 /* MXMegolmEncryption.h in Headers */, EC8A538B25B1BC77004E0802 /* MXCallCandidate.h in Headers */, F03EF5041DF01596009DF592 /* MXLRUCache.h in Headers */, EC8A539D25B1BC77004E0802 /* MXCallCandidatesEventContent.h in Headers */, EC60EDC6265CFEA800B39A4E /* MXRoomSyncUnreadNotifications.h in Headers */, - B172857C2100D4F60052C51E /* MXSendReplyEventDefaultStringLocalizations.h in Headers */, 329FB1791A0A74B100A5E88E /* MXTools.h in Headers */, 3AC135D92640335100EE1E74 /* MXDehydrationService.h in Headers */, 322691321E5EF77D00966A6E /* MXDeviceListOperation.h in Headers */, @@ -4296,6 +4293,7 @@ EC60EDDA265CFF0600B39A4E /* MXInvitedRoomSync.h in Headers */, B146D47F21A59E2400D8C2C6 /* MXEventScan.h in Headers */, B146D4E121A5AEF200D8C2C6 /* MXRealmMediaScanMapper.h in Headers */, + 1838927E2702F553003F0C4F /* MXSendReplyEventDefaultStringLocalizer.h in Headers */, 32C78B6C256CFC4D008130B1 /* MXCryptoMigration.h in Headers */, F08B8D5C1E014711006171A8 /* NSData+MatrixSDK.h in Headers */, C60165381E3AA57900B92CFA /* MXSDKOptions.h in Headers */, @@ -4313,6 +4311,7 @@ EC05478225FF99450047ECD7 /* MXRoomAccountDataUpdater.h in Headers */, 8EC511042568216B00EC4E5B /* MXTaggedEventInfo.h in Headers */, ECBF657E26DE2A4900AA3A99 /* MXMemoryRoomOutgoingMessagesStore.h in Headers */, + 183892762702F553003F0C4F /* MXRoomNameDefaultStringLocalizer.h in Headers */, B19A30D424042F2700FB6F35 /* MXSelfVerifyingMasterKeyNotTrustedQRCodeData.h in Headers */, 323F3F9420D3F0C700D26D6A /* MXRoomEventFilter.h in Headers */, 32A9E8251EF4026E0081358A /* MXUIKitBackgroundModeHandler.h in Headers */, @@ -4330,7 +4329,6 @@ B1C854EE25E7B497005867D0 /* MXRoomType.h in Headers */, B11BD45422CB583E0064D8B0 /* MXReplyEventBodyParts.h in Headers */, 32549AF923F2E2790002576B /* MXKeyVerificationReady.h in Headers */, - B17285792100C8EA0052C51E /* MXSendReplyEventStringsLocalizable.h in Headers */, 32A151521DAF8A7200400192 /* MXQueuedEncryption.h in Headers */, 32A30B181FB4813400C8309E /* MXIncomingRoomKeyRequestManager.h in Headers */, F03EF5081DF071D5009DF592 /* MXEncryptedAttachments.h in Headers */, @@ -4427,6 +4425,7 @@ 32133019228B010C0070BA9B /* MXRealmReactionCount.h in Headers */, 3275FD9821A6B53300B9C13D /* MXLoginPolicyData.h in Headers */, F082946D1DB66C3D00CEAB63 /* MXInvite3PID.h in Headers */, + 1838928627031D1D003F0C4F /* MXRoomNameStringLocalizerProtocol.h in Headers */, EC60ED5D265CFC2C00B39A4E /* MXSyncResponse.h in Headers */, 32AF929724115D8B0008A0FD /* MXPendingSecretShareRequest.h in Headers */, 3233606F1A403A0D0071A488 /* MXFileStore.h in Headers */, @@ -4440,6 +4439,7 @@ 3A59A49D25A7A16F00DDA1FC /* MXOlmOutboundGroupSession.h in Headers */, 32AF927F240EA0190008A0FD /* MXSecretShareManager.h in Headers */, 321CFDEE225264C4004D31DF /* NSArray+MatrixSDK.h in Headers */, + 1838928827031D1D003F0C4F /* MXSendReplyEventStringLocalizerProtocol.h in Headers */, B11BD44822CB56790064D8B0 /* MXReplyEventParser.h in Headers */, 321CFDEA22525DEE004D31DF /* MXIncomingSASTransaction.h in Headers */, 32F945F61FAB83D900622468 /* MXIncomingRoomKeyRequest.h in Headers */, @@ -4560,6 +4560,7 @@ B14EF2B82397E90400758AF0 /* MXReactionCount.h in Headers */, B14EF2B92397E90400758AF0 /* MXMediaScanStore.h in Headers */, EC8A53AA25B1BC77004E0802 /* MXCallRejectEventContent.h in Headers */, + 183892772702F553003F0C4F /* MXRoomNameDefaultStringLocalizer.h in Headers */, B14EF2BB2397E90400758AF0 /* MXUsersDevicesMap.h in Headers */, EC8A53C425B1BC77004E0802 /* MXCallInviteEventContent.h in Headers */, B14EF2BC2397E90400758AF0 /* MXAggregatedReactions.h in Headers */, @@ -4570,17 +4571,18 @@ B14EF2BF2397E90400758AF0 /* MXRoomThirdPartyInvite.h in Headers */, ECBF657F26DE2A4900AA3A99 /* MXMemoryRoomOutgoingMessagesStore.h in Headers */, EC8A538C25B1BC77004E0802 /* MXCallCandidate.h in Headers */, - B14EF2C02397E90400758AF0 /* MXRoomNameStringsLocalizable.h in Headers */, B14EF2C12397E90400758AF0 /* MXKeyBackup.h in Headers */, B14EF2C22397E90400758AF0 /* MXCallKitConfiguration.h in Headers */, B19A30BD2404268600FB6F35 /* MXQRCodeDataCoder.h in Headers */, B14EF2C32397E90400758AF0 /* MXFilterJSONModel.h in Headers */, 32CEEF5023B0AB030039BA98 /* MXCrossSigning.h in Headers */, + 1838927F2702F553003F0C4F /* MXSendReplyEventDefaultStringLocalizer.h in Headers */, B19A30CB2404268600FB6F35 /* MXQRCodeDataCodable.h in Headers */, 320B393B239FD15E00BE2C06 /* MXKeyVerificationRequest.h in Headers */, B14EF2C42397E90400758AF0 /* MXRealmHelper.h in Headers */, B14EF2C62397E90400758AF0 /* MXReactionRelation.h in Headers */, B14EF2C72397E90400758AF0 /* MXMediaManager.h in Headers */, + 1838928927031D1D003F0C4F /* MXSendReplyEventStringLocalizerProtocol.h in Headers */, EC60EDDB265CFF0600B39A4E /* MXInvitedRoomSync.h in Headers */, B14EF2C82397E90400758AF0 /* MXCallManager.h in Headers */, B14EF2C92397E90400758AF0 /* MXRealmReactionRelation.h in Headers */, @@ -4622,14 +4624,12 @@ B14EF2E22397E90400758AF0 /* MX3PidAddManager.h in Headers */, B19A309D240424BD00FB6F35 /* MXQRCodeTransaction.h in Headers */, B14EF2E42397E90400758AF0 /* MXStore.h in Headers */, - B14EF2E52397E90400758AF0 /* MXRoomNameDefaultStringLocalizations.h in Headers */, 32AF928B240EA3880008A0FD /* MXSecretShareSend.h in Headers */, B14EF2E62397E90400758AF0 /* MXMegolmEncryption.h in Headers */, EC8A53E125B1BCC6004E0802 /* MXThirdPartyProtocolInstance.h in Headers */, B14EF2E72397E90400758AF0 /* MXLRUCache.h in Headers */, B105CDD7261F54C8006EB204 /* MXSpaceChildContent.h in Headers */, 32AF929824115D8B0008A0FD /* MXPendingSecretShareRequest.h in Headers */, - B14EF2E82397E90400758AF0 /* MXSendReplyEventDefaultStringLocalizations.h in Headers */, B14EF2E92397E90400758AF0 /* MXTools.h in Headers */, B14EF2EA2397E90400758AF0 /* MXDeviceListOperation.h in Headers */, ECD623FF25D3DCC900DC0A0B /* MXOlmDecryption.h in Headers */, @@ -4663,7 +4663,7 @@ B14EF2FD2397E90400758AF0 /* MXScanRealmInMemoryProvider.h in Headers */, B14EF2FE2397E90400758AF0 /* MXReplyEventBodyParts.h in Headers */, 32C78B69256CFC4D008130B1 /* MXCryptoVersion.h in Headers */, - B14EF2FF2397E90400758AF0 /* MXSendReplyEventStringsLocalizable.h in Headers */, + 1838928727031D1D003F0C4F /* MXRoomNameStringLocalizerProtocol.h in Headers */, EC8A53BC25B1BC77004E0802 /* MXCallSelectAnswerEventContent.h in Headers */, B1A026F726161EF5001AADFF /* MXSpaceChildSummaryResponse.h in Headers */, B14EF3002397E90400758AF0 /* MXQueuedEncryption.h in Headers */, @@ -5247,6 +5247,7 @@ C6F9358A1E5B3BE600FC34BF /* MXEvent.swift in Sources */, B146D48021A59E2400D8C2C6 /* MXEventScan.m in Sources */, 329E808D224E2E1B00A48C3A /* MXOutgoingSASTransaction.m in Sources */, + 1838927A2702F553003F0C4F /* MXSendReplyEventDefaultStringLocalizer.m in Sources */, 32581DEA23C8C0C900832EAA /* MXUserTrustLevel.m in Sources */, 3271878A1DA7DCE50071C818 /* MXOlmEncryption.m in Sources */, 327187861DA7D0220071C818 /* MXOlmDecryption.m in Sources */, @@ -5315,7 +5316,6 @@ 3274538623FD69D600438328 /* MXKeyVerificationRequestByToDeviceJSONModel.m in Sources */, B1A026F826161EF5001AADFF /* MXSpaceChildSummaryResponse.m in Sources */, 324DD2C7246E638B00377005 /* MXAesHmacSha2.m in Sources */, - B172857D2100D4F60052C51E /* MXSendReplyEventDefaultStringLocalizations.m in Sources */, 321CFDEF225264C4004D31DF /* NSArray+MatrixSDK.m in Sources */, 327A5F52239805F600ED6329 /* MXKeyVerificationStart.m in Sources */, 3294FD9D22F321B0007F1E60 /* MXServiceTermsRestClient.m in Sources */, @@ -5389,7 +5389,6 @@ 32EEA8632604014A0041425B /* MXSummable.swift in Sources */, 3A108AB725812995005EEBE9 /* MXKeyProvider.m in Sources */, 322AB586260CD5690017E964 /* MXCachedSyncResponse.m in Sources */, - 32BA86B02152A79E008F277E /* MXRoomNameDefaultStringLocalizations.m in Sources */, B19A30D624042F2700FB6F35 /* MXSelfVerifyingMasterKeyNotTrustedQRCodeData.m in Sources */, 32F9FA7E1DBA0CF0009D98A6 /* MXDecryptionResult.m in Sources */, 321CFDF92254E721004D31DF /* MXTransactionCancelCode.m in Sources */, @@ -5430,6 +5429,7 @@ 325AD44123BE3E7500FF5277 /* MXCrossSigningInfo.m in Sources */, 329E8089224E261600A48C3A /* MXKeyVerificationTransaction.m in Sources */, C6F935891E5B3BE600FC34BF /* MXEventTimeline.swift in Sources */, + 183892802702F553003F0C4F /* MXRoomNameDefaultStringLocalizer.m in Sources */, C6F9358B1E5B3BE600FC34BF /* MXJSONModels.swift in Sources */, EC8A539725B1BC77004E0802 /* MXCallReplacesEventContent.m in Sources */, 32FA10C21FA1C9EE00E54233 /* MXOutgoingRoomKeyRequestManager.m in Sources */, @@ -5684,6 +5684,7 @@ B14EF22B2397E90400758AF0 /* MXFileStoreMetaData.m in Sources */, EC8A53A825B1BC77004E0802 /* MXCallCapabilitiesModel.m in Sources */, B14EF22C2397E90400758AF0 /* MXAccountData.m in Sources */, + 1838927B2702F553003F0C4F /* MXSendReplyEventDefaultStringLocalizer.m in Sources */, EC8A539825B1BC77004E0802 /* MXCallReplacesEventContent.m in Sources */, B18B0E6825FBDC3000E32151 /* MXSpace.swift in Sources */, B14EF22D2397E90400758AF0 /* MXRealmReactionCount.m in Sources */, @@ -5730,7 +5731,6 @@ 32CEEF4623AD2A6C0039BA98 /* MXCrossSigningKey.m in Sources */, B14EF2482397E90400758AF0 /* MXEncryptedAttachments.m in Sources */, EC05478525FF99450047ECD7 /* MXRoomAccountDataUpdater.m in Sources */, - B14EF2492397E90400758AF0 /* MXSendReplyEventDefaultStringLocalizations.m in Sources */, B14EF24A2397E90400758AF0 /* NSArray+MatrixSDK.m in Sources */, B19A30A92404257700FB6F35 /* MXSASKeyVerificationStart.m in Sources */, 324DD2B9246C21C700377005 /* MXSecretStorageKeyCreationInfo.m in Sources */, @@ -5812,7 +5812,6 @@ B14EF2742397E90400758AF0 /* MXDeviceListOperationsPool.m in Sources */, B18B0E4B25FB783B00E32151 /* MXSpaceCreationParameters.swift in Sources */, B14EF2752397E90400758AF0 /* MXResponse.swift in Sources */, - B14EF2762397E90400758AF0 /* MXRoomNameDefaultStringLocalizations.m in Sources */, B14EF2772397E90400758AF0 /* MXDecryptionResult.m in Sources */, B14EF2782397E90400758AF0 /* MXTransactionCancelCode.m in Sources */, B14EF2792397E90400758AF0 /* MXEventListener.m in Sources */, @@ -5867,6 +5866,7 @@ B14EF2902397E90400758AF0 /* MXJSONModels.swift in Sources */, 325AF3E424897D9400EF937D /* MXSecretRecoveryResult.m in Sources */, EC8A53A225B1BC77004E0802 /* MXCallSelectAnswerEventContent.m in Sources */, + 183892812702F553003F0C4F /* MXRoomNameDefaultStringLocalizer.m in Sources */, B14EF2912397E90400758AF0 /* MXOutgoingRoomKeyRequestManager.m in Sources */, B14EF2922397E90400758AF0 /* MXWellKnown.m in Sources */, B1A026F926161EF5001AADFF /* MXSpaceChildSummaryResponse.m in Sources */, diff --git a/MatrixSDK/Contrib/Swift/Data/MXRoom.swift b/MatrixSDK/Contrib/Swift/Data/MXRoom.swift index 5a84830084..4bff7cfd64 100644 --- a/MatrixSDK/Contrib/Swift/Data/MXRoom.swift +++ b/MatrixSDK/Contrib/Swift/Data/MXRoom.swift @@ -718,7 +718,7 @@ public extension MXRoom { - eventToReply: The event to reply. - textMessage: The text to send. - formattedTextMessage: The optional HTML formatted string of the text to send. - - stringLocalizations: String localizations used when building reply message. + - stringLocalizer: String localizations used when building reply message. - localEcho: a pointer to an MXEvent object. When the event type is `MXEventType.roomMessage`, this pointer is set to an actual @@ -738,8 +738,8 @@ public extension MXRoom { - returns: a `MXHTTPOperation` instance. */ - @nonobjc @discardableResult func sendReply(to eventToReply: MXEvent, textMessage: String, formattedTextMessage: String?, stringLocalizations: MXSendReplyEventStringsLocalizable?, localEcho: inout MXEvent?, completion: @escaping (_ response: MXResponse) -> Void) -> MXHTTPOperation { - return __sendReply(to: eventToReply, withTextMessage: textMessage, formattedTextMessage: formattedTextMessage, stringLocalizations: stringLocalizations, localEcho: &localEcho, success: currySuccess(completion), failure: curryFailure(completion)) + @nonobjc @discardableResult func sendReply(to eventToReply: MXEvent, textMessage: String, formattedTextMessage: String?, stringLocalizer: MXSendReplyEventStringLocalizerProtocol?, localEcho: inout MXEvent?, completion: @escaping (_ response: MXResponse) -> Void) -> MXHTTPOperation { + return __sendReply(to: eventToReply, withTextMessage: textMessage, formattedTextMessage: formattedTextMessage, stringLocalizer: stringLocalizer, localEcho: &localEcho, success: currySuccess(completion), failure: curryFailure(completion)) } diff --git a/MatrixSDK/Data/MXRoom.h b/MatrixSDK/Data/MXRoom.h index c590411f3c..eb5c72a292 100644 --- a/MatrixSDK/Data/MXRoom.h +++ b/MatrixSDK/Data/MXRoom.h @@ -39,7 +39,7 @@ #import "MXEventTimeline.h" #import "MXEventsEnumerator.h" #import "MXCryptoConstants.h" -#import "MXSendReplyEventStringsLocalizable.h" +#import "MXSendReplyEventStringLocalizerProtocol.h" @class MXRoom; @class MXSession; @@ -915,7 +915,7 @@ FOUNDATION_EXPORT NSInteger const kMXRoomAlreadyJoinedErrorCode; @param eventToReply The event to reply. @param textMessage the text to send. @param formattedTextMessage the optional HTML formatted string of the text to send. - @param stringLocalizations string localizations used when building reply message. + @param stringLocalizer string localizations used when building reply message. @param localEcho a pointer to a MXEvent object (@see sendMessageWithContent: for details). @param success A block object called when the operation succeeds. It returns the event id of the event generated on the home server @@ -926,7 +926,7 @@ FOUNDATION_EXPORT NSInteger const kMXRoomAlreadyJoinedErrorCode; - (MXHTTPOperation*)sendReplyToEvent:(MXEvent*)eventToReply withTextMessage:(NSString*)textMessage formattedTextMessage:(NSString*)formattedTextMessage - stringLocalizations:(id)stringLocalizations + stringLocalizer:(id)stringLocalizer localEcho:(MXEvent**)localEcho success:(void (^)(NSString *eventId))success failure:(void (^)(NSError *error))failure NS_REFINED_FOR_SWIFT; diff --git a/MatrixSDK/Data/MXRoom.m b/MatrixSDK/Data/MXRoom.m index 0dd5b31cba..73b8fe5a9e 100644 --- a/MatrixSDK/Data/MXRoom.m +++ b/MatrixSDK/Data/MXRoom.m @@ -29,7 +29,7 @@ #import "MXMediaManager.h" #import "MXRoomOperation.h" -#import "MXSendReplyEventDefaultStringLocalizations.h" +#import "MXSendReplyEventDefaultStringLocalizer.h" #import "MXError.h" @@ -1899,7 +1899,7 @@ - (MXHTTPOperation*)setRelatedGroups:(NSArray*)relatedGroups - (MXHTTPOperation*)sendReplyToEvent:(MXEvent*)eventToReply withTextMessage:(NSString*)textMessage formattedTextMessage:(NSString*)formattedTextMessage - stringLocalizations:(id)stringLocalizations + stringLocalizer:(id)stringLocalizer localEcho:(MXEvent**)localEcho success:(void (^)(NSString *eventId))success failure:(void (^)(NSError *error))failure @@ -1910,15 +1910,15 @@ - (MXHTTPOperation*)sendReplyToEvent:(MXEvent*)eventToReply return nil; } - id finalStringLocalizations; + id finalStringLocalizer; - if (stringLocalizations) + if (stringLocalizer) { - finalStringLocalizations = stringLocalizations; + finalStringLocalizer = stringLocalizer; } else { - finalStringLocalizations = [MXSendReplyEventDefaultStringLocalizations new]; + finalStringLocalizer = [MXSendReplyEventDefaultStringLocalizer new]; } MXHTTPOperation* operation = nil; @@ -1931,7 +1931,7 @@ - (MXHTTPOperation*)sendReplyToEvent:(MXEvent*)eventToReply formattedTextMessage:formattedTextMessage replyContentBody:&replyToBody replyContentFormattedBody:&replyToFormattedBody - stringLocalizations:finalStringLocalizations]; + stringLocalizer:finalStringLocalizer]; if (replyToBody && replyToFormattedBody) { @@ -1972,7 +1972,7 @@ - (MXHTTPOperation*)sendReplyToEvent:(MXEvent*)eventToReply @param formattedTextMessage the optional HTML formatted string of the text to send. @param replyContentBody reply string of the text to send. @param replyContentFormattedBody reply HTML formatted string of the text to send. - @param stringLocalizations string localizations used when building reply content bodies. + @param stringLocalizer string localizations used when building reply content bodies. */ - (void)getReplyContentBodiesWithEventToReply:(MXEvent*)eventToReply @@ -1980,7 +1980,7 @@ - (void)getReplyContentBodiesWithEventToReply:(MXEvent*)eventToReply formattedTextMessage:(NSString*)formattedTextMessage replyContentBody:(NSString**)replyContentBody replyContentFormattedBody:(NSString**)replyContentFormattedBody - stringLocalizations:(id)stringLocalizations + stringLocalizer:(id)stringLocalizer { NSString *msgtype; MXJSONModelSetString(msgtype, eventToReply.content[@"msgtype"]); @@ -2014,27 +2014,27 @@ - (void)getReplyContentBodiesWithEventToReply:(MXEvent*)eventToReply } else if ([msgtype isEqualToString:kMXMessageTypeImage]) { - senderMessageBody = stringLocalizations.senderSentAnImage; + senderMessageBody = stringLocalizer.senderSentAnImage; senderMessageFormattedBody = senderMessageBody; } else if ([msgtype isEqualToString:kMXMessageTypeVideo]) { - senderMessageBody = stringLocalizations.senderSentAVideo; + senderMessageBody = stringLocalizer.senderSentAVideo; senderMessageFormattedBody = senderMessageBody; } else if (eventToReply.isVoiceMessage) { - senderMessageBody = stringLocalizations.senderSentAVoiceMessage; + senderMessageBody = stringLocalizer.senderSentAVoiceMessage; senderMessageFormattedBody = senderMessageBody; } else if ([msgtype isEqualToString:kMXMessageTypeAudio]) { - senderMessageBody = stringLocalizations.senderSentAnAudioFile; + senderMessageBody = stringLocalizer.senderSentAnAudioFile; senderMessageFormattedBody = senderMessageBody; } else if ([msgtype isEqualToString:kMXMessageTypeFile]) { - senderMessageBody = stringLocalizations.senderSentAFile; + senderMessageBody = stringLocalizer.senderSentAFile; senderMessageFormattedBody = senderMessageBody; } else @@ -2058,7 +2058,7 @@ - (void)getReplyContentBodiesWithEventToReply:(MXEvent*)eventToReply senderMessageFormattedBody:senderMessageFormattedBody isSenderMessageAnEmote:isSenderMessageAnEmote replyFormattedMessage:finalFormattedTextMessage - stringLocalizations:stringLocalizations]; + stringLocalizer:stringLocalizer]; } } @@ -2148,7 +2148,7 @@ - (NSString*)replyMessageBodyFromSender:(NSString*)sender @param senderMessageFormattedBody The message body of the sender. @param isSenderMessageAnEmote Indicate if the sender message is an emote (/me). @param replyFormattedMessage The response for the sender message. HTML formatted string if any otherwise non formatted string as reply formatted body is mandatory. - @param stringLocalizations string localizations used when building formatted body. + @param stringLocalizer string localizations used when building formatted body. @return reply message body. */ @@ -2156,7 +2156,7 @@ - (NSString*)replyMessageFormattedBodyFromEventToReply:(MXEvent*)eventToReply senderMessageFormattedBody:(NSString*)senderMessageFormattedBody isSenderMessageAnEmote:(BOOL)isSenderMessageAnEmote replyFormattedMessage:(NSString*)replyFormattedMessage - stringLocalizations:(id)stringLocalizations + stringLocalizer:(id)stringLocalizer { NSString *eventId = eventToReply.eventId; NSString *roomId = eventToReply.roomId; @@ -2202,7 +2202,7 @@ - (NSString*)replyMessageFormattedBodyFromEventToReply:(MXEvent*)eventToReply [replyMessageFormattedBody appendString:@"
"]; // Add event link - [replyMessageFormattedBody appendFormat:@"%@ ", eventPermalink, stringLocalizations.messageToReplyToPrefix]; + [replyMessageFormattedBody appendFormat:@"%@ ", eventPermalink, stringLocalizer.messageToReplyToPrefix]; if (isSenderMessageAnEmote) { diff --git a/MatrixSDK/Data/MXRoomNameDefaultStringLocalizations.m b/MatrixSDK/Data/MXRoomNameDefaultStringLocalizations.m deleted file mode 100644 index 4b1cdbc6c7..0000000000 --- a/MatrixSDK/Data/MXRoomNameDefaultStringLocalizations.m +++ /dev/null @@ -1,43 +0,0 @@ -/* - Copyright 2018 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 "MXRoomNameDefaultStringLocalizations.h" - -@interface MXRoomNameDefaultStringLocalizations () - -@property (nonatomic, copy) NSString *emptyRoom; -@property (nonatomic, copy) NSString *twoMembers; -@property (nonatomic, copy) NSString *moreThanTwoMembers; -@property (nonatomic, copy) NSString *allOtherParticipantsLeft; - -@end - -@implementation MXRoomNameDefaultStringLocalizations - -- (instancetype)init -{ - if (self == [super init]) - { - _emptyRoom = @"Empty room"; - _twoMembers = @"%@ and %@"; - _moreThanTwoMembers = @"%@ & %@ others"; - _allOtherParticipantsLeft = @"%@ (Left)"; - - } - return self; -} - -@end diff --git a/MatrixSDK/Data/MXRoomNameDefaultStringLocalizations.h b/MatrixSDK/Data/MXRoomNameDefaultStringLocalizer.h similarity index 69% rename from MatrixSDK/Data/MXRoomNameDefaultStringLocalizations.h rename to MatrixSDK/Data/MXRoomNameDefaultStringLocalizer.h index ada1feecd7..517b6976a1 100644 --- a/MatrixSDK/Data/MXRoomNameDefaultStringLocalizations.h +++ b/MatrixSDK/Data/MXRoomNameDefaultStringLocalizer.h @@ -16,12 +16,12 @@ @import Foundation; -#import "MXRoomNameStringsLocalizable.h" +#import "MXRoomNameStringLocalizerProtocol.h" /** - The `MXRoomNameDefaultStringLocalizations` implements default English localization - strings for `MXRoomNameStringsLocalizable`. + The `MXRoomNameDefaultStringLocalizer` implements default English localization + strings for `MXRoomNameStringLocalizerProtocol`. */ -@interface MXRoomNameDefaultStringLocalizations : NSObject +@interface MXRoomNameDefaultStringLocalizer : NSObject @end diff --git a/MatrixSDK/Data/MXRoomNameDefaultStringLocalizer.m b/MatrixSDK/Data/MXRoomNameDefaultStringLocalizer.m new file mode 100644 index 0000000000..40dc246d6c --- /dev/null +++ b/MatrixSDK/Data/MXRoomNameDefaultStringLocalizer.m @@ -0,0 +1,41 @@ +/* + Copyright 2018 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 "MXRoomNameDefaultStringLocalizer.h" + +@implementation MXRoomNameDefaultStringLocalizer + +- (NSString *)emptyRoom +{ + return @"Empty room"; +} + +- (NSString *)twoMembers:(NSString *)firstMember second:(NSString *)secondMember +{ + return [NSString stringWithFormat:@"%@ and %@", firstMember, secondMember]; +} + +- (NSString *)moreThanTwoMembers:(NSString *)firstMember count:(NSNumber *)memberCount +{ + return [NSString stringWithFormat:@"%@ & %@ others", firstMember, memberCount]; +} + +- (NSString *)allOtherMembersLeft:(NSString *)member +{ + return [NSString stringWithFormat:@"%@ (Left)", member]; +} + +@end diff --git a/MatrixSDK/Data/MXRoomNameStringsLocalizable.h b/MatrixSDK/Data/MXRoomNameStringLocalizerProtocol.h similarity index 64% rename from MatrixSDK/Data/MXRoomNameStringsLocalizable.h rename to MatrixSDK/Data/MXRoomNameStringLocalizerProtocol.h index 5826ae2996..f5a58dda6d 100644 --- a/MatrixSDK/Data/MXRoomNameStringsLocalizable.h +++ b/MatrixSDK/Data/MXRoomNameStringLocalizerProtocol.h @@ -16,18 +16,24 @@ @import Foundation; +NS_ASSUME_NONNULL_BEGIN + /** - The `MXRoomNameStringsLocalizable` protocol defines an interface that must be implemented + The `MXRoomNameStringLocalizerProtocol` protocol defines an interface that must be implemented to provide string localizations for computing room name according to Matrix room summaries (https://github.com/matrix-org/matrix-doc/issues/688). This interface is used by `MXRoomSummaryUpdater`. */ -@protocol MXRoomNameStringsLocalizable +@protocol MXRoomNameStringLocalizerProtocol + +- (NSString *)emptyRoom; + +- (NSString *)twoMembers:(NSString *)firstMember second:(NSString *)secondMember; + +- (NSString *)moreThanTwoMembers:(NSString *)firstMember count:(NSNumber *)memberCount; -@property (copy, readonly, nonnull) NSString *emptyRoom; -@property (copy, readonly, nonnull) NSString *twoMembers; -@property (copy, readonly, nonnull) NSString *moreThanTwoMembers; -@property (copy, readonly, nonnull) NSString *allOtherParticipantsLeft; +- (NSString *)allOtherMembersLeft:(NSString *)member; @end +NS_ASSUME_NONNULL_END diff --git a/MatrixSDK/Data/MXRoomSummaryUpdater.h b/MatrixSDK/Data/MXRoomSummaryUpdater.h index 997764cda4..54ee1f3fde 100644 --- a/MatrixSDK/Data/MXRoomSummaryUpdater.h +++ b/MatrixSDK/Data/MXRoomSummaryUpdater.h @@ -18,7 +18,7 @@ #import #import "MXRoomSummary.h" -#import "MXRoomNameStringsLocalizable.h" +#import "MXRoomNameStringLocalizerProtocol.h" /** `MXRoomSummaryUpdater` is the default implementation for the `MXRoomSummaryUpdating` protocol. @@ -62,9 +62,9 @@ /** String localizations used when computing names for room with no name. - Default is an instance of `MXRoomNameDefaultStringLocalizations`. + Default is an instance of `MXRoomNameDefaultStringLocalizer`. */ -@property id roomNameStringLocalizations; +@property id roomNameStringLocalizer; /** Indicate YES to handle room types with nil or empty value. diff --git a/MatrixSDK/Data/MXRoomSummaryUpdater.m b/MatrixSDK/Data/MXRoomSummaryUpdater.m index 7213c81076..2494ac3bf9 100644 --- a/MatrixSDK/Data/MXRoomSummaryUpdater.m +++ b/MatrixSDK/Data/MXRoomSummaryUpdater.m @@ -22,7 +22,7 @@ #import "MXSession.h" #import "MXRoom.h" #import "MXSession.h" -#import "MXRoomNameDefaultStringLocalizations.h" +#import "MXRoomNameDefaultStringLocalizer.h" #import "NSArray+MatrixSDK.h" @@ -346,9 +346,9 @@ - (BOOL)updateSummaryDisplayname:(MXRoomSummary *)summary session:(MXSession *)s { NSString *displayName; - if (!_roomNameStringLocalizations) + if (!_roomNameStringLocalizer) { - _roomNameStringLocalizations = [MXRoomNameDefaultStringLocalizations new]; + _roomNameStringLocalizer = [MXRoomNameDefaultStringLocalizer new]; } // Compute a display name according to algorithm provided by Matrix room summaries @@ -416,7 +416,7 @@ - (BOOL)updateSummaryDisplayname:(MXRoomSummary *)summary session:(MXSession *)s { case 0: { - displayName = _roomNameStringLocalizations.emptyRoom; + displayName = _roomNameStringLocalizer.emptyRoom; break; } case 1: @@ -426,7 +426,7 @@ - (BOOL)updateSummaryDisplayname:(MXRoomSummary *)summary session:(MXSession *)s if (member.membership == MXMembershipLeave) { - displayName = [NSString stringWithFormat:_roomNameStringLocalizations.allOtherParticipantsLeft, memberName]; + displayName = [_roomNameStringLocalizer allOtherMembersLeft:memberName]; } else { @@ -438,21 +438,19 @@ - (BOOL)updateSummaryDisplayname:(MXRoomSummary *)summary session:(MXSession *)s { NSString *firstMemberName = [self memberNameFromRoomState:roomState withIdentifier:memberIdentifiers[0]]; NSString *secondMemberName = [self memberNameFromRoomState:roomState withIdentifier:memberIdentifiers[1]]; - displayName = [NSString stringWithFormat:_roomNameStringLocalizations.twoMembers, firstMemberName, secondMemberName]; + displayName = [_roomNameStringLocalizer twoMembers:firstMemberName second:secondMemberName]; break; } default: { NSString *memberName = [self memberNameFromRoomState:roomState withIdentifier:memberIdentifiers.firstObject]; - displayName = [NSString stringWithFormat:_roomNameStringLocalizations.moreThanTwoMembers, - memberName, - @(memberCount - 2)]; + displayName = [_roomNameStringLocalizer moreThanTwoMembers:memberName count:@(memberCount - 2)]; break; } } if (memberCount > 1 - && (!displayName || [displayName isEqualToString:_roomNameStringLocalizations.emptyRoom])) + && (!displayName || [displayName isEqualToString:_roomNameStringLocalizer.emptyRoom])) { // Data are missing to compute the display name MXLogDebug(@"[MXRoomSummaryUpdater] updateSummaryDisplayname: Warning: Computed an unexpected \"Empty Room\" name. memberCount: %@", @(memberCount)); @@ -501,7 +499,7 @@ - (NSString*)fixUnexpectedEmptyRoomDisplayname:(NSUInteger)memberCount session:( { case 0: MXLogDebug(@"[MXRoomSummaryUpdater] fixUnexpectedEmptyRoomDisplayname: No luck"); - displayname = _roomNameStringLocalizations.emptyRoom; + displayname = _roomNameStringLocalizer.emptyRoom; break; case 1: @@ -513,9 +511,7 @@ - (NSString*)fixUnexpectedEmptyRoomDisplayname:(NSUInteger)memberCount session:( else { MXLogDebug(@"[MXRoomSummaryUpdater] fixUnexpectedEmptyRoomDisplayname: Half fixed 1"); - displayname = [NSString stringWithFormat:_roomNameStringLocalizations.moreThanTwoMembers, - memberNames[0], - @(memberCount - 1)]; + displayname = [_roomNameStringLocalizer moreThanTwoMembers:memberNames[0] count:@(memberCount - 1)]; } break; @@ -523,24 +519,18 @@ - (NSString*)fixUnexpectedEmptyRoomDisplayname:(NSUInteger)memberCount session:( if (memberCount == 3) { MXLogDebug(@"[MXRoomSummaryUpdater] fixUnexpectedEmptyRoomDisplayname: Fixed 2"); - displayname = [NSString stringWithFormat:_roomNameStringLocalizations.twoMembers, - memberNames[0], - memberNames[1]]; + displayname = [_roomNameStringLocalizer twoMembers:memberNames[0] second:memberNames[1]]; } else { MXLogDebug(@"[MXRoomSummaryUpdater] fixUnexpectedEmptyRoomDisplayname: Half fixed 2"); - displayname = [NSString stringWithFormat:_roomNameStringLocalizations.moreThanTwoMembers, - memberNames[0], - @(memberCount - 2)]; + displayname = [_roomNameStringLocalizer moreThanTwoMembers:memberNames[0] count:@(memberCount - 2)]; } break; default: MXLogDebug(@"[MXRoomSummaryUpdater] fixUnexpectedEmptyRoomDisplayname: Fixed 3"); - displayname = [NSString stringWithFormat:_roomNameStringLocalizations.moreThanTwoMembers, - memberNames[0], - @(memberCount - 2)]; + displayname = [_roomNameStringLocalizer moreThanTwoMembers:memberNames[0] count:@(memberCount - 2)]; break; } diff --git a/MatrixSDK/Data/MXSendReplyEventDefaultStringLocalizations.h b/MatrixSDK/Data/MXSendReplyEventDefaultStringLocalizations.h deleted file mode 100644 index 22d2fe45b3..0000000000 --- a/MatrixSDK/Data/MXSendReplyEventDefaultStringLocalizations.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - Copyright 2018 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 "MXSendReplyEventStringsLocalizable.h" - -/** - A `MXSendReplyEventDefaultStringLocalizations` instance represents default localization strings used when send reply event to a message in a room. - */ -@interface MXSendReplyEventDefaultStringLocalizations : NSObject - -@property (copy, readonly, nonnull) NSString *senderSentAnImage; -@property (copy, readonly, nonnull) NSString *senderSentAVideo; -@property (copy, readonly, nonnull) NSString *senderSentAnAudioFile; -@property (copy, readonly, nonnull) NSString *senderSentAVoiceMessage; -@property (copy, readonly, nonnull) NSString *senderSentAFile; -@property (copy, readonly, nonnull) NSString *messageToReplyToPrefix; - -@end diff --git a/MatrixSDK/Data/MXSendReplyEventDefaultStringLocalizer.h b/MatrixSDK/Data/MXSendReplyEventDefaultStringLocalizer.h new file mode 100644 index 0000000000..d0281a5b87 --- /dev/null +++ b/MatrixSDK/Data/MXSendReplyEventDefaultStringLocalizer.h @@ -0,0 +1,25 @@ +/* + Copyright 2018 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 "MXSendReplyEventStringLocalizerProtocol.h" + +/** + A `MXSendReplyEventDefaultStringLocalizer` instance represents default localization strings used when send reply event to a message in a room. + */ +@interface MXSendReplyEventDefaultStringLocalizer : NSObject + +@end diff --git a/MatrixSDK/Data/MXSendReplyEventDefaultStringLocalizations.m b/MatrixSDK/Data/MXSendReplyEventDefaultStringLocalizer.m similarity index 64% rename from MatrixSDK/Data/MXSendReplyEventDefaultStringLocalizations.m rename to MatrixSDK/Data/MXSendReplyEventDefaultStringLocalizer.m index add838063a..7adef13d44 100644 --- a/MatrixSDK/Data/MXSendReplyEventDefaultStringLocalizations.m +++ b/MatrixSDK/Data/MXSendReplyEventDefaultStringLocalizer.m @@ -14,9 +14,20 @@ limitations under the License. */ -#import "MXSendReplyEventDefaultStringLocalizations.h" +#import "MXSendReplyEventDefaultStringLocalizer.h" -@implementation MXSendReplyEventDefaultStringLocalizations +@interface MXSendReplyEventDefaultStringLocalizer () + +@property (nonatomic, strong) NSString *senderSentAnImage; +@property (nonatomic, strong) NSString *senderSentAVideo; +@property (nonatomic, strong) NSString *senderSentAnAudioFile; +@property (nonatomic, strong) NSString *senderSentAVoiceMessage; +@property (nonatomic, strong) NSString *senderSentAFile; +@property (nonatomic, strong) NSString *messageToReplyToPrefix; + +@end + +@implementation MXSendReplyEventDefaultStringLocalizer - (instancetype)init { diff --git a/MatrixSDK/Data/MXSendReplyEventStringsLocalizable.h b/MatrixSDK/Data/MXSendReplyEventStringLocalizerProtocol.h similarity index 54% rename from MatrixSDK/Data/MXSendReplyEventStringsLocalizable.h rename to MatrixSDK/Data/MXSendReplyEventStringLocalizerProtocol.h index 4c1392da2e..e6e02da544 100644 --- a/MatrixSDK/Data/MXSendReplyEventStringsLocalizable.h +++ b/MatrixSDK/Data/MXSendReplyEventStringLocalizerProtocol.h @@ -16,19 +16,21 @@ @import Foundation; +NS_ASSUME_NONNULL_BEGIN + /** - The `MXSendReplyEventStringsLocalizable` protocol defines an interface that must be implemented + The `MXSendReplyEventStringLocalizerProtocol` protocol defines an interface that must be implemented to provide string localizations when send reply event to a message in a room. */ -@protocol MXSendReplyEventStringsLocalizable - -@required +@protocol MXSendReplyEventStringLocalizerProtocol -@property (copy, readonly, nonnull) NSString *senderSentAnImage; -@property (copy, readonly, nonnull) NSString *senderSentAVideo; -@property (copy, readonly, nonnull) NSString *senderSentAnAudioFile; -@property (copy, readonly, nonnull) NSString *senderSentAVoiceMessage; -@property (copy, readonly, nonnull) NSString *senderSentAFile; -@property (copy, readonly, nonnull) NSString *messageToReplyToPrefix; +- (NSString *)senderSentAnImage; +- (NSString *)senderSentAVideo; +- (NSString *)senderSentAnAudioFile; +- (NSString *)senderSentAVoiceMessage; +- (NSString *)senderSentAFile; +- (NSString *)messageToReplyToPrefix; @end + +NS_ASSUME_NONNULL_END diff --git a/MatrixSDKTests/MXCryptoTests.m b/MatrixSDKTests/MXCryptoTests.m index 05b84210cd..f73b24eca7 100644 --- a/MatrixSDKTests/MXCryptoTests.m +++ b/MatrixSDKTests/MXCryptoTests.m @@ -28,7 +28,7 @@ #import "MXSDKOptions.h" #import "MXTools.h" -#import "MXSendReplyEventDefaultStringLocalizations.h" +#import "MXSendReplyEventDefaultStringLocalizer.h" #import "MXOutboundSessionInfo.h" #import @@ -1473,7 +1473,7 @@ - (void)testSendReplyToTextMessage NSString *expectedThirdEventBodyStringFormat = @"> <%@> **Reply to first message**\n\n**Reply to second message**"; NSString *expectedThirdEventFormattedBodyStringFormat = @"
In reply to %@

Reply to first message

Reply to second message

"; - MXSendReplyEventDefaultStringLocalizations *defaultStringLocalizations = [MXSendReplyEventDefaultStringLocalizations new]; + MXSendReplyEventDefaultStringLocalizer *defaultStringLocalizer = [MXSendReplyEventDefaultStringLocalizer new]; __block NSUInteger successFullfillCount = 0; NSUInteger expectedSuccessFulfillCount = 2; // Bob and Alice have finished their tests @@ -1503,7 +1503,7 @@ - (void)testSendReplyToTextMessage __block MXEvent *localEchoEvent = nil; // Reply to first message - [roomFromBobPOV sendReplyToEvent:event withTextMessage:secondMessageReplyToFirst formattedTextMessage:secondMessageFormattedReplyToFirst stringLocalizations:defaultStringLocalizations localEcho:&localEchoEvent success:^(NSString *eventId) { + [roomFromBobPOV sendReplyToEvent:event withTextMessage:secondMessageReplyToFirst formattedTextMessage:secondMessageFormattedReplyToFirst stringLocalizer:defaultStringLocalizer localEcho:&localEchoEvent success:^(NSString *eventId) { MXLogDebug(@"Send reply to first message with success"); } failure:^(NSError *error) { XCTFail(@"The request should not fail - NSError: %@", error); @@ -1536,7 +1536,7 @@ - (void)testSendReplyToTextMessage __block MXEvent *localEchoEvent = nil; // Reply to second message, which was also a reply - [roomFromBobPOV sendReplyToEvent:event withTextMessage:thirdMessageReplyToSecond formattedTextMessage:thirdMessageFormattedReplyToSecond stringLocalizations:defaultStringLocalizations localEcho:&localEchoEvent success:^(NSString *eventId) { + [roomFromBobPOV sendReplyToEvent:event withTextMessage:thirdMessageReplyToSecond formattedTextMessage:thirdMessageFormattedReplyToSecond stringLocalizer:defaultStringLocalizer localEcho:&localEchoEvent success:^(NSString *eventId) { MXLogDebug(@"Send reply to second message with success"); } failure:^(NSError *error) { XCTFail(@"The request should not fail - NSError: %@", error); diff --git a/MatrixSDKTests/MXRoomTests.m b/MatrixSDKTests/MXRoomTests.m index 77c6f8d0ff..43650567fb 100644 --- a/MatrixSDKTests/MXRoomTests.m +++ b/MatrixSDKTests/MXRoomTests.m @@ -20,7 +20,7 @@ #import "MXSession.h" #import "MXTools.h" -#import "MXSendReplyEventDefaultStringLocalizations.h" +#import "MXSendReplyEventDefaultStringLocalizer.h" // Do not bother with retain cycles warnings in tests #pragma clang diagnostic push @@ -706,7 +706,7 @@ - (void)testSendReplyToTextMessage NSString *expectedThirdEventBodyStringFormat = @"> <%@> **Reply to first message**\n\n**Reply to second message**"; NSString *expectedThirdEventFormattedBodyStringFormat = @"
In reply to %@

Reply to first message

Reply to second message

"; - MXSendReplyEventDefaultStringLocalizations *defaultStringLocalizations = [MXSendReplyEventDefaultStringLocalizations new]; + MXSendReplyEventDefaultStringLocalizer *defaultStringLocalizer = [MXSendReplyEventDefaultStringLocalizer new]; [matrixSDKTestsData doMXSessionTestWithBobAndARoomWithMessages:self readyToTest:^(MXSession *mxSession, MXRoom *room, XCTestExpectation *expectation) { @@ -721,7 +721,7 @@ - (void)testSendReplyToTextMessage __block MXEvent *localEchoEvent = nil; // Reply to first message - [room sendReplyToEvent:event withTextMessage:secondMessageReplyToFirst formattedTextMessage:secondMessageFormattedReplyToFirst stringLocalizations:defaultStringLocalizations localEcho:&localEchoEvent success:^(NSString *eventId) { + [room sendReplyToEvent:event withTextMessage:secondMessageReplyToFirst formattedTextMessage:secondMessageFormattedReplyToFirst stringLocalizer:defaultStringLocalizer localEcho:&localEchoEvent success:^(NSString *eventId) { MXLogDebug(@"Send reply to first message with success"); } failure:^(NSError *error) { XCTFail(@"The request should not fail - NSError: %@", error); @@ -753,7 +753,7 @@ - (void)testSendReplyToTextMessage __block MXEvent *localEchoEvent = nil; // Reply to second message, which was also a reply - [room sendReplyToEvent:event withTextMessage:thirdMessageReplyToSecond formattedTextMessage:thirdMessageFormattedReplyToSecond stringLocalizations:defaultStringLocalizations localEcho:&localEchoEvent success:^(NSString *eventId) { + [room sendReplyToEvent:event withTextMessage:thirdMessageReplyToSecond formattedTextMessage:thirdMessageFormattedReplyToSecond stringLocalizer:defaultStringLocalizer localEcho:&localEchoEvent success:^(NSString *eventId) { MXLogDebug(@"Send reply to second message with success"); } failure:^(NSError *error) { XCTFail(@"The request should not fail - NSError: %@", error); diff --git a/changelog.d/4899.api b/changelog.d/4899.api new file mode 100644 index 0000000000..13ff268335 --- /dev/null +++ b/changelog.d/4899.api @@ -0,0 +1 @@ +`MXSendReplyEventStringsLocalizable` is now `MXSendReplyEventStringLocalizerProtocol` and `MXRoomNameStringsLocalizable` is now `MXRoomNameStringLocalizerProtocol` \ No newline at end of file diff --git a/changelog.d/4899.change b/changelog.d/4899.change new file mode 100644 index 0000000000..702de76be3 --- /dev/null +++ b/changelog.d/4899.change @@ -0,0 +1 @@ +Added dynamism and compile time safety to room name and send reply event localizable strings. \ No newline at end of file From 0c193bd2c4fb595ae49f573fd7648761c156ad37 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 30 Sep 2021 22:51:42 +0100 Subject: [PATCH 16/42] Prepare for new sprint From 72f102c78babf5c0e745411caedadea680de186a Mon Sep 17 00:00:00 2001 From: Doug Date: Fri, 1 Oct 2021 14:39:15 +0100 Subject: [PATCH 17/42] Update JitsiMeetSDK pod. --- MatrixSDK.podspec | 2 +- changelog.d/4939.change | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelog.d/4939.change diff --git a/MatrixSDK.podspec b/MatrixSDK.podspec index 33c2883f2f..d9e0205972 100644 --- a/MatrixSDK.podspec +++ b/MatrixSDK.podspec @@ -57,7 +57,7 @@ Pod::Spec.new do |s| #ss.ios.dependency 'GoogleWebRTC', '~>1.1.21820' # Use WebRTC framework included in Jitsi Meet SDK - ss.ios.dependency 'JitsiMeetSDK', ' 3.5.0' + ss.ios.dependency 'JitsiMeetSDK', ' 3.10.2' # JitsiMeetSDK has not yet binaries for arm64 simulator ss.pod_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' } diff --git a/changelog.d/4939.change b/changelog.d/4939.change new file mode 100644 index 0000000000..3fde0d8375 --- /dev/null +++ b/changelog.d/4939.change @@ -0,0 +1 @@ +Pods: Update JitsiMeetSDK. \ No newline at end of file From 3b6e49ff43a3a13e8004f648a3e1acb5285fdbf2 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Mon, 4 Oct 2021 09:19:40 +0200 Subject: [PATCH 18/42] Fix performance issues with Spaces on very large accounts #4898 - Moved space graph data structure into separate class - Cache space graph data structure --- MatrixSDK.xcodeproj/project.pbxproj | 6 + .../Data/Store/MXFileStore/MXFileStore.m | 42 +++++ MatrixSDK/Data/Store/MXStore.h | 20 ++ MatrixSDK/MXSession.h | 2 +- MatrixSDK/MXSession.m | 5 - MatrixSDK/Space/MXSpaceGraphData.swift | 176 ++++++++++++++++++ .../Space/MXSpaceNotificationCounter.swift | 6 +- MatrixSDK/Space/MXSpaceService.swift | 164 ++++++++++++---- 8 files changed, 373 insertions(+), 48 deletions(-) create mode 100644 MatrixSDK/Space/MXSpaceGraphData.swift diff --git a/MatrixSDK.xcodeproj/project.pbxproj b/MatrixSDK.xcodeproj/project.pbxproj index 83e2487b15..12f6ec74c3 100644 --- a/MatrixSDK.xcodeproj/project.pbxproj +++ b/MatrixSDK.xcodeproj/project.pbxproj @@ -616,6 +616,8 @@ 32FE41371D0AB7070060835E /* MXEnumConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 32FE41351D0AB7070060835E /* MXEnumConstants.m */; }; 32FFB4F0217E146A00C96002 /* MXRecoveryKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 32FFB4EE217E146A00C96002 /* MXRecoveryKey.h */; }; 32FFB4F1217E146A00C96002 /* MXRecoveryKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 32FFB4EF217E146A00C96002 /* MXRecoveryKey.m */; }; + 3A0AF06B2705A11400679D1A /* MXSpaceGraphData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A0AF06A2705A11400679D1A /* MXSpaceGraphData.swift */; }; + 3A0AF06C2705A11400679D1A /* MXSpaceGraphData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A0AF06A2705A11400679D1A /* MXSpaceGraphData.swift */; }; 3A108A3A2580E9C2005EEBE9 /* MXKeyProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A108A392580E9C2005EEBE9 /* MXKeyProvider.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3A108A3B2580E9C2005EEBE9 /* MXKeyProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A108A392580E9C2005EEBE9 /* MXKeyProvider.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3A108A7E25810C96005EEBE9 /* MXKeyData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A108A7C25810C96005EEBE9 /* MXKeyData.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -2069,6 +2071,7 @@ 32FFB4EE217E146A00C96002 /* MXRecoveryKey.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXRecoveryKey.h; sourceTree = ""; }; 32FFB4EF217E146A00C96002 /* MXRecoveryKey.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MXRecoveryKey.m; sourceTree = ""; }; 373B3662A92DBDD847639FA2 /* Pods-SDK-MatrixSDKTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDK-MatrixSDKTests.debug.xcconfig"; path = "Target Support Files/Pods-SDK-MatrixSDKTests/Pods-SDK-MatrixSDKTests.debug.xcconfig"; sourceTree = ""; }; + 3A0AF06A2705A11400679D1A /* MXSpaceGraphData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MXSpaceGraphData.swift; sourceTree = ""; }; 3A108A392580E9C2005EEBE9 /* MXKeyProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXKeyProvider.h; sourceTree = ""; }; 3A108A7C25810C96005EEBE9 /* MXKeyData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXKeyData.h; sourceTree = ""; }; 3A108A7D25810C96005EEBE9 /* MXKeyData.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MXKeyData.m; sourceTree = ""; }; @@ -3871,6 +3874,7 @@ 3A7509BA26FC61DF00B85773 /* MXSpaceNotificationCounter.swift */, B105CDD5261F54C8006EB204 /* MXSpaceChildContent.m */, 3AF85F9126FC7AE800A9E67B /* MXSpaceNotificationState.swift */, + 3A0AF06A2705A11400679D1A /* MXSpaceGraphData.swift */, ); path = Space; sourceTree = ""; @@ -5316,6 +5320,7 @@ 3274538623FD69D600438328 /* MXKeyVerificationRequestByToDeviceJSONModel.m in Sources */, B1A026F826161EF5001AADFF /* MXSpaceChildSummaryResponse.m in Sources */, 324DD2C7246E638B00377005 /* MXAesHmacSha2.m in Sources */, + 3A0AF06B2705A11400679D1A /* MXSpaceGraphData.swift in Sources */, 321CFDEF225264C4004D31DF /* NSArray+MatrixSDK.m in Sources */, 327A5F52239805F600ED6329 /* MXKeyVerificationStart.m in Sources */, 3294FD9D22F321B0007F1E60 /* MXServiceTermsRestClient.m in Sources */, @@ -5753,6 +5758,7 @@ B14EF2562397E90400758AF0 /* MXLogger.m in Sources */, EC383BB425406894002FBBE6 /* MXSyncResponseFileStore.swift in Sources */, B14EF2572397E90400758AF0 /* MXMegolmExportEncryption.m in Sources */, + 3A0AF06C2705A11400679D1A /* MXSpaceGraphData.swift in Sources */, B14EF2582397E90400758AF0 /* MXFilterObject.m in Sources */, EC60EDEB265CFF3100B39A4E /* MXRoomInviteState.m in Sources */, 8EC511072568216B00EC4E5B /* MXTaggedEventInfo.m in Sources */, diff --git a/MatrixSDK/Data/Store/MXFileStore/MXFileStore.m b/MatrixSDK/Data/Store/MXFileStore/MXFileStore.m index 22d4f1c754..e1433372ba 100644 --- a/MatrixSDK/Data/Store/MXFileStore/MXFileStore.m +++ b/MatrixSDK/Data/Store/MXFileStore/MXFileStore.m @@ -45,6 +45,7 @@ static NSString *const kMXFileStoreRoomSummaryFile = @"summary"; static NSString *const kMXFileStoreRoomAccountDataFile = @"accountData"; static NSString *const kMXFileStoreRoomReadReceiptsFile = @"readReceipts"; +static NSString *const kMXFileStoreSpaceGraphFile = @"spaceGraph"; static NSUInteger preloadOptions; @@ -1050,6 +1051,11 @@ - (NSString*)readReceiptsFileForRoom:(NSString*)roomId forBackup:(BOOL)backup return [[self folderForRoom:roomId forBackup:backup] stringByAppendingPathComponent:kMXFileStoreRoomReadReceiptsFile]; } +- (NSString*)spaceGraphFileForBackup:(BOOL)backup +{ + return [(backup ? storeBackupPath : storePath) stringByAppendingPathComponent:kMXFileStoreSpaceGraphFile]; +} + - (NSString*)metaDataFileForBackup:(BOOL)backup { if (!backup) @@ -2131,6 +2137,42 @@ - (void)saveReceipts } } +#pragma mark - Spaces graph + +- (BOOL)storeSpaceGraphData:(nonnull MXSpaceGraphData*)graph +{ + NSString *file = [self spaceGraphFileForBackup:NO]; + NSString *backupFile = [self spaceGraphFileForBackup:YES]; + + // Backup the file + if (backupFile && [[NSFileManager defaultManager] fileExistsAtPath:file]) + { + [[NSFileManager defaultManager] moveItemAtPath:file toPath:backupFile error:nil]; + } + + NSError *error = nil; + NSData * data = [NSKeyedArchiver archivedDataWithRootObject:graph requiringSecureCoding:NO error:&error]; + + // Store new data + return [NSKeyedArchiver archiveRootObject:graph toFile:file]; +} + +- (MXSpaceGraphData* _Nullable)loadSpaceGraphData +{ + MXSpaceGraphData *graph = nil; + NSString *file = [self spaceGraphFileForBackup:NO]; + @try + { + graph = [NSKeyedUnarchiver unarchiveObjectWithFile:file]; + } + @catch (NSException *exception) + { + MXLogDebug(@"[MXFileStore] Warning: spaceGraph file has been corrupted"); + } + + return graph; +} + #pragma mark - Async API - (void)asyncUsers:(void (^)(NSArray * _Nonnull))success failure:(nullable void (^)(NSError * _Nonnull))failure diff --git a/MatrixSDK/Data/Store/MXStore.h b/MatrixSDK/Data/Store/MXStore.h index 6103e301d8..540c7edb3e 100644 --- a/MatrixSDK/Data/Store/MXStore.h +++ b/MatrixSDK/Data/Store/MXStore.h @@ -29,6 +29,8 @@ #import "MXEventsEnumerator.h" +@class MXSpaceGraphData; + /** The `MXStore` protocol defines an interface that must be implemented in order to store Matrix data handled during a `MXSession`. @@ -517,4 +519,22 @@ success:(nonnull void (^)(NSString * _Nullable filterId))success failure:(nullable void (^)(NSError * _Nullable error))failure; +#pragma mark - Space graph data +/** + Stores the graph of space + + @param graph the data of the space graph + + @return YES if the data has been succesflly stored. + */ +- (BOOL)storeSpaceGraphData:(nonnull MXSpaceGraphData*)graph; + +/** + Loads the graph of space from the store + + @return an instance of `MXSpaceGraphData` if the data has been loaded succesfully. Nil otherwise. + */ +- (MXSpaceGraphData* _Nullable)loadSpaceGraphData; + + @end diff --git a/MatrixSDK/MXSession.h b/MatrixSDK/MXSession.h index 91ca994c54..1596fc3957 100644 --- a/MatrixSDK/MXSession.h +++ b/MatrixSDK/MXSession.h @@ -897,7 +897,7 @@ typedef void (^MXOnBackgroundSyncFail)(NSError *error); @return the MXRoom instance. */ -- (MXRoom *)roomWithRoomId:(NSString*)roomId; +- (MXRoom * _Nullable)roomWithRoomId:(NSString* _Nonnull)roomId; /** Get the MXRoom instance of the room that owns the passed room alias. diff --git a/MatrixSDK/MXSession.m b/MatrixSDK/MXSession.m index 7b2cf6c729..79f58ec2f0 100644 --- a/MatrixSDK/MXSession.m +++ b/MatrixSDK/MXSession.m @@ -663,11 +663,6 @@ - (void)handleSyncResponse:(MXSyncResponse *)syncResponse MXLogDebug(@"[MXSession] Next sync token: %@", syncResponse.nextBatch); self.store.eventStreamToken = syncResponse.nextBatch; - if (self.spaceService.needsUpdate || syncResponse.rooms.join.count || syncResponse.rooms.invite.count || syncResponse.rooms.leave.count || syncResponse.toDevice.events.count) - { - [self.spaceService buildGraphWith:self.rooms]; - } - if (completion) { completion(); diff --git a/MatrixSDK/Space/MXSpaceGraphData.swift b/MatrixSDK/Space/MXSpaceGraphData.swift new file mode 100644 index 0000000000..bf31f7f13f --- /dev/null +++ b/MatrixSDK/Space/MXSpaceGraphData.swift @@ -0,0 +1,176 @@ +// +// Copyright 2021 The Matrix.org Foundation C.I.C +// +// 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 + +/// MXSpaceGraphData aims to store all the data needed for the space graph +class MXSpaceGraphData: NSObject, NSCoding { + + // MARK: - Constants + + private enum Constants { + static let spaceRoomIdsKey: String = "spaceRoomIds" + static let parentIdsPerRoomIdKey: String = "parentIdsPerRoomId" + static let ancestorsPerRoomIdKey: String = "ancestorsPerRoomId" + static let descendantsPerRoomIdKey: String = "descendantsPerRoomId" + static let rootSpaceIdsKey: String = "rootSpaceIds" + static let orphanedRoomIdsKey: String = "orphanedRoomIds" + static let orphanedDirectRoomIdsKey: String = "orphanedDirectRoomIds" + } + + // MARK: - Properties + + /// Array of all space IDs for the session + let spaceRoomIds: [String] + + /// List of IDs of the direct parents for each room ID + let parentIdsPerRoomId: [String : Set] + + /// List of IDs of the ancestors (recursive parents) for each room ID + let ancestorsPerRoomId: [String: Set] + + /// List of IDs of the descendants (recursive children) for each room ID + let descendantsPerRoomId: [String: Set] + + /// List of space IDs for spaces without parents + let rootSpaceIds: [String] + + /// List of all rooms without space + let orphanedRoomIds: Set + + /// List of all direct rooms without space + let orphanedDirectRoomIds: Set + + // MARK: - Public + + override init() { + self.spaceRoomIds = [] + self.parentIdsPerRoomId = [:] + self.ancestorsPerRoomId = [:] + self.descendantsPerRoomId = [:] + self.rootSpaceIds = [] + self.orphanedRoomIds = [] + self.orphanedDirectRoomIds = [] + + super.init() + } + + init(spaceRoomIds: [String], + parentIdsPerRoomId: [String : Set], + ancestorsPerRoomId: [String: Set], + descendantsPerRoomId: [String: Set], + rootSpaceIds: [String], + orphanedRoomIds: Set, + orphanedDirectRoomIds: Set) { + self.spaceRoomIds = spaceRoomIds + self.parentIdsPerRoomId = parentIdsPerRoomId + self.ancestorsPerRoomId = ancestorsPerRoomId + self.descendantsPerRoomId = descendantsPerRoomId + self.rootSpaceIds = rootSpaceIds + self.orphanedRoomIds = orphanedRoomIds + self.orphanedDirectRoomIds = orphanedDirectRoomIds + } + + // MARK: - NSCoding + + func encode(with coder: NSCoder) { + coder.encode(self.spaceRoomIds, forKey: Constants.spaceRoomIdsKey) + coder.encode(self.parentIdsPerRoomId, forKey: Constants.parentIdsPerRoomIdKey) + coder.encode(self.ancestorsPerRoomId, forKey: Constants.ancestorsPerRoomIdKey) + coder.encode(self.descendantsPerRoomId, forKey: Constants.descendantsPerRoomIdKey) + coder.encode(self.rootSpaceIds, forKey: Constants.rootSpaceIdsKey) + coder.encode(self.orphanedRoomIds, forKey: Constants.orphanedRoomIdsKey) + coder.encode(self.orphanedDirectRoomIds, forKey: Constants.orphanedDirectRoomIdsKey) + } + + required init(coder: NSCoder) { + self.spaceRoomIds = coder.decodeObject(forKey: Constants.spaceRoomIdsKey) as? [String] ?? [] + self.parentIdsPerRoomId = coder.decodeObject(forKey: Constants.parentIdsPerRoomIdKey) as? [String : Set] ?? [:] + self.ancestorsPerRoomId = coder.decodeObject(forKey: Constants.ancestorsPerRoomIdKey) as? [String : Set] ?? [:] + self.descendantsPerRoomId = coder.decodeObject(forKey: Constants.descendantsPerRoomIdKey) as? [String : Set] ?? [:] + self.rootSpaceIds = coder.decodeObject(forKey: Constants.rootSpaceIdsKey) as? [String] ?? [] + self.orphanedRoomIds = coder.decodeObject(forKey: Constants.orphanedRoomIdsKey) as? Set ?? Set() + self.orphanedDirectRoomIds = coder.decodeObject(forKey: Constants.orphanedDirectRoomIdsKey) as? Set ?? Set() + } + + // MARK: - JSON format + + func jsonDictionary() -> [String : Any]! { + return [ + Constants.spaceRoomIdsKey: self.spaceRoomIds, + Constants.parentIdsPerRoomIdKey: self.parentIdsPerRoomId, + Constants.ancestorsPerRoomIdKey: self.ancestorsPerRoomId, + Constants.descendantsPerRoomIdKey: self.descendantsPerRoomId, + Constants.rootSpaceIdsKey: self.rootSpaceIds, + Constants.orphanedRoomIdsKey: self.orphanedRoomIds, + Constants.orphanedDirectRoomIdsKey: self.orphanedDirectRoomIds + ] + } + + class func model(fromJSON dictionary: [AnyHashable : Any]!) -> MXSpaceGraphData? { + guard let spaceIdsJson = dictionary[Constants.spaceRoomIdsKey] as? [String] else { + MXLog.error("[MXSpaceGraphData] model fromJSON aborted: missing \(Constants.spaceRoomIdsKey)") + return nil + } + guard let parentIdsPerRoomIdJson = dictionary[Constants.parentIdsPerRoomIdKey] as? [String : [String]] else { + MXLog.error("[MXSpaceGraphData] model fromJSON aborted: missing \(Constants.parentIdsPerRoomIdKey)") + return nil + } + guard let ancestorsPerRoomIdJson = dictionary[Constants.ancestorsPerRoomIdKey] as? [String : [String]] else { + MXLog.error("[MXSpaceGraphData] model fromJSON aborted: missing \(Constants.ancestorsPerRoomIdKey)") + return nil + } + guard let descendantsPerRoomIdJson = dictionary[Constants.descendantsPerRoomIdKey] as? [String : [String]] else { + MXLog.error("[MXSpaceGraphData] model fromJSON aborted: missing \(Constants.descendantsPerRoomIdKey)") + return nil + } + guard let rootSpaceIdsJson = dictionary[Constants.rootSpaceIdsKey] as? [String] else { + MXLog.error("[MXSpaceGraphData] model fromJSON aborted: missing \(Constants.rootSpaceIdsKey)") + return nil + } + guard let orphanedRoomIdsJson = dictionary[Constants.orphanedRoomIdsKey] as? [String] else { + MXLog.error("[MXSpaceGraphData] model fromJSON aborted: missing \(Constants.orphanedRoomIdsKey)") + return nil + } + guard let orphanedDirectRoomIdsJson = dictionary[Constants.orphanedDirectRoomIdsKey] as? [String] else { + MXLog.error("[MXSpaceGraphData] model fromJSON aborted: missing \(Constants.orphanedDirectRoomIdsKey)") + return nil + } + + var parentIdsPerRoomId: [String : Set] = [:] + var ancestorsPerRoomId: [String: Set] = [:] + var descendantsPerRoomId: [String: Set] = [:] + var orphanedRoomIds: Set = Set() + var orphanedDirectRoomIds: Set = Set() + + parentIdsPerRoomIdJson.forEach { (key: String, value: [String]) in + parentIdsPerRoomId[key] = Set(value) + } + + ancestorsPerRoomIdJson.forEach { (key: String, value: [String]) in + ancestorsPerRoomId[key] = Set(value) + } + + descendantsPerRoomIdJson.forEach { (key: String, value: [String]) in + descendantsPerRoomId[key] = Set(value) + } + + orphanedRoomIds = Set(orphanedRoomIdsJson) + orphanedDirectRoomIds = Set(orphanedDirectRoomIdsJson) + + return MXSpaceGraphData(spaceRoomIds: spaceIdsJson, parentIdsPerRoomId: parentIdsPerRoomId, ancestorsPerRoomId: ancestorsPerRoomId, descendantsPerRoomId: descendantsPerRoomId, rootSpaceIds: rootSpaceIdsJson, orphanedRoomIds: orphanedRoomIds, orphanedDirectRoomIds: orphanedDirectRoomIds) + } +} diff --git a/MatrixSDK/Space/MXSpaceNotificationCounter.swift b/MatrixSDK/Space/MXSpaceNotificationCounter.swift index e2080e8f34..d105f445ff 100644 --- a/MatrixSDK/Space/MXSpaceNotificationCounter.swift +++ b/MatrixSDK/Space/MXSpaceNotificationCounter.swift @@ -36,8 +36,8 @@ public class MXSpaceNotificationCounter: NSObject { /// - Parameters: /// - spaces: list of spaces of the current sessiom /// - rooms: list of rooms of the current session - /// - flattenedParentIds: the flattened aprent ID for all rooms - public func computeNotificationCount(for spaces:[MXSpace], with rooms:[MXRoom], flattenedParentIds: [String: Set]) { + /// - ancestorsPerRoomId: List of IDs of the ancestors (recursive parents) for each room ID + public func computeNotificationCount(for spaces:[MXSpace], with rooms:[MXRoom], ancestorsPerRoomId: [String: Set]) { let startDate = Date() MXLog.debug("[Spaces] computeNotificationCount started") @@ -53,7 +53,7 @@ public class MXSpaceNotificationCounter: NSObject { homeNotificationState += notificationState for space in spaces { - if flattenedParentIds[room.roomId]?.contains(space.spaceId) ?? false { + if ancestorsPerRoomId[room.roomId]?.contains(space.spaceId) ?? false { let storedState = notificationStatePerSpaceId[space.spaceId] ?? MXSpaceNotificationState() notificationStatePerSpaceId[space.spaceId] = storedState + notificationState } diff --git a/MatrixSDK/Space/MXSpaceService.swift b/MatrixSDK/Space/MXSpaceService.swift index c78e184da0..a072ebf4b5 100644 --- a/MatrixSDK/Space/MXSpaceService.swift +++ b/MatrixSDK/Space/MXSpaceService.swift @@ -58,31 +58,34 @@ public class MXSpaceService: NSObject { private let processingQueue: DispatchQueue private let completionQueue: DispatchQueue - private var spaces: [MXSpace] = [] - private var spacesPerId: [String : MXSpace] = [:] - private var parentIdsPerRoomId: [String : Set] = [:] - private var flattenedParentIds: [String: Set] = [:] - - private var rootSpaces: [MXSpace] = [] { + private var graph: MXSpaceGraphData = MXSpaceGraphData() { didSet { - self.rootSpaceSummaries = rootSpaces.compactMap { space in - return space.summary + self.graph.spaceRoomIds.forEach { spaceId in + if let space = self.getSpace(withId: spaceId) { + self.spacesPerId[spaceId] = space + } } } } - private var orphanedRooms: [MXRoom] = [] - private var orphanedDirectRooms: [MXRoom] = [] + private var spacesPerId: [String:MXSpace] = [:] private var isGraphBuilding = false; public let notificationCounter = MXSpaceNotificationCounter() - public private(set) var rootSpaceSummaries: [MXRoomSummary] = [] + public var rootSpaceSummaries: [MXRoomSummary] { + return self.graph.rootSpaceIds.compactMap { spaceId in + self.session.roomSummary(withRoomId: spaceId) + } + } public private(set) var needsUpdate: Bool = true public var graphUpdateEnabled = true + private var sessionStateDidChangeObserver: Any? + private var sessionDidSyncObserver: Any? + // MARK: - Setup public init(session: MXSession) { @@ -90,19 +93,22 @@ public class MXSpaceService: NSObject { self.roomTypeMapper = MXRoomTypeMapper(defaultRoomType: .room) self.processingQueue = DispatchQueue(label: "org.matrix.sdk.MXSpaceService.processingQueue", attributes: .concurrent) self.completionQueue = DispatchQueue.main + + super.init() + + self.registerNotificationObservers() + } + + deinit { + unregisterNotificationObservers() } // MARK: - Public + /// cloase the service and free all data public func close() { self.isGraphBuilding = true - self.spaces = [] - self.spacesPerId = [:] - self.parentIdsPerRoomId = [:] - self.flattenedParentIds = [:] - self.orphanedRooms = [] - self.orphanedDirectRooms = [] - self.rootSpaceSummaries = [] + self.graph = MXSpaceGraphData() self.notificationCounter.close() self.isGraphBuilding = false self.completionQueue.async { @@ -110,13 +116,34 @@ public class MXSpaceService: NSObject { } } + /// Loads graph from the given store + /// - Parameters: + /// - store: store used to load graph + public func loadData(from store: MXStore) { + self.processingQueue.async { + self.graph = store.loadSpaceGraphData?() ?? MXSpaceGraphData() + + self.completionQueue.async { + NotificationCenter.default.post(name: MXSpaceService.didBuildSpaceGraph, object: self) + } + } + } + /// Allows to know if a given room is a descendant of a given space /// - Parameters: /// - roomId: ID of the room /// - spaceId: ID of the space /// - Returns: `true` if the room with the given ID is an ancestor of the space with the given ID .`false` otherwise public func isRoom(withId roomId: String, descendantOf spaceId: String) -> Bool { - return flattenedParentIds[roomId]?.contains(spaceId) ?? false + return self.graph.descendantsPerRoomId[spaceId]?.contains(roomId) ?? false + } + + /// Allows to know if the room is oprhnaed (e.g. has no ancestor) + /// - Parameters: + /// - roomId: ID of the room + /// - Returns: `true` if the room with the given ID is orphaned .`false` otherwise + public func isOrphanedRoom(withId roomId: String) -> Bool { + return self.graph.orphanedRoomIds.contains(roomId) || self.graph.orphanedDirectRoomIds.contains(roomId) } /// Build the graph of rooms @@ -155,28 +182,46 @@ public class MXSpaceService: NSObject { } } - self.spaces = output.spaces - self.spacesPerId = output.spacesPerId - self.parentIdsPerRoomId = parentIdsPerRoomId - self.rootSpaces = output.spaces.filter { space in + let rootSpaces = output.spaces.filter { space in return parentIdsPerRoomId[space.spaceId] == nil } - self.orphanedRooms = self.session.rooms.filter { room in - return !room.isDirect && parentIdsPerRoomId[room.roomId] == nil + + var ancestorsPerRoomId: [String: Set] = [:] + var descendantsPerRoomId: [String: Set] = [:] + rootSpaces.forEach { space in + self.buildRoomHierarchy(with: space, visitedSpaceIds: [], ancestorsPerRoomId: &ancestorsPerRoomId, descendantsPerRoomId: &descendantsPerRoomId) } - self.orphanedDirectRooms = self.session.rooms.filter { room in - return room.isDirect && parentIdsPerRoomId[room.roomId] == nil + + var orphanedRoomIds: Set = Set() + var orphanedDirectRoomIds: Set = Set() + for room in rooms { + if !room.isDirect && parentIdsPerRoomId[room.roomId] == nil { + orphanedRoomIds.insert(room.roomId) + } else if room.isDirect && parentIdsPerRoomId[room.roomId] == nil { + orphanedDirectRoomIds.insert(room.roomId) + } } + + self.graph = MXSpaceGraphData( + spaceRoomIds: output.spaces.map({ space in + space.spaceId + }), + parentIdsPerRoomId: parentIdsPerRoomId, + ancestorsPerRoomId: ancestorsPerRoomId, + descendantsPerRoomId: descendantsPerRoomId, + rootSpaceIds: rootSpaces.map({ space in + space.spaceId + }), + orphanedRoomIds: orphanedRoomIds, + orphanedDirectRoomIds: orphanedDirectRoomIds) - var flattenedParentIds: [String: Set] = [:] - self.rootSpaces.forEach { space in - self.buildFlattenedParentIdList(with: space, visitedSpaceIds: [], flattenedParentIds: &flattenedParentIds) + if !(self.session.store?.store?(self.graph) ?? false) { + MXLog.error("[Spaces] buildGraph: failed to store space graph") } - self.flattenedParentIds = flattenedParentIds // TODO improve updateNotificationsCount and call the method to all spaces once subspaces will be supported - self.notificationCounter.computeNotificationCount(for: self.rootSpaces, with: rooms, flattenedParentIds: flattenedParentIds) - + self.notificationCounter.computeNotificationCount(for: rootSpaces, with: rooms, ancestorsPerRoomId: ancestorsPerRoomId) + MXLog.debug("[Spaces] buildGraph ended after \(Date().timeIntervalSince(startDate))s") self.completionQueue.async { @@ -236,9 +281,14 @@ public class MXSpaceService: NSObject { /// Get a space from a roomId. /// - Parameter spaceId: The id of the space. - /// - Returns: A MXSpace with the associated roomId or null if room type is not space. + /// - Returns: A MXSpace with the associated roomId or null if room doesn't exists or the room type is not space. public func getSpace(withId spaceId: String) -> MXSpace? { - return self.spacesPerId[spaceId] + var space = self.spacesPerId[spaceId] + if space == nil, let newSpace = self.session.room(withRoomId: spaceId)?.toSpace() { + space = newSpace + self.spacesPerId[spaceId] = newSpace + } + return space } /// Get the space children informations of a given space from the server. @@ -317,18 +367,54 @@ public class MXSpaceService: NSObject { // MARK: - Private - private func buildFlattenedParentIdList(with space: MXSpace, visitedSpaceIds: [String], flattenedParentIds: inout [String: Set]) { + private func registerNotificationObservers() { + self.sessionStateDidChangeObserver = NotificationCenter.default.addObserver(forName: NSNotification.Name.mxSessionStateDidChange, object: session, queue: nil) { [weak self] notification in + guard let session = self?.session, session.state == .storeDataReady, let store = self?.session.store else { + return + } + + self?.loadData(from: store) + } + + self.sessionDidSyncObserver = NotificationCenter.default.addObserver(forName: NSNotification.Name.mxSessionDidSync, object: session, queue: nil) { [weak self] notification in + guard let self = self, let syncResponse = notification.userInfo?[kMXSessionNotificationSyncResponseKey] as? MXSyncResponse else { + return + } + + guard self.needsUpdate || !(syncResponse.rooms?.join?.isEmpty ?? true) || !(syncResponse.rooms?.invite?.isEmpty ?? true) || !(syncResponse.rooms?.leave?.isEmpty ?? true) || !(syncResponse.toDevice?.events.isEmpty ?? true) else + { + return + } + + self.buildGraph(with: self.session.rooms) + } + } + + private func unregisterNotificationObservers() { + if let observer = self.sessionStateDidChangeObserver { + NotificationCenter.default.removeObserver(observer) + } + if let observer = self.sessionDidSyncObserver { + NotificationCenter.default.removeObserver(observer) + } + } + + private func buildRoomHierarchy(with space: MXSpace, visitedSpaceIds: [String], ancestorsPerRoomId: inout [String: Set], descendantsPerRoomId: inout [String: Set]) { var visitedSpaceIds = visitedSpaceIds visitedSpaceIds.append(space.spaceId) space.childRoomIds.forEach { roomId in - var parentIds = flattenedParentIds[roomId] ?? Set() + var parentIds = ancestorsPerRoomId[roomId] ?? Set() visitedSpaceIds.forEach { spaceId in parentIds.insert(spaceId) + + var descendantIds = descendantsPerRoomId[spaceId] ?? Set() + descendantIds.insert(roomId) + descendantsPerRoomId[spaceId] = descendantIds } - flattenedParentIds[roomId] = parentIds + ancestorsPerRoomId[roomId] = parentIds } space.childSpaces.forEach { childSpace in - buildFlattenedParentIdList(with: childSpace, visitedSpaceIds: visitedSpaceIds, flattenedParentIds: &flattenedParentIds) + buildRoomHierarchy(with: childSpace, visitedSpaceIds: visitedSpaceIds, ancestorsPerRoomId: &ancestorsPerRoomId, descendantsPerRoomId: &descendantsPerRoomId) } } From a47fa9c981b11edce30d99449eed047f1fb0bb28 Mon Sep 17 00:00:00 2001 From: Doug Date: Mon, 4 Oct 2021 11:36:22 +0100 Subject: [PATCH 19/42] Update Realm pod. --- MatrixSDK.podspec | 2 +- Podfile | 2 +- Podfile.lock | 12 ++++++------ changelog.d/4939.change | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/MatrixSDK.podspec b/MatrixSDK.podspec index d9e0205972..2bd9fa901c 100644 --- a/MatrixSDK.podspec +++ b/MatrixSDK.podspec @@ -40,7 +40,7 @@ Pod::Spec.new do |s| # Requirements for e2e encryption ss.dependency 'OLMKit', '~> 3.2.5' - ss.dependency 'Realm', '10.7.6' + ss.dependency 'Realm', '10.16.0' ss.dependency 'libbase58', '~> 0.1.4' end diff --git a/Podfile b/Podfile index eaef7f2ff4..9beae94e05 100644 --- a/Podfile +++ b/Podfile @@ -10,7 +10,7 @@ abstract_target 'MatrixSDK' do pod 'OLMKit', '~> 3.2.5', :inhibit_warnings => true #pod 'OLMKit', :path => '../olm/OLMKit.podspec' - pod 'Realm', '10.7.6' + pod 'Realm', '10.16.0' pod 'libbase58', '~> 0.1.4' target 'MatrixSDK-iOS' do diff --git a/Podfile.lock b/Podfile.lock index 02c36c110c..02f1509e80 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -34,9 +34,9 @@ PODS: - OLMKit/olmcpp (= 3.2.5) - OLMKit/olmc (3.2.5) - OLMKit/olmcpp (3.2.5) - - Realm (10.7.6): - - Realm/Headers (= 10.7.6) - - Realm/Headers (10.7.6) + - Realm (10.16.0): + - Realm/Headers (= 10.16.0) + - Realm/Headers (10.16.0) - SwiftyBeaver (1.9.5) DEPENDENCIES: @@ -45,7 +45,7 @@ DEPENDENCIES: - libbase58 (~> 0.1.4) - OHHTTPStubs (~> 9.1.0) - OLMKit (~> 3.2.5) - - Realm (= 10.7.6) + - Realm (= 10.16.0) - SwiftyBeaver (= 1.9.5) SPEC REPOS: @@ -64,9 +64,9 @@ SPEC CHECKSUMS: libbase58: 7c040313537b8c44b6e2d15586af8e21f7354efd OHHTTPStubs: 90eac6d8f2c18317baeca36698523dc67c513831 OLMKit: 9fb4799c4a044dd2c06bda31ec31a12191ad30b5 - Realm: ed860452717c8db8f4bf832b6807f7f2ce708839 + Realm: b6027801398f3743fc222f096faa85281b506e6c SwiftyBeaver: 84069991dd5dca07d7069100985badaca7f0ce82 -PODFILE CHECKSUM: ca61b137d30e689c0afb8cb0ffe424c3e276bab6 +PODFILE CHECKSUM: ea9778919e01b860c6b9fae81f500df82de7ad60 COCOAPODS: 1.10.1 diff --git a/changelog.d/4939.change b/changelog.d/4939.change index 3fde0d8375..939a40286c 100644 --- a/changelog.d/4939.change +++ b/changelog.d/4939.change @@ -1 +1 @@ -Pods: Update JitsiMeetSDK. \ No newline at end of file +Pods: Update JitsiMeetSDK and Realm. \ No newline at end of file From c22988feb1fc385041b040587038a551baefc56e Mon Sep 17 00:00:00 2001 From: Doug Date: Mon, 4 Oct 2021 15:24:43 +0100 Subject: [PATCH 20/42] Update CocoaPods and fastlane. --- Gemfile | 2 +- Gemfile.lock | 217 ++++++++++++++++++++++++----------------- changelog.d/4951.build | 1 + 3 files changed, 128 insertions(+), 92 deletions(-) create mode 100644 changelog.d/4951.build diff --git a/Gemfile b/Gemfile index fdd7bdd703..b6a6c9369d 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,4 @@ source "https://rubygems.org" gem "fastlane" -gem "cocoapods", '~>1.10.1' +gem "cocoapods", '~>1.11.2' diff --git a/Gemfile.lock b/Gemfile.lock index a2a8466161..91f1378f35 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,40 +1,43 @@ GEM remote: https://rubygems.org/ specs: - CFPropertyList (3.0.2) - activesupport (5.2.4.5) + CFPropertyList (3.0.4) + rexml + activesupport (6.1.4.1) concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) addressable (2.8.0) public_suffix (>= 2.0.2, < 5.0) algoliasearch (1.27.5) httpclient (~> 2.8, >= 2.8.3) json (>= 1.5.1) + artifactory (3.0.15) atomos (0.1.3) - aws-eventstream (1.1.0) - aws-partitions (1.393.0) - aws-sdk-core (3.109.2) + aws-eventstream (1.2.0) + aws-partitions (1.510.0) + aws-sdk-core (3.121.1) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.239.0) aws-sigv4 (~> 1.1) jmespath (~> 1.0) - aws-sdk-kms (1.39.0) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-kms (1.48.0) + aws-sdk-core (~> 3, >= 3.120.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.84.1) - aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-s3 (1.103.0) + aws-sdk-core (~> 3, >= 3.120.0) aws-sdk-kms (~> 1) - aws-sigv4 (~> 1.1) - aws-sigv4 (1.2.2) + aws-sigv4 (~> 1.4) + aws-sigv4 (1.4.0) aws-eventstream (~> 1, >= 1.0.2) babosa (1.0.4) claide (1.0.3) - cocoapods (1.10.1) - addressable (~> 2.6) + cocoapods (1.11.2) + addressable (~> 2.8) claide (>= 1.0.2, < 2.0) - cocoapods-core (= 1.10.1) + cocoapods-core (= 1.11.2) cocoapods-deintegrate (>= 1.0.3, < 2.0) cocoapods-downloader (>= 1.4.0, < 2.0) cocoapods-plugins (>= 1.0.0, < 2.0) @@ -45,63 +48,79 @@ GEM escape (~> 0.0.4) fourflusher (>= 2.3.0, < 3.0) gh_inspector (~> 1.0) - molinillo (~> 0.6.6) + molinillo (~> 0.8.0) nap (~> 1.0) - ruby-macho (~> 1.4) - xcodeproj (>= 1.19.0, < 2.0) - cocoapods-core (1.10.1) - activesupport (> 5.0, < 6) - addressable (~> 2.6) + ruby-macho (>= 1.0, < 3.0) + xcodeproj (>= 1.21.0, < 2.0) + cocoapods-core (1.11.2) + activesupport (>= 5.0, < 7) + addressable (~> 2.8) algoliasearch (~> 1.0) concurrent-ruby (~> 1.1) fuzzy_match (~> 2.0.4) nap (~> 1.0) netrc (~> 0.11) - public_suffix + public_suffix (~> 4.0) typhoeus (~> 1.0) - cocoapods-deintegrate (1.0.4) - cocoapods-downloader (1.4.0) + cocoapods-deintegrate (1.0.5) + cocoapods-downloader (1.5.1) cocoapods-plugins (1.0.0) nap - cocoapods-search (1.0.0) - cocoapods-trunk (1.5.0) + cocoapods-search (1.0.1) + cocoapods-trunk (1.6.0) nap (>= 0.8, < 2.0) netrc (~> 0.11) cocoapods-try (1.2.0) colored (1.2) colored2 (3.1.2) - commander-fastlane (4.4.6) - highline (~> 1.7.2) - concurrent-ruby (1.1.8) + commander (4.6.0) + highline (~> 2.0.0) + concurrent-ruby (1.1.9) declarative (0.0.20) - declarative-option (0.1.0) - digest-crc (0.6.1) - rake (~> 13.0) + digest-crc (0.6.4) + rake (>= 12.0.0, < 14.0.0) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) dotenv (2.7.6) - emoji_regex (3.2.1) + emoji_regex (3.2.3) escape (0.0.4) - ethon (0.12.0) - ffi (>= 1.3.0) - excon (0.78.0) - faraday (1.1.0) + ethon (0.14.0) + ffi (>= 1.15.0) + excon (0.86.0) + faraday (1.8.0) + faraday-em_http (~> 1.0) + faraday-em_synchrony (~> 1.0) + faraday-excon (~> 1.1) + faraday-httpclient (~> 1.0.1) + faraday-net_http (~> 1.0) + faraday-net_http_persistent (~> 1.1) + faraday-patron (~> 1.0) + faraday-rack (~> 1.0) multipart-post (>= 1.2, < 3) - ruby2_keywords + ruby2_keywords (>= 0.0.4) faraday-cookie_jar (0.0.7) faraday (>= 0.8.0) http-cookie (~> 1.0.0) - faraday_middleware (1.0.0) + faraday-em_http (1.0.0) + faraday-em_synchrony (1.0.0) + faraday-excon (1.1.0) + faraday-httpclient (1.0.1) + faraday-net_http (1.0.1) + faraday-net_http_persistent (1.2.0) + faraday-patron (1.0.0) + faraday-rack (1.0.0) + faraday_middleware (1.1.0) faraday (~> 1.0) - fastimage (2.2.0) - fastlane (2.167.0) + fastimage (2.2.5) + fastlane (2.195.0) CFPropertyList (>= 2.3, < 4.0.0) - addressable (>= 2.3, < 3.0.0) + addressable (>= 2.8, < 3.0.0) + artifactory (~> 3.0) aws-sdk-s3 (~> 1.0) babosa (>= 1.0.3, < 2.0.0) bundler (>= 1.12.0, < 3.0.0) colored - commander-fastlane (>= 4.4.6, < 5.0.0) + commander (~> 4.6) dotenv (>= 2.1.1, < 3.0.0) emoji_regex (>= 0.1, < 4.0) excon (>= 0.71.0, < 1.0.0) @@ -110,18 +129,20 @@ GEM faraday_middleware (~> 1.0) fastimage (>= 2.1.0, < 3.0.0) gh_inspector (>= 1.1.2, < 2.0.0) - google-api-client (>= 0.37.0, < 0.39.0) - google-cloud-storage (>= 1.15.0, < 2.0.0) - highline (>= 1.7.2, < 2.0.0) + google-apis-androidpublisher_v3 (~> 0.3) + google-apis-playcustomapp_v1 (~> 0.1) + google-cloud-storage (~> 1.31) + highline (~> 2.0) json (< 3.0.0) jwt (>= 2.1.0, < 3) mini_magick (>= 4.9.4, < 5.0.0) multipart-post (~> 2.0.0) + naturally (~> 2.2) + optparse (~> 0.1.1) plist (>= 3.1.0, < 4.0.0) rubyzip (>= 2.0.0, < 3.0.0) security (= 0.1.3) simctl (~> 1.6.3) - slack-notifier (>= 2.0.0, < 3.0.0) terminal-notifier (>= 2.0.0, < 3.0.0) terminal-table (>= 1.4.5, < 2.0.0) tty-screen (>= 0.6.3, < 1.0.0) @@ -130,116 +151,130 @@ GEM xcodeproj (>= 1.13.0, < 2.0.0) xcpretty (~> 0.3.0) xcpretty-travis-formatter (>= 0.0.3) - ffi (1.13.1) + ffi (1.15.4) fourflusher (2.3.1) fuzzy_match (2.0.4) gh_inspector (1.1.3) - google-api-client (0.38.0) + google-apis-androidpublisher_v3 (0.11.0) + google-apis-core (>= 0.4, < 2.a) + google-apis-core (0.4.1) addressable (~> 2.5, >= 2.5.1) - googleauth (~> 0.9) - httpclient (>= 2.8.1, < 3.0) + googleauth (>= 0.16.2, < 2.a) + httpclient (>= 2.8.1, < 3.a) mini_mime (~> 1.0) representable (~> 3.0) - retriable (>= 2.0, < 4.0) - signet (~> 0.12) - google-cloud-core (1.5.0) + retriable (>= 2.0, < 4.a) + rexml + webrick + google-apis-iamcredentials_v1 (0.7.0) + google-apis-core (>= 0.4, < 2.a) + google-apis-playcustomapp_v1 (0.5.0) + google-apis-core (>= 0.4, < 2.a) + google-apis-storage_v1 (0.8.0) + google-apis-core (>= 0.4, < 2.a) + google-cloud-core (1.6.0) google-cloud-env (~> 1.0) google-cloud-errors (~> 1.0) - google-cloud-env (1.4.0) + google-cloud-env (1.5.0) faraday (>= 0.17.3, < 2.0) - google-cloud-errors (1.0.1) - google-cloud-storage (1.29.1) + google-cloud-errors (1.2.0) + google-cloud-storage (1.34.1) addressable (~> 2.5) digest-crc (~> 0.4) - google-api-client (~> 0.33) - google-cloud-core (~> 1.2) - googleauth (~> 0.9) + google-apis-iamcredentials_v1 (~> 0.1) + google-apis-storage_v1 (~> 0.1) + google-cloud-core (~> 1.6) + googleauth (>= 0.16.2, < 2.a) mini_mime (~> 1.0) - googleauth (0.14.0) + googleauth (1.0.0) faraday (>= 0.17.3, < 2.0) jwt (>= 1.4, < 3.0) memoist (~> 0.16) multi_json (~> 1.11) os (>= 0.9, < 2.0) - signet (~> 0.14) - highline (1.7.10) - http-cookie (1.0.3) + signet (>= 0.16, < 2.a) + highline (2.0.3) + http-cookie (1.0.4) domain_name (~> 0.5) httpclient (2.8.3) - i18n (1.8.9) + i18n (1.8.10) concurrent-ruby (~> 1.0) jmespath (1.4.0) - json (2.3.1) - jwt (2.2.2) + json (2.5.1) + jwt (2.3.0) memoist (0.16.2) mini_magick (4.11.0) - mini_mime (1.0.2) + mini_mime (1.1.1) minitest (5.14.4) - molinillo (0.6.6) + molinillo (0.8.0) multi_json (1.15.0) multipart-post (2.0.0) nanaimo (0.3.0) nap (1.1.0) - naturally (2.2.0) + naturally (2.2.1) netrc (0.11.0) + optparse (0.1.1) os (1.1.1) - plist (3.5.0) + plist (3.6.0) public_suffix (4.0.6) - rake (13.0.1) - representable (3.0.4) + rake (13.0.6) + representable (3.1.1) declarative (< 0.1.0) - declarative-option (< 0.2.0) + trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) retriable (3.1.2) + rexml (3.2.5) rouge (2.0.7) - ruby-macho (1.4.0) - ruby2_keywords (0.0.2) - rubyzip (2.3.0) + ruby-macho (2.5.1) + ruby2_keywords (0.0.5) + rubyzip (2.3.2) security (0.1.3) - signet (0.14.0) - addressable (~> 2.3) + signet (0.16.0) + addressable (~> 2.8) faraday (>= 0.17.3, < 2.0) jwt (>= 1.5, < 3.0) multi_json (~> 1.10) simctl (1.6.8) CFPropertyList naturally - slack-notifier (2.3.2) terminal-notifier (2.0.0) terminal-table (1.8.0) unicode-display_width (~> 1.1, >= 1.1.1) - thread_safe (0.3.6) + trailblazer-option (0.1.1) tty-cursor (0.7.1) tty-screen (0.8.1) tty-spinner (0.9.3) tty-cursor (~> 0.7) typhoeus (1.4.0) ethon (>= 0.9.0) - tzinfo (1.2.9) - thread_safe (~> 0.1) + tzinfo (2.0.4) + concurrent-ruby (~> 1.0) uber (0.1.0) unf (0.1.4) unf_ext - unf_ext (0.0.7.7) - unicode-display_width (1.7.0) + unf_ext (0.0.8) + unicode-display_width (1.8.0) + webrick (1.7.0) word_wrap (1.0.0) - xcodeproj (1.19.0) + xcodeproj (1.21.0) CFPropertyList (>= 2.3.3, < 4.0) atomos (~> 0.1.3) claide (>= 1.0.2, < 2.0) colored2 (~> 3.1) nanaimo (~> 0.3.0) + rexml (~> 3.2.4) xcpretty (0.3.0) rouge (~> 2.0.7) - xcpretty-travis-formatter (1.0.0) + xcpretty-travis-formatter (1.0.1) xcpretty (~> 0.2, >= 0.0.7) + zeitwerk (2.4.2) PLATFORMS ruby DEPENDENCIES - cocoapods (~> 1.10.1) + cocoapods (~> 1.11.2) fastlane BUNDLED WITH - 2.2.14 + 2.2.28 diff --git a/changelog.d/4951.build b/changelog.d/4951.build new file mode 100644 index 0000000000..a4d355372f --- /dev/null +++ b/changelog.d/4951.build @@ -0,0 +1 @@ +Bundler: Update CocoaPods and fastlane. \ No newline at end of file From 13a3c28b4b4b856e376bed22f0e372fc364a2160 Mon Sep 17 00:00:00 2001 From: manuroe Date: Tue, 5 Oct 2021 08:46:45 +0200 Subject: [PATCH 21/42] Update MatrixSDKTests/MXCryptoTests.m Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> --- MatrixSDKTests/MXCryptoTests.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MatrixSDKTests/MXCryptoTests.m b/MatrixSDKTests/MXCryptoTests.m index c7a2d0e206..9937b8e4f5 100644 --- a/MatrixSDKTests/MXCryptoTests.m +++ b/MatrixSDKTests/MXCryptoTests.m @@ -2953,8 +2953,8 @@ - (void)testRestoreOlmOutboundKey // - Restart the session MXSession *aliceSession2 = [[MXSession alloc] initWithMatrixRestClient:aliceSession.matrixRestClient]; - [matrixSDKTestsData retain:aliceSession2] - ; + [matrixSDKTestsData retain:aliceSession2]; + [aliceSession close]; [aliceSession2 start:^{ MXOlmOutboundGroupSession *outboundSession = [aliceSession2.crypto.store outboundGroupSessionWithRoomId:roomId]; From 3678e2cd815a3a7b1e300335fcf7d885220160c6 Mon Sep 17 00:00:00 2001 From: manuroe Date: Tue, 5 Oct 2021 08:46:54 +0200 Subject: [PATCH 22/42] Update MatrixSDKTests/Utils/MXSession.swift Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> --- MatrixSDKTests/Utils/MXSession.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MatrixSDKTests/Utils/MXSession.swift b/MatrixSDKTests/Utils/MXSession.swift index 9b5435d25f..b7a8a8b7b7 100644 --- a/MatrixSDKTests/Utils/MXSession.swift +++ b/MatrixSDKTests/Utils/MXSession.swift @@ -47,7 +47,7 @@ extension MXSession { /// - Parameters: /// - orignalSelector: the original method /// - swizzledSelector: the replacing method - private class func swizzleMethods(orignalSelector: Selector, swizzledSelector: Selector) { + private class func swizzleMethods(originalSelector: Selector, swizzledSelector: Selector) { guard let originalMethod = class_getInstanceMethod(MXSession.self, orignalSelector), let swizzledMethod = class_getInstanceMethod(MXSession.self, swizzledSelector) From 3d4cc88a1f32182692846f409962bc827ac51148 Mon Sep 17 00:00:00 2001 From: manuroe Date: Tue, 5 Oct 2021 09:04:11 +0200 Subject: [PATCH 23/42] MatrixSDKTests: Fix Doug's comments --- MatrixSDKTests/MatrixSDKTestsData.m | 2 +- MatrixSDKTests/Utils/MXSession.swift | 6 +++--- MatrixSDKTests/Utils/MXSessionTracker.swift | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/MatrixSDKTests/MatrixSDKTestsData.m b/MatrixSDKTests/MatrixSDKTestsData.m index bf1cad5854..391d64c566 100644 --- a/MatrixSDKTests/MatrixSDKTestsData.m +++ b/MatrixSDKTests/MatrixSDKTestsData.m @@ -1028,7 +1028,7 @@ - (void)retain:(NSObject*)object - (void)release:(NSObject*)object { - [self.retainedObjects addObject:object]; + [self.retainedObjects removeObject:object]; } - (void)releaseRetainedObjects diff --git a/MatrixSDKTests/Utils/MXSession.swift b/MatrixSDKTests/Utils/MXSession.swift index b7a8a8b7b7..b8930999bc 100644 --- a/MatrixSDKTests/Utils/MXSession.swift +++ b/MatrixSDKTests/Utils/MXSession.swift @@ -33,9 +33,9 @@ extension MXSession { /// Start tracking open MXSession instances. class func trackOpenMXSessions() { // Swizzle init and close methods to track active MXSessions - swizzleMethods(orignalSelector: #selector(MXSession.init(matrixRestClient:)), + swizzleMethods(originalSelector: #selector(MXSession.init(matrixRestClient:)), swizzledSelector: #selector(MXSession.trackInit(matrixRestClient:))) - swizzleMethods(orignalSelector: #selector(MXSession.close), + swizzleMethods(originalSelector: #selector(MXSession.close), swizzledSelector: #selector(MXSession.trackClose)) } @@ -49,7 +49,7 @@ extension MXSession { /// - swizzledSelector: the replacing method private class func swizzleMethods(originalSelector: Selector, swizzledSelector: Selector) { guard - let originalMethod = class_getInstanceMethod(MXSession.self, orignalSelector), + let originalMethod = class_getInstanceMethod(MXSession.self, originalSelector), let swizzledMethod = class_getInstanceMethod(MXSession.self, swizzledSelector) else { return } method_exchangeImplementations(originalMethod, swizzledMethod) diff --git a/MatrixSDKTests/Utils/MXSessionTracker.swift b/MatrixSDKTests/Utils/MXSessionTracker.swift index 0e4c02bd1b..8ba3c9e282 100644 --- a/MatrixSDKTests/Utils/MXSessionTracker.swift +++ b/MatrixSDKTests/Utils/MXSessionTracker.swift @@ -60,7 +60,7 @@ class MXSessionTracker { // MARK: - Private /// All open sessions - private var trackedMXSessions = Dictionary() + private var trackedMXSessions = [String: TrackedMXSession]() func trackMXSession(mxSession: MXSession, callStack: [String]) { let trackedMXSession = TrackedMXSession(userDeviceId: mxSession.userDeviceId, callStack: callStack) From e7d91e7d5a211f76c8b82de7078e2159b5251b2d Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Wed, 6 Oct 2021 22:13:50 +0200 Subject: [PATCH 24/42] Fix performance issues with Spaces on very large accounts #4898 - Apply SDK threading model - Some optimisations --- MatrixSDK.xcodeproj/project.pbxproj | 6 + .../Data/Store/MXFileStore/MXFileStore.m | 42 --- MatrixSDK/Data/Store/MXStore.h | 17 - MatrixSDK/Space/MXSpace.swift | 97 +++--- .../Space/MXSpaceNotificationCounter.swift | 165 ++++++--- MatrixSDK/Space/MXSpaceService.swift | 318 ++++++++++++------ MatrixSDK/Space/MXSpaceStore.swift | 124 +++++++ MatrixSDKTests/MXSpaceServiceTest.swift | 23 +- changelog.d/4898.bugfix | 1 + 9 files changed, 547 insertions(+), 246 deletions(-) create mode 100644 MatrixSDK/Space/MXSpaceStore.swift create mode 100644 changelog.d/4898.bugfix diff --git a/MatrixSDK.xcodeproj/project.pbxproj b/MatrixSDK.xcodeproj/project.pbxproj index 12f6ec74c3..0e9616e1e7 100644 --- a/MatrixSDK.xcodeproj/project.pbxproj +++ b/MatrixSDK.xcodeproj/project.pbxproj @@ -651,6 +651,8 @@ 3A7509BC26FC61DF00B85773 /* MXSpaceNotificationCounter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A7509BA26FC61DF00B85773 /* MXSpaceNotificationCounter.swift */; }; 3A7B8D0E267FCF7200D9DD96 /* MXDehydrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A7B8CFD267FCD9B00D9DD96 /* MXDehydrationTests.m */; }; 3A7B8D13267FCF7300D9DD96 /* MXDehydrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A7B8CFD267FCD9B00D9DD96 /* MXDehydrationTests.m */; }; + 3AB5EBB4270B332B0058703A /* MXSpaceStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AB5EBB3270B332B0058703A /* MXSpaceStore.swift */; }; + 3AB5EBB5270B332B0058703A /* MXSpaceStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AB5EBB3270B332B0058703A /* MXSpaceStore.swift */; }; 3AC135D92640335100EE1E74 /* MXDehydrationService.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AC135D72640335100EE1E74 /* MXDehydrationService.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3AC135DA2640335100EE1E74 /* MXDehydrationService.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AC135D72640335100EE1E74 /* MXDehydrationService.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3AC135DB2640335100EE1E74 /* MXDehydrationService.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AC135D82640335100EE1E74 /* MXDehydrationService.m */; }; @@ -2089,6 +2091,7 @@ 3A59A52825A7B1B000DDA1FC /* MXOutboundSessionInfo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MXOutboundSessionInfo.m; sourceTree = ""; }; 3A7509BA26FC61DF00B85773 /* MXSpaceNotificationCounter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MXSpaceNotificationCounter.swift; sourceTree = ""; }; 3A7B8CFD267FCD9B00D9DD96 /* MXDehydrationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MXDehydrationTests.m; sourceTree = ""; }; + 3AB5EBB3270B332B0058703A /* MXSpaceStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXSpaceStore.swift; sourceTree = ""; }; 3AC135D72640335100EE1E74 /* MXDehydrationService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXDehydrationService.h; sourceTree = ""; }; 3AC135D82640335100EE1E74 /* MXDehydrationService.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MXDehydrationService.m; sourceTree = ""; }; 3AC13800264482A100EE1E74 /* MXExportedOlmDevice.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXExportedOlmDevice.h; sourceTree = ""; }; @@ -3875,6 +3878,7 @@ B105CDD5261F54C8006EB204 /* MXSpaceChildContent.m */, 3AF85F9126FC7AE800A9E67B /* MXSpaceNotificationState.swift */, 3A0AF06A2705A11400679D1A /* MXSpaceGraphData.swift */, + 3AB5EBB3270B332B0058703A /* MXSpaceStore.swift */, ); path = Space; sourceTree = ""; @@ -5093,6 +5097,7 @@ 32A1513F1DAF768D00400192 /* MXOlmInboundGroupSession.m in Sources */, 3259CFE626026A6F00C365DB /* MXRestClient+Extensions.swift in Sources */, EC60ED91265CFD3B00B39A4E /* MXRoomSync.m in Sources */, + 3AB5EBB4270B332B0058703A /* MXSpaceStore.swift in Sources */, EC8A53A125B1BC77004E0802 /* MXCallSelectAnswerEventContent.m in Sources */, B14EECE72577F76100448735 /* MXLoginSSOFlow.m in Sources */, 32481A851C03572900782AD3 /* MXRoomAccountData.m in Sources */, @@ -5531,6 +5536,7 @@ B19EC8A3260E134A00543BEC /* MXRoomInitialStateEventBuilder.swift in Sources */, B14EF1CA2397E90400758AF0 /* MXOlmInboundGroupSession.m in Sources */, B14EF1CB2397E90400758AF0 /* MXRoomAccountData.m in Sources */, + 3AB5EBB5270B332B0058703A /* MXSpaceStore.swift in Sources */, B14EF1CC2397E90400758AF0 /* MXEventAnnotationChunk.m in Sources */, B14EF1CD2397E90400758AF0 /* MXRealmEventScanStore.m in Sources */, 181FD5D72660C791008EC084 /* MXLogObjcWrapper.m in Sources */, diff --git a/MatrixSDK/Data/Store/MXFileStore/MXFileStore.m b/MatrixSDK/Data/Store/MXFileStore/MXFileStore.m index e1433372ba..22d4f1c754 100644 --- a/MatrixSDK/Data/Store/MXFileStore/MXFileStore.m +++ b/MatrixSDK/Data/Store/MXFileStore/MXFileStore.m @@ -45,7 +45,6 @@ static NSString *const kMXFileStoreRoomSummaryFile = @"summary"; static NSString *const kMXFileStoreRoomAccountDataFile = @"accountData"; static NSString *const kMXFileStoreRoomReadReceiptsFile = @"readReceipts"; -static NSString *const kMXFileStoreSpaceGraphFile = @"spaceGraph"; static NSUInteger preloadOptions; @@ -1051,11 +1050,6 @@ - (NSString*)readReceiptsFileForRoom:(NSString*)roomId forBackup:(BOOL)backup return [[self folderForRoom:roomId forBackup:backup] stringByAppendingPathComponent:kMXFileStoreRoomReadReceiptsFile]; } -- (NSString*)spaceGraphFileForBackup:(BOOL)backup -{ - return [(backup ? storeBackupPath : storePath) stringByAppendingPathComponent:kMXFileStoreSpaceGraphFile]; -} - - (NSString*)metaDataFileForBackup:(BOOL)backup { if (!backup) @@ -2137,42 +2131,6 @@ - (void)saveReceipts } } -#pragma mark - Spaces graph - -- (BOOL)storeSpaceGraphData:(nonnull MXSpaceGraphData*)graph -{ - NSString *file = [self spaceGraphFileForBackup:NO]; - NSString *backupFile = [self spaceGraphFileForBackup:YES]; - - // Backup the file - if (backupFile && [[NSFileManager defaultManager] fileExistsAtPath:file]) - { - [[NSFileManager defaultManager] moveItemAtPath:file toPath:backupFile error:nil]; - } - - NSError *error = nil; - NSData * data = [NSKeyedArchiver archivedDataWithRootObject:graph requiringSecureCoding:NO error:&error]; - - // Store new data - return [NSKeyedArchiver archiveRootObject:graph toFile:file]; -} - -- (MXSpaceGraphData* _Nullable)loadSpaceGraphData -{ - MXSpaceGraphData *graph = nil; - NSString *file = [self spaceGraphFileForBackup:NO]; - @try - { - graph = [NSKeyedUnarchiver unarchiveObjectWithFile:file]; - } - @catch (NSException *exception) - { - MXLogDebug(@"[MXFileStore] Warning: spaceGraph file has been corrupted"); - } - - return graph; -} - #pragma mark - Async API - (void)asyncUsers:(void (^)(NSArray * _Nonnull))success failure:(nullable void (^)(NSError * _Nonnull))failure diff --git a/MatrixSDK/Data/Store/MXStore.h b/MatrixSDK/Data/Store/MXStore.h index 540c7edb3e..60738a8007 100644 --- a/MatrixSDK/Data/Store/MXStore.h +++ b/MatrixSDK/Data/Store/MXStore.h @@ -519,22 +519,5 @@ success:(nonnull void (^)(NSString * _Nullable filterId))success failure:(nullable void (^)(NSError * _Nullable error))failure; -#pragma mark - Space graph data -/** - Stores the graph of space - - @param graph the data of the space graph - - @return YES if the data has been succesflly stored. - */ -- (BOOL)storeSpaceGraphData:(nonnull MXSpaceGraphData*)graph; - -/** - Loads the graph of space from the store - - @return an instance of `MXSpaceGraphData` if the data has been loaded succesfully. Nil otherwise. - */ -- (MXSpaceGraphData* _Nullable)loadSpaceGraphData; - @end diff --git a/MatrixSDK/Space/MXSpace.swift b/MatrixSDK/Space/MXSpace.swift index 30cb6ee608..8e903696f7 100644 --- a/MatrixSDK/Space/MXSpace.swift +++ b/MatrixSDK/Space/MXSpace.swift @@ -41,27 +41,39 @@ public class MXSpace: NSObject { // MARK: - Properties /// The underlying room - public let room: MXRoom + public let session: MXSession - /// Shortcut to the room roomId - public var spaceId: String { - return self.room.roomId + /// ID of the space (e.g. ID of the underlying room) + public let spaceId: String + + /// Underlynig room of the space + public var room: MXRoom? { + return self.session.room(withRoomId: self.spaceId) } /// Shortcut to the room summary public var summary: MXRoomSummary? { - return self.room.summary + return self.session.roomSummary(withRoomId: self.spaceId) } public private(set) var childSpaces: [MXSpace] = [] public private(set) var childRoomIds: [String] = [] public private(set) var otherMembersId: [String] = [] - public private(set) var membersId: [String] = [] + private let processingQueue: DispatchQueue + private let sdkProcessingQueue: DispatchQueue + private let completionQueue: DispatchQueue + // MARK: - Setup - public init(room: MXRoom) { - self.room = room + public init(roomId: String, session: MXSession) { + self.session = session + self.spaceId = roomId + + self.processingQueue = DispatchQueue(label: "org.matrix.sdk.MXSpace.processingQueue", attributes: .concurrent) + self.sdkProcessingQueue = DispatchQueue.main + self.completionQueue = DispatchQueue.main + super.init() } @@ -71,34 +83,47 @@ public class MXSpace: NSObject { /// - Parameters: /// - completion: A closure called when the operation completes. public func readChildRoomsAndMembers(completion: @escaping () -> Void) { - guard let myUserId = room.mxSession.myUserId else { + guard let room = self.room, let myUserId = room.mxSession.myUserId else { return } - room.state { [weak self] roomState in - roomState?.stateEvents.forEach({ event in - if event.eventType == .spaceChild { - self?.childRoomIds.append(event.stateKey) - } - }) - - self?.room.members { [weak self] response in - guard let members = response.value as? MXRoomMembers else { + self.sdkProcessingQueue.async { + room.state { [weak self] roomState in + guard let self = self else { return } + + self.processingQueue.async { + roomState?.stateEvents.forEach({ event in + if event.eventType == .spaceChild { + self.childRoomIds.append(event.stateKey) + } + }) + + self.sdkProcessingQueue.async { + room.members { [weak self] response in + guard let self = self, let members = response.value as? MXRoomMembers else { + return + } - var otherMembersId: [String] = [] - var membersId: [String] = [] - members.members?.forEach { roomMember in - membersId.append(roomMember.userId) - if roomMember.userId != myUserId { - otherMembersId.append(roomMember.userId) + self.processingQueue.async { + var otherMembersId: [String] = [] + var membersId: [String] = [] + members.members?.forEach { roomMember in + membersId.append(roomMember.userId) + if roomMember.userId != myUserId { + otherMembersId.append(roomMember.userId) + } + } + self.otherMembersId = otherMembersId + + self.completionQueue.async { + completion() + } + } + } } } - self?.otherMembersId = otherMembersId - self?.membersId = membersId - - completion() } } } @@ -127,7 +152,7 @@ public class MXSpace: NSObject { finalViaServers = viaServers } else { // If viaServers is nil use the current homeserver as via server - guard let homeserverName = self.room.mxSession.credentials.homeServerName() else { + guard let homeserverName = self.session.credentials.homeServerName() else { completion(.failure(MXSpaceError.homeserverNameNotFound)) return nil } @@ -144,10 +169,7 @@ public class MXSpace: NSObject { fatalError("[MXSpace] MXSpaceChildContent dictionary cannot be nil") } - return self.room.sendStateEvent(.spaceChild, - content: stateEventContent, - stateKey: roomId, - completion: completion) + return self.room?.sendStateEvent(.spaceChild, content: stateEventContent, stateKey: roomId, completion: completion) } /// Update child spaces using the list of spaces @@ -164,7 +186,7 @@ public class MXSpace: NSObject { /// Update child rooms using the list of direct rooms /// - Parameters: /// - directRoomsPerMember: complete list of direct rooms by member ID - public func updateChildDirectRooms(with directRoomsPerMember: [String : [MXRoom]]) { + public func updateChildDirectRooms(with directRoomsPerMember: [String : [String]]) { self.updateChildRooms(from: self, with: directRoomsPerMember) } @@ -178,12 +200,9 @@ public class MXSpace: NSObject { // MARK: - Private - private func updateChildRooms(from space: MXSpace, with directRoomsPerMember: [String : [MXRoom]]) { + private func updateChildRooms(from space: MXSpace, with directRoomsPerMember: [String : [String]]) { space.otherMembersId.forEach { memberId in - let rooms = directRoomsPerMember[memberId] ?? [] - self.childRoomIds.append(contentsOf: rooms.compactMap({ room in - return room.roomId - })) + self.childRoomIds.append(contentsOf: directRoomsPerMember[memberId] ?? []) } } } diff --git a/MatrixSDK/Space/MXSpaceNotificationCounter.swift b/MatrixSDK/Space/MXSpaceNotificationCounter.swift index d105f445ff..99dad472c5 100644 --- a/MatrixSDK/Space/MXSpaceNotificationCounter.swift +++ b/MatrixSDK/Space/MXSpaceNotificationCounter.swift @@ -16,54 +16,93 @@ import Foundation +// MARK: - MXSpaceNotificationCounter notification constants +extension MXSpaceNotificationCounter { + /// Posted once notification count for all spaces has been updated + public static let didUpdateNotificationCount = Notification.Name("MXSpaceNotificationCounterDidUpdateNotificationCount") +} + /// MXSpaceNotificationCounter compute the number of unread messages for each space @objcMembers public class MXSpaceNotificationCounter: NSObject { // MARK: - Properties + private unowned let session: MXSession + + private let processingQueue: DispatchQueue + private let sdkProcessingQueue: DispatchQueue + private let completionQueue: DispatchQueue + public private(set) var homeNotificationState = MXSpaceNotificationState() private var notificationStatePerSpaceId: [String:MXSpaceNotificationState] = [:] + + // MARK: - Setup + public init(session: MXSession) { + self.session = session + + self.processingQueue = DispatchQueue(label: "org.matrix.sdk.MXSpaceNotificationCounter.processingQueue", attributes: .concurrent) + self.completionQueue = DispatchQueue.main + self.sdkProcessingQueue = DispatchQueue.main + + super.init() + } + // MARK: - Public + /// close the service and free all data public func close() { self.homeNotificationState = MXSpaceNotificationState() self.notificationStatePerSpaceId = [:] } + private class RoomInfo { + let roomId: String + let roomTags: [String: MXRoomTag]? + let highlightCount: UInt + let notificationCount: UInt + let isDirect: Bool + let membership: MXMembership + + init(with room: MXRoom) { + self.roomId = room.roomId + self.roomTags = room.accountData.tags + + let summary = room.summary + self.highlightCount = summary?.highlightCount ?? 0 + self.notificationCount = summary?.notificationCount ?? 0 + self.isDirect = summary?.isDirect ?? false + self.membership = summary?.membership ?? .unknown + } + } + /// Compute the notification count for every spaces - /// - Parameters: - /// - spaces: list of spaces of the current sessiom - /// - rooms: list of rooms of the current session - /// - ancestorsPerRoomId: List of IDs of the ancestors (recursive parents) for each room ID - public func computeNotificationCount(for spaces:[MXSpace], with rooms:[MXRoom], ancestorsPerRoomId: [String: Set]) { + public func computeNotificationCount() { let startDate = Date() MXLog.debug("[Spaces] computeNotificationCount started") - - var homeNotificationState = MXSpaceNotificationState() - var notificationStatePerSpaceId: [String:MXSpaceNotificationState] = [:] - for room in rooms { - guard room.summary.roomType != .space else { - continue + self.sdkProcessingQueue.async { + let roomsIds: [String] = self.session.rooms.compactMap { room in + room.roomId } - let notificationState = self.notificationState(forRoomWithId: room) + let spaceIds: [String] = self.session.spaceService.rootSpaceSummaries.compactMap { summary in + summary.roomId + } - homeNotificationState += notificationState - for space in spaces { - if ancestorsPerRoomId[room.roomId]?.contains(space.spaceId) ?? false { - let storedState = notificationStatePerSpaceId[space.spaceId] ?? MXSpaceNotificationState() - notificationStatePerSpaceId[space.spaceId] = storedState + notificationState + self.computeNotificationCount(for: spaceIds, with: roomsIds, at: 0, output: ComputeDataResult(), ancestorsPerRoomId: self.session.spaceService.ancestorsPerRoomId) { result in + + self.homeNotificationState = result.homeNotificationState + self.notificationStatePerSpaceId = result.notificationStatePerSpaceId + + MXLog.debug("[Spaces] computeNotificationCount ended after \(Date().timeIntervalSince(startDate))s") + + self.completionQueue.async { + NotificationCenter.default.post(name: MXSpaceNotificationCounter.didUpdateNotificationCount, object: self) } } } - - self.homeNotificationState = homeNotificationState - self.notificationStatePerSpaceId = notificationStatePerSpaceId - - MXLog.debug("[Spaces] computeNotificationCount ended after \(Date().timeIntervalSince(startDate))s") } /// Notification state for a given space @@ -90,30 +129,78 @@ public class MXSpaceNotificationCounter: NSObject { // MARK: - Private - private func notificationState(forRoomWithId room: MXRoom) -> MXSpaceNotificationState { + private class ComputeDataResult { + var homeNotificationState: MXSpaceNotificationState = MXSpaceNotificationState() + var notificationStatePerSpaceId: [String:MXSpaceNotificationState] = [:] + } + + private func computeNotificationCount(for spaceIds:[String], with roomIds:[String], at index: Int, output: ComputeDataResult, ancestorsPerRoomId: [String: Set], completion: @escaping (_ result: ComputeDataResult) -> Void) { + guard index < roomIds.count else { + self.completionQueue.async { + completion(output) + } + return + } + + self.processingQueue.async { + + let roomId = roomIds[index] + var roomInfo: RoomInfo? + + self.sdkProcessingQueue.sync { + guard let room = self.session.room(withRoomId: roomId), let summary = room.summary, summary.roomType != .space else { + return + } + + roomInfo = RoomInfo(with: room) + } + + guard let roomInfo = roomInfo else { + self.computeNotificationCount(for: spaceIds, with: roomIds, at: index + 1, output: output, ancestorsPerRoomId: ancestorsPerRoomId, completion: completion) + return + } + + let notificationState = self.notificationState(for: roomInfo) + + output.homeNotificationState += notificationState + for spaceId in spaceIds { + if ancestorsPerRoomId[roomInfo.roomId]?.contains(spaceId) ?? false { + let storedState = output.notificationStatePerSpaceId[spaceId] ?? MXSpaceNotificationState() + output.notificationStatePerSpaceId[spaceId] = storedState + notificationState + } + } + + self.computeNotificationCount(for: spaceIds, with: roomIds, at: index + 1, output: output, ancestorsPerRoomId: ancestorsPerRoomId, completion: completion) + } + } + + private func notificationState(for roomInfo: RoomInfo) -> MXSpaceNotificationState { let notificationState = MXSpaceNotificationState() - guard let summary = room.summary else { - return notificationState + + var isMentionOnly: Bool = false + + self.sdkProcessingQueue.sync { + isMentionOnly = self.isRoomMentionsOnly(roomInfo) } - let notificationCount = self.isRoomMentionsOnly(summary) ? summary.highlightCount : summary.notificationCount + let notificationCount = isMentionOnly ? roomInfo.highlightCount : roomInfo.notificationCount if notificationCount > 0 { - let tags = room.accountData.tags + let tags = roomInfo.roomTags if tags != nil, tags?[kMXRoomTagFavourite] != nil { - notificationState.favouriteMissedDiscussionsCount += summary.notificationCount - notificationState.favouriteMissedDiscussionsHighlightedCount += summary.highlightCount + notificationState.favouriteMissedDiscussionsCount += roomInfo.notificationCount + notificationState.favouriteMissedDiscussionsHighlightedCount += roomInfo.highlightCount } - if summary.isDirect { - notificationState.directMissedDiscussionsCount += summary.notificationCount - notificationState.directMissedDiscussionsHighlightedCount += summary.highlightCount + if roomInfo.isDirect { + notificationState.directMissedDiscussionsCount += roomInfo.notificationCount + notificationState.directMissedDiscussionsHighlightedCount += roomInfo.highlightCount } else if tags?.isEmpty ?? true || tags?[kMXRoomTagFavourite] != nil { - notificationState.groupMissedDiscussionsCount += summary.notificationCount - notificationState.groupMissedDiscussionsHighlightedCount += summary.highlightCount + notificationState.groupMissedDiscussionsCount += roomInfo.notificationCount + notificationState.groupMissedDiscussionsHighlightedCount += roomInfo.highlightCount } - } else if summary.membership == .invite { - if room.isDirect { + } else if roomInfo.membership == .invite { + if roomInfo.isDirect { notificationState.directMissedDiscussionsHighlightedCount += 1 } else { notificationState.groupMissedDiscussionsHighlightedCount += 1 @@ -123,13 +210,13 @@ public class MXSpaceNotificationCounter: NSObject { return notificationState } - private func isRoomMentionsOnly(_ summary: MXRoomSummary) -> Bool { - guard let rules = summary.mxSession?.notificationCenter?.rules?.global?.room as? [MXPushRule] else { + private func isRoomMentionsOnly(_ roomInfo: RoomInfo) -> Bool { + guard let rules = self.session.notificationCenter?.rules?.global?.room as? [MXPushRule] else { return false } for rule in rules { - guard rule.ruleId == summary.roomId, let ruleActions = rule.actions as? [MXPushRuleAction] else { + guard rule.ruleId == roomInfo.roomId, let ruleActions = rule.actions as? [MXPushRuleAction] else { continue } diff --git a/MatrixSDK/Space/MXSpaceService.swift b/MatrixSDK/Space/MXSpaceService.swift index a072ebf4b5..8793f8df55 100644 --- a/MatrixSDK/Space/MXSpaceService.swift +++ b/MatrixSDK/Space/MXSpaceService.swift @@ -37,6 +37,9 @@ extension MXSpaceServiceError: CustomNSError { // MARK: - MXSpaceService notification constants extension MXSpaceService { + /// Posted once the first graph as been built or loaded + public static let didInitialised = Notification.Name("MXSpaceServiceDidInitialised") + /// Posted once the graph of rooms is up and running public static let didBuildSpaceGraph = Notification.Name("MXSpaceServiceDidBuildSpaceGraph") } @@ -56,6 +59,7 @@ public class MXSpaceService: NSObject { private let roomTypeMapper: MXRoomTypeMapper private let processingQueue: DispatchQueue + private let sdkProcessingQueue: DispatchQueue private let completionQueue: DispatchQueue private var graph: MXSpaceGraphData = MXSpaceGraphData() { @@ -71,7 +75,7 @@ public class MXSpaceService: NSObject { private var isGraphBuilding = false; - public let notificationCounter = MXSpaceNotificationCounter() + public let notificationCounter: MXSpaceNotificationCounter public var rootSpaceSummaries: [MXRoomSummary] { return self.graph.rootSpaceIds.compactMap { spaceId in @@ -85,14 +89,30 @@ public class MXSpaceService: NSObject { private var sessionStateDidChangeObserver: Any? private var sessionDidSyncObserver: Any? + + public var ancestorsPerRoomId: [String:Set] { + return graph.ancestorsPerRoomId + } + + public private(set) var isInitialised = false { + didSet { + if !oldValue && isInitialised { + self.completionQueue.async { + NotificationCenter.default.post(name: MXSpaceService.didInitialised, object: self) + } + } + } + } // MARK: - Setup public init(session: MXSession) { self.session = session + self.notificationCounter = MXSpaceNotificationCounter(session: session) self.roomTypeMapper = MXRoomTypeMapper(defaultRoomType: .room) self.processingQueue = DispatchQueue(label: "org.matrix.sdk.MXSpaceService.processingQueue", attributes: .concurrent) self.completionQueue = DispatchQueue.main + self.sdkProcessingQueue = DispatchQueue.main super.init() @@ -105,7 +125,7 @@ public class MXSpaceService: NSObject { // MARK: - Public - /// cloase the service and free all data + /// close the service and free all data public func close() { self.isGraphBuilding = true self.graph = MXSpaceGraphData() @@ -117,14 +137,17 @@ public class MXSpaceService: NSObject { } /// Loads graph from the given store - /// - Parameters: - /// - store: store used to load graph - public func loadData(from store: MXStore) { + public func loadData() { self.processingQueue.async { - self.graph = store.loadSpaceGraphData?() ?? MXSpaceGraphData() - - self.completionQueue.async { - NotificationCenter.default.post(name: MXSpaceService.didBuildSpaceGraph, object: self) + let store = MXSpaceStore(session: self.session) + if let loadedGraph = store.loadSpaceGraphData() { + self.graph = loadedGraph + + self.completionQueue.async { + self.isInitialised = true + self.notificationCounter.computeNotificationCount() + NotificationCenter.default.post(name: MXSpaceService.didBuildSpaceGraph, object: self) + } } } } @@ -147,9 +170,7 @@ public class MXSpaceService: NSObject { } /// Build the graph of rooms - /// - Parameters: - /// - rooms: the complete list of rooms and spaces - public func buildGraph(with rooms:[MXRoom]) { + public func buildGraph() { guard !self.isGraphBuilding && self.graphUpdateEnabled else { MXLog.debug("[Spaces] buildGraph aborted: graph is building or disabled") self.needsUpdate = true @@ -162,71 +183,42 @@ public class MXSpaceService: NSObject { let startDate = Date() MXLog.debug("[Spaces] buildGraph started") - let output = PrepareDataResult() - MXLog.debug("[Spaces] preparing data for \(rooms.count) rooms") - self.prepareData(with: rooms, index: 0, output: output) { result in - MXLog.debug("[Spaces] data prepared") - var parentIdsPerRoomId: [String : Set] = [:] - output.spaces.forEach { space in - space.updateChildSpaces(with: output.spacesPerId) - space.updateChildDirectRooms(with: output.directRooms) - space.childRoomIds.forEach { roomId in - var parentIds = parentIdsPerRoomId[roomId] ?? Set() - parentIds.insert(space.spaceId) - parentIdsPerRoomId[roomId] = parentIds - } - space.childSpaces.forEach { childSpace in - var parentIds = parentIdsPerRoomId[childSpace.spaceId] ?? Set() - parentIds.insert(space.spaceId) - parentIdsPerRoomId[childSpace.spaceId] = parentIds - } - } - - let rootSpaces = output.spaces.filter { space in - return parentIdsPerRoomId[space.spaceId] == nil - } - - var ancestorsPerRoomId: [String: Set] = [:] - var descendantsPerRoomId: [String: Set] = [:] - rootSpaces.forEach { space in - self.buildRoomHierarchy(with: space, visitedSpaceIds: [], ancestorsPerRoomId: &ancestorsPerRoomId, descendantsPerRoomId: &descendantsPerRoomId) - } - - var orphanedRoomIds: Set = Set() - var orphanedDirectRoomIds: Set = Set() - for room in rooms { - if !room.isDirect && parentIdsPerRoomId[room.roomId] == nil { - orphanedRoomIds.insert(room.roomId) - } else if room.isDirect && parentIdsPerRoomId[room.roomId] == nil { - orphanedDirectRoomIds.insert(room.roomId) - } + var directRoomIds = Set() + let roomIds: [String] = self.session.rooms.compactMap { room in + if room.isDirect { + directRoomIds.insert(room.roomId) } - - self.graph = MXSpaceGraphData( - spaceRoomIds: output.spaces.map({ space in - space.spaceId - }), - parentIdsPerRoomId: parentIdsPerRoomId, - ancestorsPerRoomId: ancestorsPerRoomId, - descendantsPerRoomId: descendantsPerRoomId, - rootSpaceIds: rootSpaces.map({ space in - space.spaceId - }), - orphanedRoomIds: orphanedRoomIds, - orphanedDirectRoomIds: orphanedDirectRoomIds) - - if !(self.session.store?.store?(self.graph) ?? false) { - MXLog.error("[Spaces] buildGraph: failed to store space graph") + return room.roomId + } + + let output = PrepareDataResult() + MXLog.debug("[Spaces] preparing data for \(roomIds.count) rooms") + self.prepareData(with: roomIds, index: 0, output: output) { result in + while !output.computingSpaces.isEmpty { + sleep(1) } - // TODO improve updateNotificationsCount and call the method to all spaces once subspaces will be supported - self.notificationCounter.computeNotificationCount(for: rootSpaces, with: rooms, ancestorsPerRoomId: ancestorsPerRoomId) - - MXLog.debug("[Spaces] buildGraph ended after \(Date().timeIntervalSince(startDate))s") + MXLog.debug("[Spaces] data prepared in \(Date().timeIntervalSince(startDate))") - self.completionQueue.async { + self.computSpaceGraph(with: result, roomIds: roomIds, directRoomIds: directRoomIds) { graph in + self.graph = graph + + MXLog.debug("[Spaces] buildGraph ended after \(Date().timeIntervalSince(startDate))s") + self.isGraphBuilding = false + self.isInitialised = true + NotificationCenter.default.post(name: MXSpaceService.didBuildSpaceGraph, object: self) + + self.processingQueue.async { + let store = MXSpaceStore(session: self.session) + if !store.store(spaceGraphData: self.graph) { + MXLog.error("[Spaces] buildGraph: failed to store space graph") + } + + // TODO improve updateNotificationsCount and call the method to all spaces once subspaces will be supported + self.notificationCounter.computeNotificationCount() + } } } } @@ -241,7 +233,7 @@ public class MXSpaceService: NSObject { return self.session.createRoom(parameters: parameters) { (response) in switch response { case .success(let room): - let space: MXSpace = MXSpace(room: room) + let space: MXSpace = MXSpace(roomId: room.roomId, session:self.session) self.completionQueue.async { completion(.success(space)) } @@ -369,11 +361,11 @@ public class MXSpaceService: NSObject { private func registerNotificationObservers() { self.sessionStateDidChangeObserver = NotificationCenter.default.addObserver(forName: NSNotification.Name.mxSessionStateDidChange, object: session, queue: nil) { [weak self] notification in - guard let session = self?.session, session.state == .storeDataReady, let store = self?.session.store else { + guard let session = self?.session, session.state == .storeDataReady else { return } - self?.loadData(from: store) + self?.loadData() } self.sessionDidSyncObserver = NotificationCenter.default.addObserver(forName: NSNotification.Name.mxSessionDidSync, object: session, queue: nil) { [weak self] notification in @@ -386,7 +378,7 @@ public class MXSpaceService: NSObject { return } - self.buildGraph(with: self.session.rooms) + self.buildGraph() } } @@ -495,48 +487,164 @@ public class MXSpaceService: NSObject { } private class PrepareDataResult { + var isPreparingData = true var spaces: [MXSpace] = [] var spacesPerId: [String : MXSpace] = [:] - var roomsPerId: [String : MXRoom] = [:] - var directRooms: [String: [MXRoom]] = [:] + var directRoomIdsPerMemberId: [String: [String]] = [:] + var computingSpaces: Set = Set() + var computingDirectRooms: Set = Set() + var isComputing: Bool { + return !self.computingSpaces.isEmpty || !self.computingDirectRooms.isEmpty + } } - private func prepareData(with rooms:[MXRoom], index: Int, output: PrepareDataResult, completion: @escaping (_ result: PrepareDataResult) -> Void) { + private func prepareData(with roomIds:[String], index: Int, output: PrepareDataResult, completion: @escaping (_ result: PrepareDataResult) -> Void) { self.processingQueue.async { - guard index < rooms.count else { - completion(output) + guard index < roomIds.count else { + self.completionQueue.async { + output.isPreparingData = false + if !output.isComputing { + completion(output) + } + } return } - let room = rooms[index] - if let space = room.toSpace() { - space.readChildRoomsAndMembers { - output.spaces.append(space) - output.spacesPerId[space.spaceId] = space - - self.prepareData(with: rooms, index: index+1, output: output, completion: completion) + var room: MXRoom? + var space: MXSpace? + var isRoomDirect = false + var directUserId: String? + self.sdkProcessingQueue.sync { + room = self.session.room(withRoomId: roomIds[index]) + + if let room = room { + space = self.spacesPerId[room.roomId] ?? room.toSpace() + isRoomDirect = room.isDirect + directUserId = room.directUserId } - } else if room.isDirect { - room.members { response in - guard let members = response.value as? MXRoomMembers else { - self.prepareData(with: rooms, index: index+1, output: output, completion: completion) - return + } + + guard let room = room else { + self.prepareData(with: roomIds, index: index+1, output: output, completion: completion) + return + } + + if let space = space { + output.computingSpaces.insert(space.spaceId) + space.readChildRoomsAndMembers { + output.computingSpaces.remove(space.spaceId) + if !output.isPreparingData && !output.isComputing { + completion(output) } - - let membersId = members.members?.compactMap({ roomMember in - return roomMember.userId != self.session.myUserId ? roomMember.userId : nil - }) ?? [] - - membersId.forEach { memberId in - var rooms = output.directRooms[memberId] ?? [] - rooms.append(room) - output.directRooms[memberId] = rooms + } + output.spaces.append(space) + output.spacesPerId[space.spaceId] = space + + self.prepareData(with: roomIds, index: index+1, output: output, completion: completion) + } else if isRoomDirect { + if let directUserId = directUserId { + var rooms = output.directRoomIdsPerMemberId[directUserId] ?? [] + rooms.append(room.roomId) + output.directRoomIdsPerMemberId[directUserId] = rooms + self.prepareData(with: roomIds, index: index+1, output: output, completion: completion) + } else { + self.sdkProcessingQueue.async { + output.computingDirectRooms.insert(room.roomId) + + room.members { response in + guard let members = response.value as? MXRoomMembers else { + self.prepareData(with: roomIds, index: index+1, output: output, completion: completion) + return + } + + let membersId = members.members?.compactMap({ roomMember in + return roomMember.userId != self.session.myUserId ? roomMember.userId : nil + }) ?? [] + + assert(membersId.count == 1) + + self.processingQueue.async { + membersId.forEach { memberId in + var rooms = output.directRoomIdsPerMemberId[memberId] ?? [] + rooms.append(room.roomId) + output.directRoomIdsPerMemberId[memberId] = rooms + } + + output.computingDirectRooms.remove(room.roomId) + if !output.isPreparingData && !output.isComputing { + completion(output) + } + } + } + + self.prepareData(with: roomIds, index: index+1, output: output, completion: completion) } - self.prepareData(with: rooms, index: index+1, output: output, completion: completion) } } else { - output.roomsPerId[room.roomId] = room - self.prepareData(with: rooms, index: index+1, output: output, completion: completion) + self.prepareData(with: roomIds, index: index+1, output: output, completion: completion) + } + } + } + + private func computSpaceGraph(with result: PrepareDataResult, roomIds: [String], directRoomIds: Set, completion: @escaping (_ graph: MXSpaceGraphData) -> Void) { + let startDate = Date() + MXLog.debug("[Spaces] started computSpaceGraph") + + self.processingQueue.async { + var parentIdsPerRoomId: [String : Set] = [:] + result.spaces.forEach { space in + space.updateChildSpaces(with: result.spacesPerId) + space.updateChildDirectRooms(with: result.directRoomIdsPerMemberId) + space.childRoomIds.forEach { roomId in + var parentIds = parentIdsPerRoomId[roomId] ?? Set() + parentIds.insert(space.spaceId) + parentIdsPerRoomId[roomId] = parentIds + } + space.childSpaces.forEach { childSpace in + var parentIds = parentIdsPerRoomId[childSpace.spaceId] ?? Set() + parentIds.insert(space.spaceId) + parentIdsPerRoomId[childSpace.spaceId] = parentIds + } + } + + let rootSpaces = result.spaces.filter { space in + return parentIdsPerRoomId[space.spaceId] == nil + } + + var ancestorsPerRoomId: [String: Set] = [:] + var descendantsPerRoomId: [String: Set] = [:] + rootSpaces.forEach { space in + self.buildRoomHierarchy(with: space, visitedSpaceIds: [], ancestorsPerRoomId: &ancestorsPerRoomId, descendantsPerRoomId: &descendantsPerRoomId) + } + + var orphanedRoomIds: Set = Set() + var orphanedDirectRoomIds: Set = Set() + for roomId in roomIds { + let isRoomDirect = directRoomIds.contains(roomId) + if !isRoomDirect && parentIdsPerRoomId[roomId] == nil { + orphanedRoomIds.insert(roomId) + } else if isRoomDirect && parentIdsPerRoomId[roomId] == nil { + orphanedDirectRoomIds.insert(roomId) + } + } + + let graph = MXSpaceGraphData( + spaceRoomIds: result.spaces.map({ space in + space.spaceId + }), + parentIdsPerRoomId: parentIdsPerRoomId, + ancestorsPerRoomId: ancestorsPerRoomId, + descendantsPerRoomId: descendantsPerRoomId, + rootSpaceIds: rootSpaces.map({ space in + space.spaceId + }), + orphanedRoomIds: orphanedRoomIds, + orphanedDirectRoomIds: orphanedDirectRoomIds) + + MXLog.debug("[Spaces] space graph computed in \(Date().timeIntervalSince(startDate))s") + + self.completionQueue.async { + completion(graph) } } } @@ -595,6 +703,6 @@ extension MXRoom { guard let summary = self.summary, summary.roomType == .space else { return nil } - return MXSpace(room: self) + return MXSpace(roomId: self.roomId, session: self.mxSession) } } diff --git a/MatrixSDK/Space/MXSpaceStore.swift b/MatrixSDK/Space/MXSpaceStore.swift new file mode 100644 index 0000000000..47917cb29e --- /dev/null +++ b/MatrixSDK/Space/MXSpaceStore.swift @@ -0,0 +1,124 @@ +// +// Copyright 2021 The Matrix.org Foundation C.I.C +// +// 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 + +/// `MXSpaceStore` is used to store the spaces related data into a permanent store +class MXSpaceStore { + + // MARK: - Constants + + private enum Constants { + static let fileStoreFolder = "MXSpaceStore" + static let fileStoreGraphFile = "graph" + static let backupFileExtension = "backup" + } + + // MARK: - Properties + + private let userId: String + private var storeUrl: URL? + + // MARK - Setup + + init(session: MXSession) { + self.userId = session.myUserId + self.setUpStoragePaths() + } + + /// Stores the given graph + /// - Parameters: + /// - spaceGraphData: space graph to be stored + /// - Returns: `true` if the data has been stored properly.`false` otherwise + func store(spaceGraphData: MXSpaceGraphData) -> Bool { + guard let storeUrl = self.storeUrl else { + MXLog.error("[MXSpaceStore] storeSpaceGraphData failed: storeUrl not defined") + return false + } + + let fileUrl = storeUrl.appendingPathComponent(Constants.fileStoreGraphFile) + let backupUrl = fileUrl.appendingPathExtension(Constants.backupFileExtension) + + if FileManager.default.fileExists(atPath: fileUrl.path) { + do { + if FileManager.default.fileExists(atPath: backupUrl.path) { + try FileManager.default.removeItem(at: backupUrl) + } + try FileManager.default.moveItem(at: fileUrl, to: backupUrl) + } catch { + MXLog.error("[MXSpaceStore] storeSpaceGraphData failed to move graph to backup: \(error)") + } + } + + return NSKeyedArchiver.archiveRootObject(spaceGraphData, toFile: fileUrl.path) + } + + /// Loads graph data from store + /// - Returns:an instance of `MXSpaceGraphData` if the data has been restored succesfully. `nil` otherwise + func loadSpaceGraphData() -> MXSpaceGraphData? { + guard let storeUrl = self.storeUrl else { + MXLog.error("[MXSpaceStore] loadSpaceGraphData failed: storeUrl not defined") + return nil + } + + let fileUrl = storeUrl.appendingPathComponent(Constants.fileStoreGraphFile) + + do { + guard let graph = try? NSKeyedUnarchiver.unarchiveObject(withFile: fileUrl.path) as? MXSpaceGraphData else { + MXLog.warning("[MXSpaceStore] loadSpaceGraphData found no archived graph") + return nil + } + + return graph + } catch { + MXLog.warning("[MXSpaceStore] loadSpaceGraphData failed with error: \(error)") + } + + return nil + } + + // MARK - Private + + private func setUpStoragePaths() { + var cacheUrl: URL? + + if let applicationGroupIdentifier = MXSDKOptions.sharedInstance().applicationGroupIdentifier { + cacheUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: applicationGroupIdentifier) + } else { + let cacheDirList = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true) + cacheUrl = URL(fileURLWithPath: cacheDirList[0]) + } + + guard let cacheUrl = cacheUrl else { + MXLog.error("[MXSpaceStore] setUpStoragePaths was unable to define cache URL") + return + } + + let storeUrl = cacheUrl.appendingPathComponent(Constants.fileStoreFolder).appendingPathComponent(self.userId) + + var isDirectory: ObjCBool = false + if !FileManager.default.fileExists(atPath: storeUrl.path, isDirectory: &isDirectory) { + do { + try FileManager.default.createDirectory(at: storeUrl, withIntermediateDirectories: true, attributes: nil) + self.storeUrl = storeUrl + } catch { + MXLog.error("[MXSpaceStore] setUpStoragePaths was unable to create space storage folder: \(error)") + } + } else { + self.storeUrl = storeUrl + } + } +} diff --git a/MatrixSDKTests/MXSpaceServiceTest.swift b/MatrixSDKTests/MXSpaceServiceTest.swift index 83ff55fd28..f16dc024e3 100644 --- a/MatrixSDKTests/MXSpaceServiceTest.swift +++ b/MatrixSDKTests/MXSpaceServiceTest.swift @@ -140,7 +140,12 @@ class MXSpaceServiceTest: XCTestCase { XCTAssert(summary.membersCount.members == 1, "Bob must be the only one") // Check if room state match space creation parameters - space.room.state { (roomState) in + guard let room = space.room else { + XCTFail("Space should have a room") + return + } + + room.state { (roomState) in guard let roomState = roomState else { XCTFail("Room should have a room state") return @@ -177,7 +182,7 @@ class MXSpaceServiceTest: XCTestCase { case .success(let space): // Wait topic update - self.waitRoomSummaryUpdate(for: space.room.roomId) { _ in + self.waitRoomSummaryUpdate(for: space.spaceId) { _ in guard let summary = space.summary else { XCTFail("Space summary cannot be nil") return @@ -188,8 +193,13 @@ class MXSpaceServiceTest: XCTestCase { XCTAssertTrue(summary.displayname == expectedSpaceName) XCTAssertTrue(summary.topic == expectedSpaceTopic) + guard let room = space.room else { + XCTFail("Space should have a room") + return + } + // Check if room state match space creation parameters - space.room.state { (roomState) in + room.state { (roomState) in guard let roomState = roomState else { XCTFail("Room should have a room state") return @@ -251,8 +261,13 @@ class MXSpaceServiceTest: XCTestCase { return } + guard let room = foundRootSpace.room else { + XCTFail("Space should have a room") + return + } + // Check if space A contains the space child state event for space B - foundRootSpace.room.state({ (roomState) in + room.state({ (roomState) in let stateEvent = roomState?.stateEvents(with: .spaceChild)?.first diff --git a/changelog.d/4898.bugfix b/changelog.d/4898.bugfix new file mode 100644 index 0000000000..e2fe119500 --- /dev/null +++ b/changelog.d/4898.bugfix @@ -0,0 +1 @@ +Apply threading model for Spaces and cache space graph \ No newline at end of file From 43137c753f2082c0e933e33a8f1e59af17c79f44 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Thu, 7 Oct 2021 09:44:02 +0200 Subject: [PATCH 25/42] Fix performance issues with Spaces on very large accounts #4898 - Update after review --- MatrixSDK.xcodeproj/project.pbxproj | 6 + MatrixSDK/MXSession.m | 3 + MatrixSDK/Space/MXSpaceFileStore.swift | 125 ++++++ .../Space/MXSpaceNotificationCounter.swift | 4 +- MatrixSDK/Space/MXSpaceService.swift | 358 +++++++++--------- MatrixSDK/Space/MXSpaceStore.swift | 100 +---- 6 files changed, 319 insertions(+), 277 deletions(-) create mode 100644 MatrixSDK/Space/MXSpaceFileStore.swift diff --git a/MatrixSDK.xcodeproj/project.pbxproj b/MatrixSDK.xcodeproj/project.pbxproj index 0e9616e1e7..4b38bf8944 100644 --- a/MatrixSDK.xcodeproj/project.pbxproj +++ b/MatrixSDK.xcodeproj/project.pbxproj @@ -653,6 +653,8 @@ 3A7B8D13267FCF7300D9DD96 /* MXDehydrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A7B8CFD267FCD9B00D9DD96 /* MXDehydrationTests.m */; }; 3AB5EBB4270B332B0058703A /* MXSpaceStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AB5EBB3270B332B0058703A /* MXSpaceStore.swift */; }; 3AB5EBB5270B332B0058703A /* MXSpaceStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AB5EBB3270B332B0058703A /* MXSpaceStore.swift */; }; + 3AB5EBB7270ED1C00058703A /* MXSpaceFileStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AB5EBB6270ED1C00058703A /* MXSpaceFileStore.swift */; }; + 3AB5EBB8270ED1C00058703A /* MXSpaceFileStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AB5EBB6270ED1C00058703A /* MXSpaceFileStore.swift */; }; 3AC135D92640335100EE1E74 /* MXDehydrationService.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AC135D72640335100EE1E74 /* MXDehydrationService.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3AC135DA2640335100EE1E74 /* MXDehydrationService.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AC135D72640335100EE1E74 /* MXDehydrationService.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3AC135DB2640335100EE1E74 /* MXDehydrationService.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AC135D82640335100EE1E74 /* MXDehydrationService.m */; }; @@ -2092,6 +2094,7 @@ 3A7509BA26FC61DF00B85773 /* MXSpaceNotificationCounter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MXSpaceNotificationCounter.swift; sourceTree = ""; }; 3A7B8CFD267FCD9B00D9DD96 /* MXDehydrationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MXDehydrationTests.m; sourceTree = ""; }; 3AB5EBB3270B332B0058703A /* MXSpaceStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXSpaceStore.swift; sourceTree = ""; }; + 3AB5EBB6270ED1C00058703A /* MXSpaceFileStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXSpaceFileStore.swift; sourceTree = ""; }; 3AC135D72640335100EE1E74 /* MXDehydrationService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXDehydrationService.h; sourceTree = ""; }; 3AC135D82640335100EE1E74 /* MXDehydrationService.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MXDehydrationService.m; sourceTree = ""; }; 3AC13800264482A100EE1E74 /* MXExportedOlmDevice.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXExportedOlmDevice.h; sourceTree = ""; }; @@ -3879,6 +3882,7 @@ 3AF85F9126FC7AE800A9E67B /* MXSpaceNotificationState.swift */, 3A0AF06A2705A11400679D1A /* MXSpaceGraphData.swift */, 3AB5EBB3270B332B0058703A /* MXSpaceStore.swift */, + 3AB5EBB6270ED1C00058703A /* MXSpaceFileStore.swift */, ); path = Space; sourceTree = ""; @@ -5141,6 +5145,7 @@ 3259CD541DF860C300186944 /* MXRealmCryptoStore.m in Sources */, EC60EDAA265CFE3B00B39A4E /* MXRoomSyncTimeline.m in Sources */, EC8A53E225B1BCC6004E0802 /* MXThirdPartyUserInstance.m in Sources */, + 3AB5EBB7270ED1C00058703A /* MXSpaceFileStore.swift in Sources */, 321B41401E09937E009EEEC7 /* MXRoomSummary.m in Sources */, 32CAB1081A91EA34008C5BB9 /* MXPushRuleRoomMemberCountConditionChecker.m in Sources */, 3245A7511AF7B2930001D8A7 /* MXCall.m in Sources */, @@ -5580,6 +5585,7 @@ EC8A53E725B1BCC6004E0802 /* MXThirdPartyProtocol.m in Sources */, B19A30D724042F2700FB6F35 /* MXSelfVerifyingMasterKeyNotTrustedQRCodeData.m in Sources */, B14EF1EA2397E90400758AF0 /* MXRealmMediaScan.m in Sources */, + 3AB5EBB8270ED1C00058703A /* MXSpaceFileStore.swift in Sources */, B14EF1EB2397E90400758AF0 /* MXRoomOperation.m in Sources */, B14EF1EC2397E90400758AF0 /* MXCryptoAlgorithms.m in Sources */, B14EF1ED2397E90400758AF0 /* MXIdentityServerHashDetails.m in Sources */, diff --git a/MatrixSDK/MXSession.m b/MatrixSDK/MXSession.m index 79f58ec2f0..d9a9e07505 100644 --- a/MatrixSDK/MXSession.m +++ b/MatrixSDK/MXSession.m @@ -663,6 +663,9 @@ - (void)handleSyncResponse:(MXSyncResponse *)syncResponse MXLogDebug(@"[MXSession] Next sync token: %@", syncResponse.nextBatch); self.store.eventStreamToken = syncResponse.nextBatch; + // Propagate sync response to the associated space service + [self.spaceService handleSyncResponse:syncResponse]; + if (completion) { completion(); diff --git a/MatrixSDK/Space/MXSpaceFileStore.swift b/MatrixSDK/Space/MXSpaceFileStore.swift new file mode 100644 index 0000000000..7ea15c0eae --- /dev/null +++ b/MatrixSDK/Space/MXSpaceFileStore.swift @@ -0,0 +1,125 @@ +// +// Copyright 2021 The Matrix.org Foundation C.I.C +// +// 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 + +/// `MXSpaceFileStore` is used to store the spaces related data into a file +class MXSpaceFileStore: MXSpaceStore { + + // MARK: - Constants + + private enum Constants { + static let fileStoreFolder = "MXSpaceStore" + static let fileStoreGraphFile = "graph" + static let backupFileExtension = "backup" + } + + // MARK: - Properties + + private let userId: String + private var storeUrl: URL? + + // MARK - Setup + + init(userId: String) { + self.userId = userId + self.setUpStoragePaths() + } + + /// Stores the given graph + /// - Parameters: + /// - spaceGraphData: space graph to be stored + /// - Returns: `true` if the data has been stored properly.`false` otherwise + func store(spaceGraphData: MXSpaceGraphData) -> Bool { + guard let storeUrl = self.storeUrl else { + MXLog.error("[MXSpaceStore] storeSpaceGraphData failed: storeUrl not defined") + return false + } + + let fileUrl = storeUrl.appendingPathComponent(Constants.fileStoreGraphFile) + let backupUrl = fileUrl.appendingPathExtension(Constants.backupFileExtension) + + if FileManager.default.fileExists(atPath: fileUrl.path) { + do { + if FileManager.default.fileExists(atPath: backupUrl.path) { + try FileManager.default.removeItem(at: backupUrl) + } + try FileManager.default.moveItem(at: fileUrl, to: backupUrl) + } catch { + MXLog.error("[MXSpaceStore] storeSpaceGraphData failed to move graph to backup: \(error)") + } + } + + return NSKeyedArchiver.archiveRootObject(spaceGraphData, toFile: fileUrl.path) + } + + /// Loads graph data from store + /// - Returns:an instance of `MXSpaceGraphData` if the data has been restored succesfully. `nil` otherwise + func loadSpaceGraphData() -> MXSpaceGraphData? { + guard let storeUrl = self.storeUrl else { + MXLog.error("[MXSpaceStore] loadSpaceGraphData failed: storeUrl not defined") + return nil + } + + let fileUrl = storeUrl.appendingPathComponent(Constants.fileStoreGraphFile) + + do { + guard let graph = try? NSKeyedUnarchiver.unarchiveObject(withFile: fileUrl.path) as? MXSpaceGraphData else { + MXLog.warning("[MXSpaceStore] loadSpaceGraphData found no archived graph") + return nil + } + + return graph + } catch { + MXLog.warning("[MXSpaceStore] loadSpaceGraphData failed with error: \(error)") + } + + return nil + } + + // MARK - Private + + private func setUpStoragePaths() { + var cacheUrl: URL? + + if let applicationGroupIdentifier = MXSDKOptions.sharedInstance().applicationGroupIdentifier { + cacheUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: applicationGroupIdentifier) + } else { + let cacheDirList = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true) + cacheUrl = URL(fileURLWithPath: cacheDirList[0]) + } + + guard let cacheUrl = cacheUrl else { + MXLog.error("[MXSpaceStore] setUpStoragePaths was unable to define cache URL") + return + } + + let storeUrl = cacheUrl.appendingPathComponent(Constants.fileStoreFolder).appendingPathComponent(self.userId) + + var isDirectory: ObjCBool = false + if !FileManager.default.fileExists(atPath: storeUrl.path, isDirectory: &isDirectory) { + do { + try FileManager.default.createDirectory(at: storeUrl, withIntermediateDirectories: true, attributes: nil) + self.storeUrl = storeUrl + } catch { + MXLog.error("[MXSpaceStore] setUpStoragePaths was unable to create space storage folder: \(error)") + } + } else { + self.storeUrl = storeUrl + } + } + +} diff --git a/MatrixSDK/Space/MXSpaceNotificationCounter.swift b/MatrixSDK/Space/MXSpaceNotificationCounter.swift index 99dad472c5..2e86628ee4 100644 --- a/MatrixSDK/Space/MXSpaceNotificationCounter.swift +++ b/MatrixSDK/Space/MXSpaceNotificationCounter.swift @@ -80,7 +80,7 @@ public class MXSpaceNotificationCounter: NSObject { /// Compute the notification count for every spaces public func computeNotificationCount() { let startDate = Date() - MXLog.debug("[Spaces] computeNotificationCount started") + MXLog.debug("[MXSpaceNotificationCounter] computeNotificationCount: started") self.sdkProcessingQueue.async { let roomsIds: [String] = self.session.rooms.compactMap { room in @@ -96,7 +96,7 @@ public class MXSpaceNotificationCounter: NSObject { self.homeNotificationState = result.homeNotificationState self.notificationStatePerSpaceId = result.notificationStatePerSpaceId - MXLog.debug("[Spaces] computeNotificationCount ended after \(Date().timeIntervalSince(startDate))s") + MXLog.debug("[MXSpaceNotificationCounter] computeNotificationCount: ended after \(Date().timeIntervalSince(startDate))s") self.completionQueue.async { NotificationCenter.default.post(name: MXSpaceNotificationCounter.didUpdateNotificationCount, object: self) diff --git a/MatrixSDK/Space/MXSpaceService.swift b/MatrixSDK/Space/MXSpaceService.swift index 8793f8df55..37a95e2f95 100644 --- a/MatrixSDK/Space/MXSpaceService.swift +++ b/MatrixSDK/Space/MXSpaceService.swift @@ -88,7 +88,6 @@ public class MXSpaceService: NSObject { public var graphUpdateEnabled = true private var sessionStateDidChangeObserver: Any? - private var sessionDidSyncObserver: Any? public var ancestorsPerRoomId: [String:Set] { return graph.ancestorsPerRoomId @@ -139,7 +138,7 @@ public class MXSpaceService: NSObject { /// Loads graph from the given store public func loadData() { self.processingQueue.async { - let store = MXSpaceStore(session: self.session) + let store = MXSpaceFileStore(userId: self.session.myUserId) if let loadedGraph = store.loadSpaceGraphData() { self.graph = loadedGraph @@ -169,58 +168,16 @@ public class MXSpaceService: NSObject { return self.graph.orphanedRoomIds.contains(roomId) || self.graph.orphanedDirectRoomIds.contains(roomId) } - /// Build the graph of rooms - public func buildGraph() { - guard !self.isGraphBuilding && self.graphUpdateEnabled else { - MXLog.debug("[Spaces] buildGraph aborted: graph is building or disabled") - self.needsUpdate = true + /// Handle a sync response and decide serverTimeout for the next sync request. + /// - Parameters: + /// - syncResponse: The sync response object + public func handleSyncResponse(_ syncResponse: MXSyncResponse) { + guard self.needsUpdate || !(syncResponse.rooms?.join?.isEmpty ?? true) || !(syncResponse.rooms?.invite?.isEmpty ?? true) || !(syncResponse.rooms?.leave?.isEmpty ?? true) || !(syncResponse.toDevice?.events.isEmpty ?? true) else + { return } - self.isGraphBuilding = true - self.needsUpdate = false - - let startDate = Date() - MXLog.debug("[Spaces] buildGraph started") - - var directRoomIds = Set() - let roomIds: [String] = self.session.rooms.compactMap { room in - if room.isDirect { - directRoomIds.insert(room.roomId) - } - return room.roomId - } - - let output = PrepareDataResult() - MXLog.debug("[Spaces] preparing data for \(roomIds.count) rooms") - self.prepareData(with: roomIds, index: 0, output: output) { result in - while !output.computingSpaces.isEmpty { - sleep(1) - } - - MXLog.debug("[Spaces] data prepared in \(Date().timeIntervalSince(startDate))") - - self.computSpaceGraph(with: result, roomIds: roomIds, directRoomIds: directRoomIds) { graph in - self.graph = graph - - MXLog.debug("[Spaces] buildGraph ended after \(Date().timeIntervalSince(startDate))s") - - self.isGraphBuilding = false - self.isInitialised = true - - NotificationCenter.default.post(name: MXSpaceService.didBuildSpaceGraph, object: self) - - self.processingQueue.async { - let store = MXSpaceStore(session: self.session) - if !store.store(spaceGraphData: self.graph) { - MXLog.error("[Spaces] buildGraph: failed to store space graph") - } - - // TODO improve updateNotificationsCount and call the method to all spaces once subspaces will be supported - self.notificationCounter.computeNotificationCount() - } - } - } + self.buildGraph() } /// Create a space. @@ -357,147 +314,74 @@ public class MXSpaceService: NSObject { } } - // MARK: - Private - - private func registerNotificationObservers() { - self.sessionStateDidChangeObserver = NotificationCenter.default.addObserver(forName: NSNotification.Name.mxSessionStateDidChange, object: session, queue: nil) { [weak self] notification in - guard let session = self?.session, session.state == .storeDataReady else { - return - } - - self?.loadData() - } - - self.sessionDidSyncObserver = NotificationCenter.default.addObserver(forName: NSNotification.Name.mxSessionDidSync, object: session, queue: nil) { [weak self] notification in - guard let self = self, let syncResponse = notification.userInfo?[kMXSessionNotificationSyncResponseKey] as? MXSyncResponse else { - return - } - - guard self.needsUpdate || !(syncResponse.rooms?.join?.isEmpty ?? true) || !(syncResponse.rooms?.invite?.isEmpty ?? true) || !(syncResponse.rooms?.leave?.isEmpty ?? true) || !(syncResponse.toDevice?.events.isEmpty ?? true) else - { - return - } - - self.buildGraph() - } - } + // MARK: - Space graph computation - private func unregisterNotificationObservers() { - if let observer = self.sessionStateDidChangeObserver { - NotificationCenter.default.removeObserver(observer) - } - if let observer = self.sessionDidSyncObserver { - NotificationCenter.default.removeObserver(observer) + private class PrepareDataResult { + var isPreparingData = true + var spaces: [MXSpace] = [] + var spacesPerId: [String : MXSpace] = [:] + var directRoomIdsPerMemberId: [String: [String]] = [:] + var computingSpaces: Set = Set() + var computingDirectRooms: Set = Set() + var isComputing: Bool { + return !self.computingSpaces.isEmpty || !self.computingDirectRooms.isEmpty } } - private func buildRoomHierarchy(with space: MXSpace, visitedSpaceIds: [String], ancestorsPerRoomId: inout [String: Set], descendantsPerRoomId: inout [String: Set]) { - var visitedSpaceIds = visitedSpaceIds - visitedSpaceIds.append(space.spaceId) - space.childRoomIds.forEach { roomId in - var parentIds = ancestorsPerRoomId[roomId] ?? Set() - visitedSpaceIds.forEach { spaceId in - parentIds.insert(spaceId) - - var descendantIds = descendantsPerRoomId[spaceId] ?? Set() - descendantIds.insert(roomId) - descendantsPerRoomId[spaceId] = descendantIds - } - ancestorsPerRoomId[roomId] = parentIds - } - space.childSpaces.forEach { childSpace in - buildRoomHierarchy(with: childSpace, visitedSpaceIds: visitedSpaceIds, ancestorsPerRoomId: &ancestorsPerRoomId, descendantsPerRoomId: &descendantsPerRoomId) + /// Build the graph of rooms + private func buildGraph() { + guard !self.isGraphBuilding && self.graphUpdateEnabled else { + MXLog.debug("[MXSpaceService] buildGraph: aborted: graph is building or disabled") + self.needsUpdate = true + return } - } - - private func createRoomSummary(with spaceChildSummaryResponse: MXSpaceChildSummaryResponse) -> MXRoomSummary { - - let roomId = spaceChildSummaryResponse.roomId - let roomTypeString = spaceChildSummaryResponse.roomType - - let roomSummary: MXRoomSummary = MXRoomSummary(roomId: roomId, andMatrixSession: nil) - roomSummary.roomTypeString = roomTypeString - roomSummary.roomType = self.roomTypeMapper.roomType(from: roomTypeString) - let joinedMembersCount = UInt(spaceChildSummaryResponse.numJoinedMembers) + self.isGraphBuilding = true + self.needsUpdate = false - let membersCount = MXRoomMembersCount() - membersCount.joined = joinedMembersCount - membersCount.members = joinedMembersCount + let startDate = Date() + MXLog.debug("[MXSpaceService] buildGraph: started") - roomSummary.membersCount = membersCount - roomSummary.displayname = spaceChildSummaryResponse.name - roomSummary.topic = spaceChildSummaryResponse.topic - roomSummary.avatar = spaceChildSummaryResponse.avatarUrl - roomSummary.isEncrypted = false - - return roomSummary - } - - private func spaceChildInfos(from spaceChildrenResponse: MXSpaceChildrenResponse, excludedSpaceId: String, childrenIdsPerChildRoomId: [String: [String]], parentIdsPerChildRoomId: [String:Set], spaceChildEventsPerChildRoomId: [String:[String:Any]]) -> [MXSpaceChildInfo] { - guard let spaceChildSummaries = spaceChildrenResponse.rooms else { - return [] + var directRoomIds = Set() + let roomIds: [String] = self.session.rooms.compactMap { room in + if room.isDirect { + directRoomIds.insert(room.roomId) + } + return room.roomId } - let childInfos: [MXSpaceChildInfo] = spaceChildSummaries.compactMap { (spaceChildSummaryResponse) -> MXSpaceChildInfo? in + let output = PrepareDataResult() + MXLog.debug("[MXSpaceService] buildGraph: preparing data for \(roomIds.count) rooms") + self.prepareData(with: roomIds, index: 0, output: output) { result in + while !output.computingSpaces.isEmpty { + sleep(1) + } - let spaceId = spaceChildSummaryResponse.roomId + MXLog.debug("[MXSpaceService] buildGraph: data prepared in \(Date().timeIntervalSince(startDate))") - guard spaceId != excludedSpaceId else { - return nil + self.computSpaceGraph(with: result, roomIds: roomIds, directRoomIds: directRoomIds) { graph in + self.graph = graph + + MXLog.debug("[MXSpaceService] buildGraph: ended after \(Date().timeIntervalSince(startDate))s") + + self.isGraphBuilding = false + self.isInitialised = true + + NotificationCenter.default.post(name: MXSpaceService.didBuildSpaceGraph, object: self) + + self.processingQueue.async { + let store = MXSpaceFileStore(userId: self.session.myUserId) + if !store.store(spaceGraphData: self.graph) { + MXLog.error("[MXSpaceService] buildGraph: failed to store space graph") + } + + // TODO improve updateNotificationsCount and call the method to all spaces once subspaces will be supported + self.notificationCounter.computeNotificationCount() + } } - - let childStateEvent = spaceChildrenResponse.events?.first(where: { (event) -> Bool in - return event.stateKey == spaceId && event.eventType == .spaceChild - }) - - return self.createSpaceChildInfo(with: spaceChildSummaryResponse, and: childStateEvent, parentIds: parentIdsPerChildRoomId[spaceId], childrenIds: childrenIdsPerChildRoomId[spaceId], childEvents: spaceChildEventsPerChildRoomId[spaceId]) - } - - return childInfos - } - - private func createSpaceChildInfo(with spaceChildSummaryResponse: MXSpaceChildSummaryResponse, and spaceChildStateEvent: MXEvent?, parentIds: Set?, childrenIds: [String]?, childEvents: [String:Any]?) -> MXSpaceChildInfo { - - var spaceChildContent: MXSpaceChildContent? - - if let stateEventContent = spaceChildStateEvent?.content { - spaceChildContent = MXSpaceChildContent(fromJSON: stateEventContent) - } - - let roomTypeString = spaceChildSummaryResponse.roomType - let roomType = self.roomTypeMapper.roomType(from: roomTypeString) - - return MXSpaceChildInfo(childRoomId: spaceChildSummaryResponse.roomId, - isKnown: true, - roomTypeString: roomTypeString, - roomType: roomType, - name: spaceChildSummaryResponse.name, - topic: spaceChildSummaryResponse.topic, - canonicalAlias: spaceChildSummaryResponse.canonicalAlias, - avatarUrl: spaceChildSummaryResponse.avatarUrl, - order: spaceChildContent?.order, - activeMemberCount: spaceChildSummaryResponse.numJoinedMembers, - autoJoin: childEvents?[kMXEventTypeStringAutoJoinKey] as? Bool ?? false, - suggested: childEvents?[kMXEventTypeStringSuggestedKey] as? Bool ?? false, - parentIds: parentIds ?? Set(), - childrenIds: childrenIds ?? [], - viaServers: spaceChildContent?.via ?? [], - parentRoomId: spaceChildStateEvent?.roomId) - } - - private class PrepareDataResult { - var isPreparingData = true - var spaces: [MXSpace] = [] - var spacesPerId: [String : MXSpace] = [:] - var directRoomIdsPerMemberId: [String: [String]] = [:] - var computingSpaces: Set = Set() - var computingDirectRooms: Set = Set() - var isComputing: Bool { - return !self.computingSpaces.isEmpty || !self.computingDirectRooms.isEmpty } } - + private func prepareData(with roomIds:[String], index: Int, output: PrepareDataResult, completion: @escaping (_ result: PrepareDataResult) -> Void) { self.processingQueue.async { guard index < roomIds.count else { @@ -588,7 +472,7 @@ public class MXSpaceService: NSObject { private func computSpaceGraph(with result: PrepareDataResult, roomIds: [String], directRoomIds: Set, completion: @escaping (_ graph: MXSpaceGraphData) -> Void) { let startDate = Date() - MXLog.debug("[Spaces] started computSpaceGraph") + MXLog.debug("[MXSpaceService] computSpaceGraph: started") self.processingQueue.async { var parentIdsPerRoomId: [String : Set] = [:] @@ -641,13 +525,129 @@ public class MXSpaceService: NSObject { orphanedRoomIds: orphanedRoomIds, orphanedDirectRoomIds: orphanedDirectRoomIds) - MXLog.debug("[Spaces] space graph computed in \(Date().timeIntervalSince(startDate))s") + MXLog.debug("[MXSpaceService] computSpaceGraph: space graph computed in \(Date().timeIntervalSince(startDate))s") self.completionQueue.async { completion(graph) } } } + + private func buildRoomHierarchy(with space: MXSpace, visitedSpaceIds: [String], ancestorsPerRoomId: inout [String: Set], descendantsPerRoomId: inout [String: Set]) { + var visitedSpaceIds = visitedSpaceIds + visitedSpaceIds.append(space.spaceId) + space.childRoomIds.forEach { roomId in + var parentIds = ancestorsPerRoomId[roomId] ?? Set() + visitedSpaceIds.forEach { spaceId in + parentIds.insert(spaceId) + + var descendantIds = descendantsPerRoomId[spaceId] ?? Set() + descendantIds.insert(roomId) + descendantsPerRoomId[spaceId] = descendantIds + } + ancestorsPerRoomId[roomId] = parentIds + } + space.childSpaces.forEach { childSpace in + buildRoomHierarchy(with: childSpace, visitedSpaceIds: visitedSpaceIds, ancestorsPerRoomId: &ancestorsPerRoomId, descendantsPerRoomId: &descendantsPerRoomId) + } + } + + // MARK: - Notification handling + + private func registerNotificationObservers() { + self.sessionStateDidChangeObserver = NotificationCenter.default.addObserver(forName: NSNotification.Name.mxSessionStateDidChange, object: session, queue: nil) { [weak self] notification in + guard let session = self?.session, session.state == .storeDataReady else { + return + } + + self?.loadData() + } + } + + private func unregisterNotificationObservers() { + if let observer = self.sessionStateDidChangeObserver { + NotificationCenter.default.removeObserver(observer) + } + } + + // MARK: - Private + + private func createRoomSummary(with spaceChildSummaryResponse: MXSpaceChildSummaryResponse) -> MXRoomSummary { + + let roomId = spaceChildSummaryResponse.roomId + let roomTypeString = spaceChildSummaryResponse.roomType + + let roomSummary: MXRoomSummary = MXRoomSummary(roomId: roomId, andMatrixSession: nil) + roomSummary.roomTypeString = roomTypeString + roomSummary.roomType = self.roomTypeMapper.roomType(from: roomTypeString) + + let joinedMembersCount = UInt(spaceChildSummaryResponse.numJoinedMembers) + + let membersCount = MXRoomMembersCount() + membersCount.joined = joinedMembersCount + membersCount.members = joinedMembersCount + + roomSummary.membersCount = membersCount + roomSummary.displayname = spaceChildSummaryResponse.name + roomSummary.topic = spaceChildSummaryResponse.topic + roomSummary.avatar = spaceChildSummaryResponse.avatarUrl + roomSummary.isEncrypted = false + + return roomSummary + } + + private func spaceChildInfos(from spaceChildrenResponse: MXSpaceChildrenResponse, excludedSpaceId: String, childrenIdsPerChildRoomId: [String: [String]], parentIdsPerChildRoomId: [String:Set], spaceChildEventsPerChildRoomId: [String:[String:Any]]) -> [MXSpaceChildInfo] { + guard let spaceChildSummaries = spaceChildrenResponse.rooms else { + return [] + } + + let childInfos: [MXSpaceChildInfo] = spaceChildSummaries.compactMap { (spaceChildSummaryResponse) -> MXSpaceChildInfo? in + + let spaceId = spaceChildSummaryResponse.roomId + + guard spaceId != excludedSpaceId else { + return nil + } + + let childStateEvent = spaceChildrenResponse.events?.first(where: { (event) -> Bool in + return event.stateKey == spaceId && event.eventType == .spaceChild + }) + + return self.createSpaceChildInfo(with: spaceChildSummaryResponse, and: childStateEvent, parentIds: parentIdsPerChildRoomId[spaceId], childrenIds: childrenIdsPerChildRoomId[spaceId], childEvents: spaceChildEventsPerChildRoomId[spaceId]) + } + + return childInfos + } + + private func createSpaceChildInfo(with spaceChildSummaryResponse: MXSpaceChildSummaryResponse, and spaceChildStateEvent: MXEvent?, parentIds: Set?, childrenIds: [String]?, childEvents: [String:Any]?) -> MXSpaceChildInfo { + + var spaceChildContent: MXSpaceChildContent? + + if let stateEventContent = spaceChildStateEvent?.content { + spaceChildContent = MXSpaceChildContent(fromJSON: stateEventContent) + } + + let roomTypeString = spaceChildSummaryResponse.roomType + let roomType = self.roomTypeMapper.roomType(from: roomTypeString) + + return MXSpaceChildInfo(childRoomId: spaceChildSummaryResponse.roomId, + isKnown: true, + roomTypeString: roomTypeString, + roomType: roomType, + name: spaceChildSummaryResponse.name, + topic: spaceChildSummaryResponse.topic, + canonicalAlias: spaceChildSummaryResponse.canonicalAlias, + avatarUrl: spaceChildSummaryResponse.avatarUrl, + order: spaceChildContent?.order, + activeMemberCount: spaceChildSummaryResponse.numJoinedMembers, + autoJoin: childEvents?[kMXEventTypeStringAutoJoinKey] as? Bool ?? false, + suggested: childEvents?[kMXEventTypeStringSuggestedKey] as? Bool ?? false, + parentIds: parentIds ?? Set(), + childrenIds: childrenIds ?? [], + viaServers: spaceChildContent?.via ?? [], + parentRoomId: spaceChildStateEvent?.roomId) + } + } // MARK: - Objective-C interface diff --git a/MatrixSDK/Space/MXSpaceStore.swift b/MatrixSDK/Space/MXSpaceStore.swift index 47917cb29e..910a7821b0 100644 --- a/MatrixSDK/Space/MXSpaceStore.swift +++ b/MatrixSDK/Space/MXSpaceStore.swift @@ -16,109 +16,17 @@ import Foundation -/// `MXSpaceStore` is used to store the spaces related data into a permanent store -class MXSpaceStore { - - // MARK: - Constants - - private enum Constants { - static let fileStoreFolder = "MXSpaceStore" - static let fileStoreGraphFile = "graph" - static let backupFileExtension = "backup" - } - - // MARK: - Properties - - private let userId: String - private var storeUrl: URL? - - // MARK - Setup - - init(session: MXSession) { - self.userId = session.myUserId - self.setUpStoragePaths() - } +/// `MXSpaceStore` instances are used to store the spaces related data into a permanent store +protocol MXSpaceStore { /// Stores the given graph /// - Parameters: /// - spaceGraphData: space graph to be stored /// - Returns: `true` if the data has been stored properly.`false` otherwise - func store(spaceGraphData: MXSpaceGraphData) -> Bool { - guard let storeUrl = self.storeUrl else { - MXLog.error("[MXSpaceStore] storeSpaceGraphData failed: storeUrl not defined") - return false - } - - let fileUrl = storeUrl.appendingPathComponent(Constants.fileStoreGraphFile) - let backupUrl = fileUrl.appendingPathExtension(Constants.backupFileExtension) - - if FileManager.default.fileExists(atPath: fileUrl.path) { - do { - if FileManager.default.fileExists(atPath: backupUrl.path) { - try FileManager.default.removeItem(at: backupUrl) - } - try FileManager.default.moveItem(at: fileUrl, to: backupUrl) - } catch { - MXLog.error("[MXSpaceStore] storeSpaceGraphData failed to move graph to backup: \(error)") - } - } - - return NSKeyedArchiver.archiveRootObject(spaceGraphData, toFile: fileUrl.path) - } + func store(spaceGraphData: MXSpaceGraphData) -> Bool /// Loads graph data from store /// - Returns:an instance of `MXSpaceGraphData` if the data has been restored succesfully. `nil` otherwise - func loadSpaceGraphData() -> MXSpaceGraphData? { - guard let storeUrl = self.storeUrl else { - MXLog.error("[MXSpaceStore] loadSpaceGraphData failed: storeUrl not defined") - return nil - } - - let fileUrl = storeUrl.appendingPathComponent(Constants.fileStoreGraphFile) - - do { - guard let graph = try? NSKeyedUnarchiver.unarchiveObject(withFile: fileUrl.path) as? MXSpaceGraphData else { - MXLog.warning("[MXSpaceStore] loadSpaceGraphData found no archived graph") - return nil - } - - return graph - } catch { - MXLog.warning("[MXSpaceStore] loadSpaceGraphData failed with error: \(error)") - } - - return nil - } + func loadSpaceGraphData() -> MXSpaceGraphData? - // MARK - Private - - private func setUpStoragePaths() { - var cacheUrl: URL? - - if let applicationGroupIdentifier = MXSDKOptions.sharedInstance().applicationGroupIdentifier { - cacheUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: applicationGroupIdentifier) - } else { - let cacheDirList = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true) - cacheUrl = URL(fileURLWithPath: cacheDirList[0]) - } - - guard let cacheUrl = cacheUrl else { - MXLog.error("[MXSpaceStore] setUpStoragePaths was unable to define cache URL") - return - } - - let storeUrl = cacheUrl.appendingPathComponent(Constants.fileStoreFolder).appendingPathComponent(self.userId) - - var isDirectory: ObjCBool = false - if !FileManager.default.fileExists(atPath: storeUrl.path, isDirectory: &isDirectory) { - do { - try FileManager.default.createDirectory(at: storeUrl, withIntermediateDirectories: true, attributes: nil) - self.storeUrl = storeUrl - } catch { - MXLog.error("[MXSpaceStore] setUpStoragePaths was unable to create space storage folder: \(error)") - } - } else { - self.storeUrl = storeUrl - } - } } From 1b9cb4721061585ef1659ea2ad9e23b967caf0f2 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Thu, 7 Oct 2021 09:56:56 +0200 Subject: [PATCH 26/42] Try to make CI happy --- MatrixSDK/Space/MXSpaceFileStore.swift | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/MatrixSDK/Space/MXSpaceFileStore.swift b/MatrixSDK/Space/MXSpaceFileStore.swift index 7ea15c0eae..b33e9fac4c 100644 --- a/MatrixSDK/Space/MXSpaceFileStore.swift +++ b/MatrixSDK/Space/MXSpaceFileStore.swift @@ -45,7 +45,7 @@ class MXSpaceFileStore: MXSpaceStore { /// - Returns: `true` if the data has been stored properly.`false` otherwise func store(spaceGraphData: MXSpaceGraphData) -> Bool { guard let storeUrl = self.storeUrl else { - MXLog.error("[MXSpaceStore] storeSpaceGraphData failed: storeUrl not defined") + MXLog.error("[MXSpaceFileStore] store: storeSpaceGraphData failed: storeUrl not defined") return false } @@ -59,7 +59,7 @@ class MXSpaceFileStore: MXSpaceStore { } try FileManager.default.moveItem(at: fileUrl, to: backupUrl) } catch { - MXLog.error("[MXSpaceStore] storeSpaceGraphData failed to move graph to backup: \(error)") + MXLog.error("[MXSpaceFileStore] store: storeSpaceGraphData failed to move graph to backup: \(error)") } } @@ -70,7 +70,7 @@ class MXSpaceFileStore: MXSpaceStore { /// - Returns:an instance of `MXSpaceGraphData` if the data has been restored succesfully. `nil` otherwise func loadSpaceGraphData() -> MXSpaceGraphData? { guard let storeUrl = self.storeUrl else { - MXLog.error("[MXSpaceStore] loadSpaceGraphData failed: storeUrl not defined") + MXLog.error("[MXSpaceStore] loadSpaceGraphData: failed: storeUrl not defined") return nil } @@ -78,13 +78,13 @@ class MXSpaceFileStore: MXSpaceStore { do { guard let graph = try? NSKeyedUnarchiver.unarchiveObject(withFile: fileUrl.path) as? MXSpaceGraphData else { - MXLog.warning("[MXSpaceStore] loadSpaceGraphData found no archived graph") + MXLog.warning("[MXSpaceStore] loadSpaceGraphData: found no archived graph") return nil } return graph } catch { - MXLog.warning("[MXSpaceStore] loadSpaceGraphData failed with error: \(error)") + MXLog.warning("[MXSpaceStore] loadSpaceGraphData: failed with error: \(error)") } return nil @@ -93,16 +93,16 @@ class MXSpaceFileStore: MXSpaceStore { // MARK - Private private func setUpStoragePaths() { - var cacheUrl: URL? + var _cacheUrl: URL? if let applicationGroupIdentifier = MXSDKOptions.sharedInstance().applicationGroupIdentifier { - cacheUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: applicationGroupIdentifier) + _cacheUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: applicationGroupIdentifier) } else { let cacheDirList = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true) - cacheUrl = URL(fileURLWithPath: cacheDirList[0]) + _cacheUrl = URL(fileURLWithPath: cacheDirList[0]) } - guard let cacheUrl = cacheUrl else { + guard let cacheUrl = _cacheUrl else { MXLog.error("[MXSpaceStore] setUpStoragePaths was unable to define cache URL") return } From ff051e0b40f533293ff10b540d353c3906975fe1 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Thu, 7 Oct 2021 10:16:44 +0200 Subject: [PATCH 27/42] Try to make CI happy --- .../Space/MXSpaceNotificationCounter.swift | 6 +++--- MatrixSDK/Space/MXSpaceService.swift | 20 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/MatrixSDK/Space/MXSpaceNotificationCounter.swift b/MatrixSDK/Space/MXSpaceNotificationCounter.swift index 2e86628ee4..e435fe863f 100644 --- a/MatrixSDK/Space/MXSpaceNotificationCounter.swift +++ b/MatrixSDK/Space/MXSpaceNotificationCounter.swift @@ -145,17 +145,17 @@ public class MXSpaceNotificationCounter: NSObject { self.processingQueue.async { let roomId = roomIds[index] - var roomInfo: RoomInfo? + var _roomInfo: RoomInfo? self.sdkProcessingQueue.sync { guard let room = self.session.room(withRoomId: roomId), let summary = room.summary, summary.roomType != .space else { return } - roomInfo = RoomInfo(with: room) + _roomInfo = RoomInfo(with: room) } - guard let roomInfo = roomInfo else { + guard let roomInfo = _roomInfo else { self.computeNotificationCount(for: spaceIds, with: roomIds, at: index + 1, output: output, ancestorsPerRoomId: ancestorsPerRoomId, completion: completion) return } diff --git a/MatrixSDK/Space/MXSpaceService.swift b/MatrixSDK/Space/MXSpaceService.swift index 37a95e2f95..b9e77bb68a 100644 --- a/MatrixSDK/Space/MXSpaceService.swift +++ b/MatrixSDK/Space/MXSpaceService.swift @@ -394,26 +394,26 @@ public class MXSpaceService: NSObject { return } - var room: MXRoom? - var space: MXSpace? + var _room: MXRoom? + var _space: MXSpace? var isRoomDirect = false - var directUserId: String? + var _directUserId: String? self.sdkProcessingQueue.sync { - room = self.session.room(withRoomId: roomIds[index]) + _room = self.session.room(withRoomId: roomIds[index]) - if let room = room { - space = self.spacesPerId[room.roomId] ?? room.toSpace() + if let room = _room { + _space = self.spacesPerId[room.roomId] ?? room.toSpace() isRoomDirect = room.isDirect - directUserId = room.directUserId + _directUserId = room.directUserId } } - guard let room = room else { + guard let room = _room else { self.prepareData(with: roomIds, index: index+1, output: output, completion: completion) return } - if let space = space { + if let space = _space { output.computingSpaces.insert(space.spaceId) space.readChildRoomsAndMembers { output.computingSpaces.remove(space.spaceId) @@ -426,7 +426,7 @@ public class MXSpaceService: NSObject { self.prepareData(with: roomIds, index: index+1, output: output, completion: completion) } else if isRoomDirect { - if let directUserId = directUserId { + if let directUserId = _directUserId { var rooms = output.directRoomIdsPerMemberId[directUserId] ?? [] rooms.append(room.roomId) output.directRoomIdsPerMemberId[directUserId] = rooms From 6961b264cda376339ba5bde9243909e7fd85de6a Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Thu, 7 Oct 2021 10:20:12 +0200 Subject: [PATCH 28/42] Try to make CI happy --- MatrixSDK/MXSession.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MatrixSDK/MXSession.h b/MatrixSDK/MXSession.h index 1596fc3957..3e6c5c5849 100644 --- a/MatrixSDK/MXSession.h +++ b/MatrixSDK/MXSession.h @@ -897,7 +897,7 @@ typedef void (^MXOnBackgroundSyncFail)(NSError *error); @return the MXRoom instance. */ -- (MXRoom * _Nullable)roomWithRoomId:(NSString* _Nonnull)roomId; +- (MXRoom *)roomWithRoomId:(NSString*)roomId; /** Get the MXRoom instance of the room that owns the passed room alias. From 93c61e6def204e6b9c8e622fd4bd5c16e38946d8 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Thu, 7 Oct 2021 12:34:43 +0200 Subject: [PATCH 29/42] Fix performance issues with Spaces on very large accounts #4898 - Update after review --- MatrixSDK/Space/MXSpaceFileStore.swift | 6 ++++-- MatrixSDK/Space/MXSpaceService.swift | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/MatrixSDK/Space/MXSpaceFileStore.swift b/MatrixSDK/Space/MXSpaceFileStore.swift index b33e9fac4c..4bb709bcb0 100644 --- a/MatrixSDK/Space/MXSpaceFileStore.swift +++ b/MatrixSDK/Space/MXSpaceFileStore.swift @@ -30,12 +30,14 @@ class MXSpaceFileStore: MXSpaceStore { // MARK: - Properties private let userId: String + private let deviceId: String private var storeUrl: URL? // MARK - Setup - init(userId: String) { + init(userId: String, deviceId: String) { self.userId = userId + self.deviceId = deviceId self.setUpStoragePaths() } @@ -107,7 +109,7 @@ class MXSpaceFileStore: MXSpaceStore { return } - let storeUrl = cacheUrl.appendingPathComponent(Constants.fileStoreFolder).appendingPathComponent(self.userId) + let storeUrl = cacheUrl.appendingPathComponent(Constants.fileStoreFolder).appendingPathComponent(self.userId).appendingPathComponent(self.deviceId) var isDirectory: ObjCBool = false if !FileManager.default.fileExists(atPath: storeUrl.path, isDirectory: &isDirectory) { diff --git a/MatrixSDK/Space/MXSpaceService.swift b/MatrixSDK/Space/MXSpaceService.swift index b9e77bb68a..3ebad1570e 100644 --- a/MatrixSDK/Space/MXSpaceService.swift +++ b/MatrixSDK/Space/MXSpaceService.swift @@ -138,7 +138,7 @@ public class MXSpaceService: NSObject { /// Loads graph from the given store public func loadData() { self.processingQueue.async { - let store = MXSpaceFileStore(userId: self.session.myUserId) + let store = MXSpaceFileStore(userId: self.session.myUserId, deviceId: self.session.myDeviceId) if let loadedGraph = store.loadSpaceGraphData() { self.graph = loadedGraph @@ -168,7 +168,7 @@ public class MXSpaceService: NSObject { return self.graph.orphanedRoomIds.contains(roomId) || self.graph.orphanedDirectRoomIds.contains(roomId) } - /// Handle a sync response and decide serverTimeout for the next sync request. + /// Handle a sync response /// - Parameters: /// - syncResponse: The sync response object public func handleSyncResponse(_ syncResponse: MXSyncResponse) { @@ -370,7 +370,7 @@ public class MXSpaceService: NSObject { NotificationCenter.default.post(name: MXSpaceService.didBuildSpaceGraph, object: self) self.processingQueue.async { - let store = MXSpaceFileStore(userId: self.session.myUserId) + let store = MXSpaceFileStore(userId: self.session.myUserId, deviceId: self.session.myDeviceId) if !store.store(spaceGraphData: self.graph) { MXLog.error("[MXSpaceService] buildGraph: failed to store space graph") } From 05774fa854b87fd1b6d66cfcc9546bf5302c04f1 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Thu, 7 Oct 2021 18:16:13 +0300 Subject: [PATCH 30/42] Create an extension over RLMRealm --- MatrixSDK.xcodeproj/project.pbxproj | 12 ++++++ .../Utils/Categories/RLMRealm+MatrixSDK.h | 43 +++++++++++++++++++ .../Utils/Categories/RLMRealm+MatrixSDK.m | 38 ++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 MatrixSDK/Utils/Categories/RLMRealm+MatrixSDK.h create mode 100644 MatrixSDK/Utils/Categories/RLMRealm+MatrixSDK.m diff --git a/MatrixSDK.xcodeproj/project.pbxproj b/MatrixSDK.xcodeproj/project.pbxproj index 3674d8961d..980522289b 100644 --- a/MatrixSDK.xcodeproj/project.pbxproj +++ b/MatrixSDK.xcodeproj/project.pbxproj @@ -1335,6 +1335,10 @@ EC054973260123BE0047ECD7 /* MXRoomAccountDataUpdating.h in Headers */ = {isa = PBXBuildFile; fileRef = EC054972260123BE0047ECD7 /* MXRoomAccountDataUpdating.h */; settings = {ATTRIBUTES = (Public, ); }; }; EC054974260123BE0047ECD7 /* MXRoomAccountDataUpdating.h in Headers */ = {isa = PBXBuildFile; fileRef = EC054972260123BE0047ECD7 /* MXRoomAccountDataUpdating.h */; settings = {ATTRIBUTES = (Public, ); }; }; EC0C51752559388C00F2CC66 /* MXStopwatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECB5D98B2552C9B4000AD89C /* MXStopwatch.swift */; }; + EC11658D270F3ABF0089FA56 /* RLMRealm+MatrixSDK.h in Headers */ = {isa = PBXBuildFile; fileRef = EC11658B270F3ABF0089FA56 /* RLMRealm+MatrixSDK.h */; }; + EC11658E270F3ABF0089FA56 /* RLMRealm+MatrixSDK.h in Headers */ = {isa = PBXBuildFile; fileRef = EC11658B270F3ABF0089FA56 /* RLMRealm+MatrixSDK.h */; }; + EC11658F270F3ABF0089FA56 /* RLMRealm+MatrixSDK.m in Sources */ = {isa = PBXBuildFile; fileRef = EC11658C270F3ABF0089FA56 /* RLMRealm+MatrixSDK.m */; }; + EC116590270F3ABF0089FA56 /* RLMRealm+MatrixSDK.m in Sources */ = {isa = PBXBuildFile; fileRef = EC11658C270F3ABF0089FA56 /* RLMRealm+MatrixSDK.m */; }; EC1848C52685F64D00865E16 /* MXiOSAudioOutputRoute.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC1848C42685F64D00865E16 /* MXiOSAudioOutputRoute.swift */; }; EC1848C72686174E00865E16 /* MXiOSAudioOutputRouteType.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC1848C62686174E00865E16 /* MXiOSAudioOutputRouteType.swift */; }; EC1848C92686176D00865E16 /* MXiOSAudioOutputRouterDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC1848C82686176D00865E16 /* MXiOSAudioOutputRouterDelegate.swift */; }; @@ -2282,6 +2286,8 @@ EC05478025FF99450047ECD7 /* MXRoomAccountDataUpdater.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXRoomAccountDataUpdater.h; sourceTree = ""; }; EC05478125FF99450047ECD7 /* MXRoomAccountDataUpdater.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MXRoomAccountDataUpdater.m; sourceTree = ""; }; EC054972260123BE0047ECD7 /* MXRoomAccountDataUpdating.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXRoomAccountDataUpdating.h; sourceTree = ""; }; + EC11658B270F3ABF0089FA56 /* RLMRealm+MatrixSDK.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RLMRealm+MatrixSDK.h"; sourceTree = ""; }; + EC11658C270F3ABF0089FA56 /* RLMRealm+MatrixSDK.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "RLMRealm+MatrixSDK.m"; sourceTree = ""; }; EC1848C42685F64D00865E16 /* MXiOSAudioOutputRoute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXiOSAudioOutputRoute.swift; sourceTree = ""; }; EC1848C62686174E00865E16 /* MXiOSAudioOutputRouteType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXiOSAudioOutputRouteType.swift; sourceTree = ""; }; EC1848C82686176D00865E16 /* MXiOSAudioOutputRouterDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXiOSAudioOutputRouterDelegate.swift; sourceTree = ""; }; @@ -4172,6 +4178,8 @@ 3259D02126037A7200C365DB /* NSArray.swift */, 321CFDEC225264C4004D31DF /* NSArray+MatrixSDK.h */, 321CFDED225264C4004D31DF /* NSArray+MatrixSDK.m */, + EC11658B270F3ABF0089FA56 /* RLMRealm+MatrixSDK.h */, + EC11658C270F3ABF0089FA56 /* RLMRealm+MatrixSDK.m */, ); path = Categories; sourceTree = ""; @@ -4341,6 +4349,7 @@ EC8A53C325B1BC77004E0802 /* MXCallInviteEventContent.h in Headers */, 3281E8B919E42DFE00976E1A /* MXJSONModels.h in Headers */, 3A108AA225810FE5005EEBE9 /* MXRawDataKey.h in Headers */, + EC11658D270F3ABF0089FA56 /* RLMRealm+MatrixSDK.h in Headers */, B1A026F626161EF5001AADFF /* MXSpaceChildSummaryResponse.h in Headers */, EC05478225FF99450047ECD7 /* MXRoomAccountDataUpdater.h in Headers */, 8EC511042568216B00EC4E5B /* MXTaggedEventInfo.h in Headers */, @@ -4786,6 +4795,7 @@ B14EF3362397E90400758AF0 /* MXEventScanStore.h in Headers */, 3287165023C4C12200D720CA /* MXKeyVerificationManager_Private.h in Headers */, EC60EE07265CFFF400B39A4E /* MXGroupSyncProfile.h in Headers */, + EC11658E270F3ABF0089FA56 /* RLMRealm+MatrixSDK.h in Headers */, 324AAC7E2399143400380A66 /* MXKeyVerificationCancel.h in Headers */, B14EF3372397E90400758AF0 /* MXRoomTombStoneContent.h in Headers */, 3274538B23FD918800438328 /* MXKeyVerificationByToDeviceRequest.h in Headers */, @@ -5335,6 +5345,7 @@ 320B393C239FD15E00BE2C06 /* MXKeyVerificationRequest.m in Sources */, EC383BAC254030DF002FBBE6 /* MXBackgroundStore.swift in Sources */, 32A31BC920D401FC005916C7 /* MXRoomFilter.m in Sources */, + EC11658F270F3ABF0089FA56 /* RLMRealm+MatrixSDK.m in Sources */, 32A151471DAF7C0C00400192 /* MXDeviceInfo.m in Sources */, 321CFDEB22525DEE004D31DF /* MXIncomingSASTransaction.m in Sources */, 3A108A8025810C96005EEBE9 /* MXKeyData.m in Sources */, @@ -5778,6 +5789,7 @@ 324DD2B9246C21C700377005 /* MXSecretStorageKeyCreationInfo.m in Sources */, B14EF24B2397E90400758AF0 /* MXServiceTermsRestClient.m in Sources */, B14EF24C2397E90400758AF0 /* MXCredentials.m in Sources */, + EC116590270F3ABF0089FA56 /* RLMRealm+MatrixSDK.m in Sources */, B14EF24D2397E90400758AF0 /* MXOutgoingRoomKeyRequest.m in Sources */, B14EF24E2397E90400758AF0 /* MXAllowedCertificates.m in Sources */, B14EF24F2397E90400758AF0 /* MXLRUCache.m in Sources */, diff --git a/MatrixSDK/Utils/Categories/RLMRealm+MatrixSDK.h b/MatrixSDK/Utils/Categories/RLMRealm+MatrixSDK.h new file mode 100644 index 0000000000..8000559eed --- /dev/null +++ b/MatrixSDK/Utils/Categories/RLMRealm+MatrixSDK.h @@ -0,0 +1,43 @@ +// +// Copyright 2021 The Matrix.org Foundation C.I.C +// +// 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 "RLMRealm.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface RLMRealm (MatrixSDK) + +/** + Same method with `RLMRealm(MatrixSDK) transactionWithName:block:error` without error handling. + @see -[RLMRealm(MatrixSDK) transactionWithName:block:error] + */ +- (void)transactionWithName:(NSString *)name block:(void(^)(void))block; + +/** + Transaction wrapped in a background task + + @param name Background task name to distinguish it from others + @param block The block containing actions to perform. + @param outError If an error occurs, upon return contains an `NSError` object + that describes the problem. If you are not interested in + possible errors, pass in `NULL`. + @return Whether the transaction succeeded. + */ +- (BOOL)transactionWithName:(NSString *)name block:(void(^)(void))block error:(NSError * _Nullable __autoreleasing *)outError; + +@end + +NS_ASSUME_NONNULL_END diff --git a/MatrixSDK/Utils/Categories/RLMRealm+MatrixSDK.m b/MatrixSDK/Utils/Categories/RLMRealm+MatrixSDK.m new file mode 100644 index 0000000000..bf752f8f3f --- /dev/null +++ b/MatrixSDK/Utils/Categories/RLMRealm+MatrixSDK.m @@ -0,0 +1,38 @@ +// +// Copyright 2021 The Matrix.org Foundation C.I.C +// +// 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 "RLMRealm+MatrixSDK.h" +#import "MXSDKOptions.h" +#import "MXBackgroundTask.h" +#import "MXBackgroundModeHandler.h" + +@implementation RLMRealm (MatrixSDK) + +- (void)transactionWithName:(NSString *)name block:(void (^)(void))block +{ + [self transactionWithName:name block:block error:nil]; +} + +- (BOOL)transactionWithName:(NSString *)name block:(void (^)(void))block error:(NSError * _Nullable __autoreleasing *)outError +{ + id handler = [MXSDKOptions sharedInstance].backgroundModeHandler; + id backgroundTask = [handler startBackgroundTaskWithName:name expirationHandler:nil]; + BOOL result = [self transactionWithBlock:block error:outError]; + [backgroundTask stop]; + return result; +} + +@end From fe401c2e9b0890dcf82b8b48c4a17bf06638ece6 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Thu, 7 Oct 2021 18:17:54 +0300 Subject: [PATCH 31/42] Use new Realm method everywhere --- .../Store/Realm/MXRealmAggregationsStore.m | 18 +++--- .../Store/Realm/Event/MXRealmEventScanStore.m | 11 ++-- .../Store/Realm/Media/MXRealmMediaScanStore.m | 9 +-- .../RealmProvider/MXScanRealmFileProvider.m | 3 +- .../MXScanRealmInMemoryProvider.m | 3 +- .../MXRealmCryptoStore/MXRealmCryptoStore.m | 60 +++++++++---------- 6 files changed, 54 insertions(+), 50 deletions(-) diff --git a/MatrixSDK/Aggregations/Data/Store/Realm/MXRealmAggregationsStore.m b/MatrixSDK/Aggregations/Data/Store/Realm/MXRealmAggregationsStore.m index 321f95caa2..df4ef2d381 100644 --- a/MatrixSDK/Aggregations/Data/Store/Realm/MXRealmAggregationsStore.m +++ b/MatrixSDK/Aggregations/Data/Store/Realm/MXRealmAggregationsStore.m @@ -22,7 +22,7 @@ #import "MXRealmAggregationsMapper.h" #import "MXLog.h" - +#import "RLMRealm+MatrixSDK.h" @interface MXRealmAggregationsStore () @@ -54,7 +54,7 @@ - (void)addOrUpdateReactionCount:(nonnull MXReactionCount *)reactionCount onEven { RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmAggregationsStore] addOrUpdateReactionCount" block:^{ MXRealmReactionCount *realmReactionCount = [self.mapper realmReactionCountFromReactionCount:reactionCount onEvent:eventId inRoomId:roomId]; @@ -87,7 +87,7 @@ - (void)deleteReactionCountsForReaction:(nonnull NSString *)reaction onEvent:(no { RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmAggregationsStore] deleteReactionCountsForReaction" block:^{ NSString *primaryKey = [MXRealmReactionCount primaryKeyFromEventId:eventId andReaction:reaction]; MXRealmReactionCount *realmReactionCount = [MXRealmReactionCount objectInRealm:realm forPrimaryKey:primaryKey]; @@ -102,7 +102,7 @@ - (void)setReactionCounts:(nonnull NSArray *)reactionCounts o { RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmAggregationsStore] setReactionCounts" block:^{ // Flush previous data RLMResults *realmReactionCounts = [MXRealmReactionCount objectsInRealm:realm where:@"eventId = %@", eventId]; @@ -142,7 +142,7 @@ - (void)deleteAllReactionCountsInRoom:(nonnull NSString *)roomId { RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmAggregationsStore] deleteAllReactionCountsInRoom" block:^{ RLMResults *results = [MXRealmReactionCount objectsInRealm:realm where:@"roomId = %@", roomId]; [realm deleteObjects:results]; @@ -157,7 +157,7 @@ - (void)addReactionRelation:(MXReactionRelation*)relation inRoom:(NSString*)room { RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmAggregationsStore] addReactionRelation" block:^{ MXRealmReactionRelation *realmRelation = [self.mapper realmReactionRelationFromReactionRelation:relation inRoomId:roomId]; [realm addOrUpdateObject:realmRelation]; }]; @@ -181,7 +181,7 @@ - (void)deleteReactionRelation:(MXReactionRelation*)relation { RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmAggregationsStore] deleteReactionRelation" block:^{ NSString *primaryKey = [MXRealmReactionRelation primaryKeyFromEventId:relation.eventId andReactionEventId:relation.reactionEventId]; MXRealmReactionRelation *result = [MXRealmReactionRelation objectInRealm:realm forPrimaryKey:primaryKey]; @@ -214,7 +214,7 @@ - (void)deleteAllReactionRelationsInRoom:(NSString*)roomId { RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmAggregationsStore] deleteAllReactionRelationsInRoom" block:^{ RLMResults *results = [MXRealmReactionRelation objectsInRealm:realm where:@"roomId = %@", roomId]; [realm deleteObjects:results]; @@ -228,7 +228,7 @@ - (void)deleteAll { RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmAggregationsStore] deleteAll" block:^{ [realm deleteAllObjects]; }]; } diff --git a/MatrixSDK/ContentScan/Data/Store/Realm/Event/MXRealmEventScanStore.m b/MatrixSDK/ContentScan/Data/Store/Realm/Event/MXRealmEventScanStore.m index ebd1e5f8ea..a54a0a6567 100644 --- a/MatrixSDK/ContentScan/Data/Store/Realm/Event/MXRealmEventScanStore.m +++ b/MatrixSDK/ContentScan/Data/Store/Realm/Event/MXRealmEventScanStore.m @@ -23,6 +23,7 @@ #import "MXRealmEventScanMapper.h" #import "MXRealmMediaScanStore.h" #import "MXTools.h" +#import "RLMRealm+MatrixSDK.h" @interface MXRealmEventScanStore() @@ -87,7 +88,7 @@ - (nonnull MXEventScan *)createOrUpdateWithId:(nonnull NSString *)eventId initia __block MXRealmEventScan *realmEventScan; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmEventScanStore] createOrUpdateWithId" block:^{ MXRealmEventScan *foundRealmEventScan = [self findRealmEventScanWithId:eventId inRealm:realm]; @@ -131,7 +132,7 @@ - (BOOL)updateAntivirusScanStatus:(MXAntivirusScanStatus)antivirusScanStatus for RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmEventScanStore] updateAntivirusScanStatus" block:^{ MXRealmEventScan *realmEventScan = [self findRealmEventScanWithId:eventId inRealm:realm]; if (realmEventScan) @@ -155,7 +156,7 @@ - (BOOL)updateAntivirusScanStatusFromMediaScansAntivirusScanStatusesAndAntivirus RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmEventScanStore] updateAntivirusScanStatusFromMediaScansAntivirusScanStatusesAndAntivirusScanDate" block:^{ MXRealmEventScan *realmEventScan = [self findRealmEventScanWithId:eventId inRealm:realm]; if (realmEventScan) @@ -180,7 +181,7 @@ - (void)resetAllAntivirusScanStatusInProgressToUnknown { RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmEventScanStore] resetAllAntivirusScanStatusInProgressToUnknown" block:^{ RLMResults *eventScansInProgress = [MXRealmEventScan objectsInRealm:realm where:@"%K = %d", MXRealmEventScanAttributes.antivirusScanStatusRawValue, MXAntivirusScanStatusInProgress]; for (MXRealmEventScan *eventScan in eventScansInProgress) { @@ -195,7 +196,7 @@ - (void)deleteAll __block NSArray *deletedEventScans; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmEventScanStore] deleteAll" block:^{ RLMResults *realmEventScansToDelete = [MXRealmEventScan objectsInRealm:realm withPredicate:nil]; deletedEventScans = [self eventScansFromResults:realmEventScansToDelete]; [realm deleteObjects:realmEventScansToDelete]; diff --git a/MatrixSDK/ContentScan/Data/Store/Realm/Media/MXRealmMediaScanStore.m b/MatrixSDK/ContentScan/Data/Store/Realm/Media/MXRealmMediaScanStore.m index 22a5d44bec..447ae08696 100644 --- a/MatrixSDK/ContentScan/Data/Store/Realm/Media/MXRealmMediaScanStore.m +++ b/MatrixSDK/ContentScan/Data/Store/Realm/Media/MXRealmMediaScanStore.m @@ -22,6 +22,7 @@ #import "MXTools.h" #import "MXScanRealmProvider.h" #import "MXRealmMediaScanMapper.h" +#import "RLMRealm+MatrixSDK.h" @interface MXRealmMediaScanStore() @@ -126,7 +127,7 @@ - (void)resetAllAntivirusScanStatusInProgressToUnknown { RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmMediaScanStore] resetAllAntivirusScanStatusInProgressToUnknown" block:^{ RLMResults *mediaScansInProgress = [MXRealmMediaScan objectsInRealm:realm where:@"%K = %d", MXRealmMediaScanAttributes.antivirusScanStatusRawValue, MXAntivirusScanStatusInProgress]; for (MXRealmMediaScan *mediaScan in mediaScansInProgress) { @@ -157,7 +158,7 @@ - (void)deleteAll __block NSArray *deletedMediaScans; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmMediaScanStore] deleteAll" block:^{ RLMResults *realmMediaScansToDelete = [MXRealmMediaScan objectsInRealm:realm withPredicate:nil]; deletedMediaScans = [self mediaScansFromResults:realmMediaScansToDelete]; [realm deleteObjects:realmMediaScansToDelete]; @@ -195,7 +196,7 @@ - (nonnull MXRealmMediaScan*)findOrCreateRealmMediaScanWithURL:(nonnull NSString if (useTransaction) { - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmMediaScanStore] findOrCreateRealmMediaScanWithURL" block:^{ realmOperations(); }]; } @@ -218,7 +219,7 @@ - (BOOL)updateRealmMediaScanWithURL:(nonnull NSString*)url updateHandler:(void ( RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmMediaScanStore] updateRealmMediaScanWithURL" block:^{ MXRealmMediaScan *realmMediaScan = [self findRealmMediaScanWithURL:url inRealm:realm]; diff --git a/MatrixSDK/ContentScan/Data/Store/Realm/RealmProvider/MXScanRealmFileProvider.m b/MatrixSDK/ContentScan/Data/Store/Realm/RealmProvider/MXScanRealmFileProvider.m index c7909dfbf9..e383f418ee 100644 --- a/MatrixSDK/ContentScan/Data/Store/Realm/RealmProvider/MXScanRealmFileProvider.m +++ b/MatrixSDK/ContentScan/Data/Store/Realm/RealmProvider/MXScanRealmFileProvider.m @@ -22,6 +22,7 @@ #import "MXRealmMediaScan.h" #import "MXLog.h" +#import "RLMRealm+MatrixSDK.h" @interface MXScanRealmFileProvider() @@ -64,7 +65,7 @@ - (void)deleteAllObjects { RLMRealm *realm = [self realm]; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXScanRealmFileProvider] deleteAllObjects" block:^{ [realm deleteAllObjects]; }]; } diff --git a/MatrixSDK/ContentScan/Data/Store/Realm/RealmProvider/MXScanRealmInMemoryProvider.m b/MatrixSDK/ContentScan/Data/Store/Realm/RealmProvider/MXScanRealmInMemoryProvider.m index e19e114e33..3b13a1e4d8 100644 --- a/MatrixSDK/ContentScan/Data/Store/Realm/RealmProvider/MXScanRealmInMemoryProvider.m +++ b/MatrixSDK/ContentScan/Data/Store/Realm/RealmProvider/MXScanRealmInMemoryProvider.m @@ -20,6 +20,7 @@ #import "MXRealmMediaScan.h" #import "MXLog.h" +#import "RLMRealm+MatrixSDK.h" @interface MXScanRealmInMemoryProvider() @@ -62,7 +63,7 @@ - (void)deleteAllObjects { RLMRealm *realm = [self realm]; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXScanRealmInMemoryProvider] deleteAllObjects" block:^{ [realm deleteAllObjects]; }]; } diff --git a/MatrixSDK/Crypto/Data/Store/MXRealmCryptoStore/MXRealmCryptoStore.m b/MatrixSDK/Crypto/Data/Store/MXRealmCryptoStore/MXRealmCryptoStore.m index f9d62e257c..af616e6132 100644 --- a/MatrixSDK/Crypto/Data/Store/MXRealmCryptoStore/MXRealmCryptoStore.m +++ b/MatrixSDK/Crypto/Data/Store/MXRealmCryptoStore/MXRealmCryptoStore.m @@ -30,7 +30,7 @@ #import "MatrixSDKSwiftHeader.h" #import "MXRealmHelper.h" #import "MXBackgroundModeHandler.h" - +#import "RLMRealm+MatrixSDK.h" NSUInteger const kMXRealmCryptoStoreVersion = 17; @@ -413,7 +413,7 @@ + (void)_deleteStoreWithCredentials:(MXCredentials*)credentials readOnly:(BOOL)r if (!error) { MXLogDebug(@"[MXRealmCryptoStore] deleteStore: Delete at least its content"); - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmCryptoStore] deleteStore" block:^{ [realm deleteAllObjects]; }]; } @@ -476,7 +476,7 @@ - (void)storeDeviceId:(NSString*)deviceId { MXRealmOlmAccount *account = self.accountInCurrentThread; - [account.realm transactionWithBlock:^{ + [account.realm transactionWithName:@"[MXRealmCryptoStore] storeDeviceId" block:^{ account.deviceId = deviceId; }]; } @@ -494,7 +494,7 @@ - (void)setAccount:(OLMAccount*)olmAccount MXRealmOlmAccount *account = self.accountInCurrentThread; - [account.realm transactionWithBlock:^{ + [account.realm transactionWithName:@"[MXRealmCryptoStore] setAccount" block:^{ account.olmAccountData = [NSKeyedArchiver archivedDataWithRootObject:olmAccount]; }]; @@ -551,7 +551,7 @@ - (void)performAccountOperationWithBlock:(void (^)(OLMAccount *))block - (void)storeDeviceSyncToken:(NSString*)deviceSyncToken { MXRealmOlmAccount *account = self.accountInCurrentThread; - [account.realm transactionWithBlock:^{ + [account.realm transactionWithName:@"[MXRealmCryptoStore] storeDeviceSyncToken" block:^{ account.deviceSyncToken = deviceSyncToken; }]; } @@ -568,7 +568,7 @@ - (void)storeDeviceForUser:(NSString*)userID device:(MXDeviceInfo*)device RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmCryptoStore] storeDeviceForUser" block:^{ MXRealmUser *realmUser = [MXRealmUser objectsInRealm:realm where:@"userId = %@", userID].firstObject; if (!realmUser) @@ -630,7 +630,7 @@ - (void)storeDevicesForUser:(NSString*)userID devices:(NSDictionary*)statusMap { MXRealmOlmAccount *account = self.accountInCurrentThread; - [account.realm transactionWithBlock:^{ + [account.realm transactionWithName:@"[MXRealmCryptoStore] storeDeviceTrackingStatus" block:^{ account.deviceTrackingStatusData = [NSKeyedArchiver archivedDataWithRootObject:statusMap]; }]; @@ -701,7 +701,7 @@ - (void)storeCrossSigningKeys:(MXCrossSigningInfo*)crossSigningInfo { RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmCryptoStore] storeCrossSigningKeys" block:^{ MXRealmUser *realmUser = [MXRealmUser objectsInRealm:realm where:@"userId = %@", crossSigningInfo.userId].firstObject; if (!realmUser) @@ -760,7 +760,7 @@ - (void)storeAlgorithmForRoom:(NSString*)roomId algorithm:(NSString*)algorithm NSDate *startDate = [NSDate date]; RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmCryptoStore] storeAlgorithmForRoom" block:^{ MXRealmRoomAlgorithm *roomAlgorithm = [self realmRoomAlgorithmForRoom:roomId inRealm:realm]; if (roomAlgorithm) @@ -793,7 +793,7 @@ - (void)storeBlacklistUnverifiedDevicesInRoom:(NSString *)roomId blacklist:(BOOL NSDate *startDate = [NSDate date]; RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmCryptoStore] storeBlacklistUnverifiedDevicesInRoom" block:^{ MXRealmRoomAlgorithm *roomAlgorithm = [self realmRoomAlgorithmForRoom:roomId inRealm:realm]; if (roomAlgorithm) @@ -832,7 +832,7 @@ - (void)storeSession:(MXOlmSession*)session forDevice:(NSString*)deviceKey NSDate *startDate = [NSDate date]; RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmCryptoStore] storeSession" block:^{ MXRealmOlmSession *realmOlmSession = [MXRealmOlmSession objectsInRealm:realm where:@"sessionId = %@ AND deviceKey = %@", session.session.sessionIdentifier, deviceKey].firstObject; if (realmOlmSession) @@ -945,7 +945,7 @@ - (void)storeInboundGroupSessions:(NSArray*)sessions NSDate *startDate = [NSDate date]; RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmCryptoStore] storeInboundGroupSessions" block:^{ for (MXOlmInboundGroupSession *session in sessions) { @@ -1057,7 +1057,7 @@ - (void)performSessionOperationWithGroupSessionWithId:(NSString*)sessionId sende - (void)removeInboundGroupSessionWithId:(NSString*)sessionId andSenderKey:(NSString*)senderKey { RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmCryptoStore] removeInboundGroupSessionWithId" block:^{ RLMResults *realmSessions = [MXRealmOlmInboundGroupSession objectsInRealm:realm where:@"sessionId = %@ AND senderKey = %@", sessionId, senderKey]; @@ -1076,7 +1076,7 @@ - (MXOlmOutboundGroupSession *)storeOutboundGroupSession:(OLMOutboundGroupSessio __block MXOlmOutboundGroupSession *storedSession = nil; RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmCryptoStore] storeOutboundGroupSession" block:^{ MXRealmOlmOutboundGroupSession *realmSession = [MXRealmOlmOutboundGroupSession objectsInRealm:realm where:@"roomId = %@", roomId].firstObject; if (realmSession && [realmSession.sessionId isEqual:session.sessionIdentifier]) @@ -1157,7 +1157,7 @@ - (MXOlmOutboundGroupSession *)outboundGroupSessionWithRoomId:(NSString*)roomId - (void)removeOutboundGroupSessionWithRoomId:(NSString*)roomId { RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmCryptoStore] removeOutboundGroupSessionWithRoomId" block:^{ RLMResults *realmSessions = [MXRealmOlmOutboundGroupSession objectsInRealm:realm where:@"roomId = %@", roomId]; [realm deleteObjects:realmSessions]; @@ -1171,7 +1171,7 @@ - (void)storeSharedDevices:(MXUsersDevicesMap *)devices messageIndex RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmCryptoStore] storeSharedDevices" block:^{ for (NSString *userId in [devices userIds]) { @@ -1255,7 +1255,7 @@ - (NSNumber *)messageIndexForSharedDeviceInRoomWithId:(NSString *)roomId session - (void)setBackupVersion:(NSString *)backupVersion { MXRealmOlmAccount *account = self.accountInCurrentThread; - [account.realm transactionWithBlock:^{ + [account.realm transactionWithName:@"[MXRealmCryptoStore] setBackupVersion" block:^{ account.backupVersion = backupVersion; }]; } @@ -1269,7 +1269,7 @@ - (NSString *)backupVersion - (void)resetBackupMarkers { RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmCryptoStore] resetBackupMarkers" block:^{ RLMResults *realmSessions = [MXRealmOlmInboundGroupSession allObjectsInRealm:realm]; @@ -1285,7 +1285,7 @@ - (void)resetBackupMarkers - (void)markBackupDoneForInboundGroupSessions:(NSArray*)sessions { RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmCryptoStore] markBackupDoneForInboundGroupSessions" block:^{ for (MXOlmInboundGroupSession *session in sessions) { @@ -1387,7 +1387,7 @@ - (MXOutgoingRoomKeyRequest*)outgoingRoomKeyRequestWithState:(MXRoomKeyRequestSt - (void)storeOutgoingRoomKeyRequest:(MXOutgoingRoomKeyRequest*)request { RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmCryptoStore] storeOutgoingRoomKeyRequest" block:^{ NSString *requestBodyString = [MXTools serialiseJSONObject:request.requestBody]; NSString *requestBodyHash = [MXCryptoTools canonicalJSONStringForJSON:request.requestBody]; @@ -1410,7 +1410,7 @@ - (void)storeOutgoingRoomKeyRequest:(MXOutgoingRoomKeyRequest*)request - (void)updateOutgoingRoomKeyRequest:(MXOutgoingRoomKeyRequest*)request { RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmCryptoStore] updateOutgoingRoomKeyRequest" block:^{ MXRealmOutgoingRoomKeyRequest *realmOutgoingRoomKeyRequest = [MXRealmOutgoingRoomKeyRequest objectsInRealm:realm where:@"requestId = %@", request.requestId].firstObject; @@ -1427,7 +1427,7 @@ - (void)updateOutgoingRoomKeyRequest:(MXOutgoingRoomKeyRequest*)request - (void)deleteOutgoingRoomKeyRequestWithRequestId:(NSString*)requestId { RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmCryptoStore] deleteOutgoingRoomKeyRequestWithRequestId" block:^{ RLMResults *realmOutgoingRoomKeyRequests = [MXRealmOutgoingRoomKeyRequest objectsInRealm:realm where:@"requestId = %@", requestId]; @@ -1441,7 +1441,7 @@ - (void)deleteOutgoingRoomKeyRequestWithRequestId:(NSString*)requestId - (void)storeIncomingRoomKeyRequest:(MXIncomingRoomKeyRequest*)request { RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmCryptoStore] storeIncomingRoomKeyRequest" block:^{ MXRealmIncomingRoomKeyRequest *realmIncomingRoomKeyRequest = [[MXRealmIncomingRoomKeyRequest alloc] initWithValue:@{ @@ -1457,7 +1457,7 @@ - (void)storeIncomingRoomKeyRequest:(MXIncomingRoomKeyRequest*)request - (void)deleteIncomingRoomKeyRequest:(NSString*)requestId fromUser:(NSString*)userId andDevice:(NSString*)deviceId { RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmCryptoStore] deleteIncomingRoomKeyRequest" block:^{ RLMResults *realmIncomingRoomKeyRequests = [MXRealmIncomingRoomKeyRequest objectsInRealm:realm where:@"requestId = %@ AND userId = %@ AND deviceId = %@", requestId, userId, deviceId]; @@ -1504,7 +1504,7 @@ - (MXIncomingRoomKeyRequest*)incomingRoomKeyRequestWithRequestId:(NSString*)requ - (void)storeSecret:(NSString*)secret withSecretId:(NSString*)secretId { RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmCryptoStore] storeSecret" block:^{ MXRealmSecret *realmSecret; @@ -1582,7 +1582,7 @@ - (NSString*)secretWithSecretId:(NSString*)secretId - (void)deleteSecretWithSecretId:(NSString*)secretId { RLMRealm *realm = self.realm; - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmCryptoStore] deleteSecretWithSecretId" block:^{ [realm deleteObjects:[MXRealmSecret objectsInRealm:realm where:@"secretId = %@", secretId]]; }]; } @@ -1599,7 +1599,7 @@ - (BOOL)globalBlacklistUnverifiedDevices - (void)setGlobalBlacklistUnverifiedDevices:(BOOL)globalBlacklistUnverifiedDevices { MXRealmOlmAccount *account = self.accountInCurrentThread; - [account.realm transactionWithBlock:^{ + [account.realm transactionWithName:@"[MXRealmCryptoStore] setGlobalBlacklistUnverifiedDevices" block:^{ account.globalBlacklistUnverifiedDevices = globalBlacklistUnverifiedDevices; }]; } @@ -1616,7 +1616,7 @@ - (MXCryptoVersion)cryptoVersion -(void)setCryptoVersion:(MXCryptoVersion)cryptoVersion { MXRealmOlmAccount *account = self.accountInCurrentThread; - [account.realm transactionWithBlock:^{ + [account.realm transactionWithName:@"[MXRealmCryptoStore] setCryptoVersion" block:^{ account.cryptoVersion = cryptoVersion; }]; } @@ -2194,7 +2194,7 @@ + (BOOL)finaliseMigrationWith:(RLMMigration *)migration oldSchemaVersion:(uint64 */ + (void)cleanDuplicatedDevicesInRealm:(RLMRealm*)realm { - [realm transactionWithBlock:^{ + [realm transactionWithName:@"[MXRealmCryptoStore] cleanDuplicatedDevicesInRealm" block:^{ // Due to a bug (https://github.com/vector-im/riot-ios/issues/2132), there were // duplicated devices living in the database without no more relationship with From 3e7e99b32fff0865ffa508acbbebd95d574e4f0e Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Thu, 7 Oct 2021 18:25:47 +0300 Subject: [PATCH 32/42] Fix non-modular header --- MatrixSDK/Utils/Categories/RLMRealm+MatrixSDK.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MatrixSDK/Utils/Categories/RLMRealm+MatrixSDK.h b/MatrixSDK/Utils/Categories/RLMRealm+MatrixSDK.h index 8000559eed..7c435d8825 100644 --- a/MatrixSDK/Utils/Categories/RLMRealm+MatrixSDK.h +++ b/MatrixSDK/Utils/Categories/RLMRealm+MatrixSDK.h @@ -14,7 +14,7 @@ // limitations under the License. // -#import "RLMRealm.h" +#import NS_ASSUME_NONNULL_BEGIN From e249f548480527113669aaa3ff502795e9119601 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Thu, 7 Oct 2021 18:29:36 +0300 Subject: [PATCH 33/42] Add changelog --- changelog.d/4964.change | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/4964.change diff --git a/changelog.d/4964.change b/changelog.d/4964.change new file mode 100644 index 0000000000..59f6df0d36 --- /dev/null +++ b/changelog.d/4964.change @@ -0,0 +1 @@ +Start a background task for every Realm transaction. From 1ae7bb67d3950c92f3bd6a7655dd9dca6ffb43f9 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Thu, 7 Oct 2021 23:58:31 +0300 Subject: [PATCH 34/42] Refactor long method names --- MatrixSDK/Utils/MXUIKitApplicationStateService.swift | 8 ++++---- MatrixSDK/Utils/MXUIKitBackgroundModeHandler.m | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/MatrixSDK/Utils/MXUIKitApplicationStateService.swift b/MatrixSDK/Utils/MXUIKitApplicationStateService.swift index 0f6260aa2f..a50264b325 100644 --- a/MatrixSDK/Utils/MXUIKitApplicationStateService.swift +++ b/MatrixSDK/Utils/MXUIKitApplicationStateService.swift @@ -37,7 +37,7 @@ public class MXUIKitApplicationStateService: NSObject { // MARK: - Static Method - static public func readableApplicationState(applicationState: UIApplication.State) -> NSString { + static public func readableApplicationState(_ applicationState: UIApplication.State) -> NSString { switch applicationState { case .active: return "active" @@ -50,7 +50,7 @@ public class MXUIKitApplicationStateService: NSObject { } } - static public func readableEstimatedBackgroundTimeRemaining(backgroundTimeRemaining: TimeInterval) -> NSString { + static public func readableEstimatedBackgroundTimeRemaining(_ backgroundTimeRemaining: TimeInterval) -> NSString { if backgroundTimeRemaining == .greatestFiniteMagnitude { return "undetermined" } @@ -90,8 +90,8 @@ public class MXUIKitApplicationStateService: NSObject { let newApplicationState = self.sharedApplicationState if newApplicationState != applicationState { - let applicationStateString = MXUIKitApplicationStateService.readableApplicationState(applicationState: applicationState) - let newApplicationStateString = MXUIKitApplicationStateService.readableApplicationState(applicationState: newApplicationState) + let applicationStateString = MXUIKitApplicationStateService.readableApplicationState(applicationState) + let newApplicationStateString = MXUIKitApplicationStateService.readableApplicationState(newApplicationState) MXLog.debug("[MXUIKitApplicationStateService] applicationStateDidChange: from \(applicationStateString) to \(newApplicationStateString)") applicationState = newApplicationState diff --git a/MatrixSDK/Utils/MXUIKitBackgroundModeHandler.m b/MatrixSDK/Utils/MXUIKitBackgroundModeHandler.m index 7e5ee40fc0..99657423bd 100644 --- a/MatrixSDK/Utils/MXUIKitBackgroundModeHandler.m +++ b/MatrixSDK/Utils/MXUIKitBackgroundModeHandler.m @@ -75,8 +75,8 @@ - (instancetype)init if (backgroundTask) { - NSString *readableAppState = [MXUIKitApplicationStateService readableApplicationStateWithApplicationState:applicationStateService.applicationState]; - NSString *readableBackgroundTimeRemaining = [MXUIKitApplicationStateService readableEstimatedBackgroundTimeRemainingWithBackgroundTimeRemaining:applicationStateService.backgroundTimeRemaining]; + NSString *readableAppState = [MXUIKitApplicationStateService readableApplicationState:applicationStateService.applicationState]; + NSString *readableBackgroundTimeRemaining = [MXUIKitApplicationStateService readableEstimatedBackgroundTimeRemaining:applicationStateService.backgroundTimeRemaining]; MXLogDebug(@"[MXBackgroundTask] Background task %@ started with app state: %@ and estimated background time remaining: %@", backgroundTask.name, readableAppState, readableBackgroundTimeRemaining); } From e1341eee9f1975a30e5d1d0d956f676617c24910 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Fri, 8 Oct 2021 00:00:10 +0300 Subject: [PATCH 35/42] Introduce reusable background tasks --- MatrixSDK/Utils/MXBackgroundModeHandler.h | 30 +++++++++ MatrixSDK/Utils/MXBackgroundTask.h | 17 +++-- .../Utils/MXUIKitBackgroundModeHandler.m | 64 ++++++++++++++++++- MatrixSDK/Utils/MXUIKitBackgroundTask.h | 1 + MatrixSDK/Utils/MXUIKitBackgroundTask.m | 10 ++- 5 files changed, 113 insertions(+), 9 deletions(-) diff --git a/MatrixSDK/Utils/MXBackgroundModeHandler.h b/MatrixSDK/Utils/MXBackgroundModeHandler.h index 5d81e38b06..2a41a7a2f0 100644 --- a/MatrixSDK/Utils/MXBackgroundModeHandler.h +++ b/MatrixSDK/Utils/MXBackgroundModeHandler.h @@ -31,7 +31,37 @@ NS_ASSUME_NONNULL_BEGIN */ @protocol MXBackgroundModeHandler +/** + Create a background task with a name. + + @param name name of the background task + + @return background task + */ +- (nullable id)startBackgroundTaskWithName:(NSString *)name; + +/** + Create a background task with a name and expirationHandler. + + @param name name of the background task + @param expirationHandler a block to be called when the background task is about to expire + + @return background task + */ +- (nullable id)startBackgroundTaskWithName:(NSString *)name + expirationHandler:(nullable MXBackgroundTaskExpirationHandler)expirationHandler; + +/** + Create a background task with a name and expirationHandler. + + @param name name of the background task + @param reusable flag indicating the background task will be reusable + @param expirationHandler a block to be called when the background task is about to expire + + @return background task + */ - (nullable id)startBackgroundTaskWithName:(NSString *)name + reusable:(BOOL)reusable expirationHandler:(nullable MXBackgroundTaskExpirationHandler)expirationHandler; @end diff --git a/MatrixSDK/Utils/MXBackgroundTask.h b/MatrixSDK/Utils/MXBackgroundTask.h index da0cc34b01..a8a2f1b4ec 100644 --- a/MatrixSDK/Utils/MXBackgroundTask.h +++ b/MatrixSDK/Utils/MXBackgroundTask.h @@ -28,11 +28,20 @@ typedef void (^MXBackgroundTaskExpirationHandler)(void); */ @protocol MXBackgroundTask -// Name of the background task for debug. -@property (nonatomic, strong, readonly) NSString *name; +/** + Name of the background task for debug. + */ +@property (nonatomic, copy, readonly) NSString *name; -// Yes if the background task is currently running. -@property (nonatomic, readonly) BOOL isRunning; +/** + YES if the background task is currently running. + */ +@property (nonatomic, readonly, getter=isRunning) BOOL running; + +/** + Flag indicating the background task is reusable. If reusable, `name` is the key to distinguish background tasks. + */ +@property (nonatomic, readonly, getter=isReusable) BOOL reusable; /** Stop the background task. Cannot be started anymore. diff --git a/MatrixSDK/Utils/MXUIKitBackgroundModeHandler.m b/MatrixSDK/Utils/MXUIKitBackgroundModeHandler.m index 99657423bd..45bb67c8d6 100644 --- a/MatrixSDK/Utils/MXUIKitBackgroundModeHandler.m +++ b/MatrixSDK/Utils/MXUIKitBackgroundModeHandler.m @@ -35,6 +35,11 @@ @interface MXUIKitBackgroundModeHandler () { MXUIKitApplicationStateService *applicationStateService; + + /** + Cache to store reusable background tasks. + */ + NSMapTable> *reusableTasks; } @end @@ -47,6 +52,7 @@ - (instancetype)init if (self) { applicationStateService = [MXUIKitApplicationStateService new]; + reusableTasks = [NSMapTable weakToWeakObjectsMapTable]; } return self; } @@ -55,7 +61,20 @@ - (instancetype)init #pragma mark - MXBackgroundModeHandler - (nullable id)startBackgroundTaskWithName:(NSString *)name +{ + return [self startBackgroundTaskWithName:name expirationHandler:nil]; +} + +- (nullable id)startBackgroundTaskWithName:(NSString *)name + expirationHandler:(nullable MXBackgroundTaskExpirationHandler)expirationHandler +{ + return [self startBackgroundTaskWithName:name reusable:NO expirationHandler:expirationHandler]; +} + +- (nullable id)startBackgroundTaskWithName:(NSString *)name + reusable:(BOOL)reusable expirationHandler:(nullable MXBackgroundTaskExpirationHandler)expirationHandler + { // application is in background and not enough time to start this task if (applicationStateService.applicationState == UIApplicationStateBackground && @@ -71,14 +90,55 @@ - (instancetype)init return nil; } - id backgroundTask = [[MXUIKitBackgroundTask alloc] initAndStartWithName:name expirationHandler:expirationHandler]; + BOOL created = NO; + + __block id backgroundTask; + if (reusable) + { + // reusable + + // first look in the cache + backgroundTask = [reusableTasks objectForKey:name]; + + // create if not found or not running + // According to the documentation, a weak-values map table doesn't have to remove objects immediately when they are released, so also check the running state of the task. + if (backgroundTask == nil || !backgroundTask.isRunning) + { + backgroundTask = [[MXUIKitBackgroundTask alloc] initAndStartWithName:name + reusable:reusable + expirationHandler:^{ + // remove when expired + [self->reusableTasks removeObjectForKey:backgroundTask.name]; + + if (expirationHandler) + { + expirationHandler(); + } + }]; + created = YES; + + // cache the task if successfully created + if (backgroundTask) + { + [reusableTasks setObject:backgroundTask forKey:name]; + } + } + } + else + { + // not reusable, just create one and continue. Do not store non-reusable tasks in the cache + backgroundTask = [[MXUIKitBackgroundTask alloc] initAndStartWithName:name + reusable:reusable + expirationHandler:expirationHandler]; + created = YES; + } if (backgroundTask) { NSString *readableAppState = [MXUIKitApplicationStateService readableApplicationState:applicationStateService.applicationState]; NSString *readableBackgroundTimeRemaining = [MXUIKitApplicationStateService readableEstimatedBackgroundTimeRemaining:applicationStateService.backgroundTimeRemaining]; - MXLogDebug(@"[MXBackgroundTask] Background task %@ started with app state: %@ and estimated background time remaining: %@", backgroundTask.name, readableAppState, readableBackgroundTimeRemaining); + MXLogDebug(@"[MXBackgroundTask] Background task %@ %@ with app state: %@ and estimated background time remaining: %@", backgroundTask.name, (created ? @"started" : @"reused"), readableAppState, readableBackgroundTimeRemaining); } return backgroundTask; diff --git a/MatrixSDK/Utils/MXUIKitBackgroundTask.h b/MatrixSDK/Utils/MXUIKitBackgroundTask.h index 181454520c..32a1257fff 100644 --- a/MatrixSDK/Utils/MXUIKitBackgroundTask.h +++ b/MatrixSDK/Utils/MXUIKitBackgroundTask.h @@ -27,6 +27,7 @@ NS_ASSUME_NONNULL_BEGIN @interface MXUIKitBackgroundTask : NSObject - (nullable instancetype)initAndStartWithName:(NSString*)name + reusable:(BOOL)reusable expirationHandler:(nullable MXBackgroundTaskExpirationHandler)expirationHandler; @end diff --git a/MatrixSDK/Utils/MXUIKitBackgroundTask.m b/MatrixSDK/Utils/MXUIKitBackgroundTask.m index 12de55f962..ef01b841a9 100644 --- a/MatrixSDK/Utils/MXUIKitBackgroundTask.m +++ b/MatrixSDK/Utils/MXUIKitBackgroundTask.m @@ -25,8 +25,9 @@ @interface MXUIKitBackgroundTask () @property (nonatomic) UIBackgroundTaskIdentifier identifier; -@property (nonatomic, strong) NSString *name; +@property (nonatomic, copy) NSString *name; @property (nonatomic, copy, nullable) MXBackgroundTaskExpirationHandler expirationHandler; +@property (nonatomic, assign) BOOL reusable; @property (nonatomic, strong, nullable) NSDate *startDate; @end @@ -36,6 +37,7 @@ @implementation MXUIKitBackgroundTask #pragma Setup - (instancetype)initWithName:(NSString*)name + reusable:(BOOL)reusable expirationHandler:(MXBackgroundTaskExpirationHandler)expirationHandler { self = [super init]; @@ -43,15 +45,17 @@ - (instancetype)initWithName:(NSString*)name { self.identifier = UIBackgroundTaskInvalid; self.name = name; + self.reusable = reusable; self.expirationHandler = expirationHandler; } return self; } - (nullable instancetype)initAndStartWithName:(NSString*)name - expirationHandler:(MXBackgroundTaskExpirationHandler)expirationHandler + reusable:(BOOL)reusable + expirationHandler:(nullable MXBackgroundTaskExpirationHandler)expirationHandler { - self = [self initWithName:name expirationHandler:expirationHandler]; + self = [self initWithName:name reusable:reusable expirationHandler:expirationHandler]; if (self) { UIApplication *sharedApplication = [self sharedApplication]; From 712feb272a71351c9517308a05e6a2c8c383fb9a Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Fri, 8 Oct 2021 00:01:21 +0300 Subject: [PATCH 36/42] Remove extra params --- .../Data/Store/MXRealmCryptoStore/MXRealmCryptoStore.m | 6 +++--- MatrixSDK/Data/Store/MXFileStore/MXFileStore.m | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MatrixSDK/Crypto/Data/Store/MXRealmCryptoStore/MXRealmCryptoStore.m b/MatrixSDK/Crypto/Data/Store/MXRealmCryptoStore/MXRealmCryptoStore.m index af616e6132..d6995aa7af 100644 --- a/MatrixSDK/Crypto/Data/Store/MXRealmCryptoStore/MXRealmCryptoStore.m +++ b/MatrixSDK/Crypto/Data/Store/MXRealmCryptoStore/MXRealmCryptoStore.m @@ -516,7 +516,7 @@ - (void)performAccountOperationWithBlock:(void (^)(OLMAccount *))block // Make sure write operations complete in background to avoid to keep the realm internal lock until the app resumes. // Thus, other components (Notification Extension Service, Share Extension, ...) will not be blocked by this lock. id handler = [MXSDKOptions sharedInstance].backgroundModeHandler; - id backgroundTask = [handler startBackgroundTaskWithName:@"[MXRealmCryptoStore] performAccountOperationWithBlock" expirationHandler:nil]; + id backgroundTask = [handler startBackgroundTaskWithName:@"[MXRealmCryptoStore] performAccountOperationWithBlock"]; MXRealmOlmAccount *account = self.accountInCurrentThread; if (account.olmAccountData) @@ -880,7 +880,7 @@ - (void)performSessionOperationWithDevice:(NSString*)deviceKey andSessionId:(NSS // Make sure write operations complete in background to avoid to keep the realm internal lock until the app resumes. // Thus, other components (Notification Extension Service, Share Extension, ...) will not be blocked by this lock. id handler = [MXSDKOptions sharedInstance].backgroundModeHandler; - id backgroundTask = [handler startBackgroundTaskWithName:@"[MXRealmCryptoStore] performSessionOperationWithDevice" expirationHandler:nil]; + id backgroundTask = [handler startBackgroundTaskWithName:@"[MXRealmCryptoStore] performSessionOperationWithDevice"]; RLMRealm *realm = self.realm; @@ -1006,7 +1006,7 @@ - (void)performSessionOperationWithGroupSessionWithId:(NSString*)sessionId sende // Make sure write operations complete in background to avoid to keep the realm internal lock until the app resumes. // Thus, other components (Notification Extension Service, Share Extension, ...) will not be blocked by this lock. id handler = [MXSDKOptions sharedInstance].backgroundModeHandler; - id backgroundTask = [handler startBackgroundTaskWithName:@"[MXRealmCryptoStore] performSessionOperationWithGroupSessionWithId" expirationHandler:nil]; + id backgroundTask = [handler startBackgroundTaskWithName:@"[MXRealmCryptoStore] performSessionOperationWithGroupSessionWithId"]; RLMRealm *realm = self.realm; diff --git a/MatrixSDK/Data/Store/MXFileStore/MXFileStore.m b/MatrixSDK/Data/Store/MXFileStore/MXFileStore.m index 22d4f1c754..b50afc191b 100644 --- a/MatrixSDK/Data/Store/MXFileStore/MXFileStore.m +++ b/MatrixSDK/Data/Store/MXFileStore/MXFileStore.m @@ -184,7 +184,7 @@ - (void)openWithCredentials:(MXCredentials*)someCredentials onComplete:(void (^) id handler = [MXSDKOptions sharedInstance].backgroundModeHandler; - id backgroundTask = [handler startBackgroundTaskWithName:@"[MXFileStore] openWithCredentials:onComplete:failure:" expirationHandler:nil]; + id backgroundTask = [handler startBackgroundTaskWithName:@"[MXFileStore] openWithCredentials:onComplete:failure:"]; /* Mount data corresponding to the account credentials. From 3b9e004cc60ed26a6a8ebad94719795fd1e3d438 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Fri, 8 Oct 2021 00:01:52 +0300 Subject: [PATCH 37/42] Make background tasks reusable for Realm transactions --- MatrixSDK/Utils/Categories/RLMRealm+MatrixSDK.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MatrixSDK/Utils/Categories/RLMRealm+MatrixSDK.m b/MatrixSDK/Utils/Categories/RLMRealm+MatrixSDK.m index bf752f8f3f..891cdc0349 100644 --- a/MatrixSDK/Utils/Categories/RLMRealm+MatrixSDK.m +++ b/MatrixSDK/Utils/Categories/RLMRealm+MatrixSDK.m @@ -29,7 +29,7 @@ - (void)transactionWithName:(NSString *)name block:(void (^)(void))block - (BOOL)transactionWithName:(NSString *)name block:(void (^)(void))block error:(NSError * _Nullable __autoreleasing *)outError { id handler = [MXSDKOptions sharedInstance].backgroundModeHandler; - id backgroundTask = [handler startBackgroundTaskWithName:name expirationHandler:nil]; + id backgroundTask = [handler startBackgroundTaskWithName:name reusable:YES expirationHandler:nil]; BOOL result = [self transactionWithBlock:block error:outError]; [backgroundTask stop]; return result; From 120adfae931f7dd38ac366223e5cf26e94eece4e Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Fri, 8 Oct 2021 04:11:10 +0300 Subject: [PATCH 38/42] Refactor background task api to handle macOS target --- MatrixSDK.xcodeproj/project.pbxproj | 26 ++++- MatrixSDK/MatrixSDK.h | 3 + MatrixSDK/Utils/MXApplicationProtocol.h | 39 ++++++++ MatrixSDK/Utils/MXBackgroundTask.h | 7 +- .../Utils/MXUIKitBackgroundModeHandler.h | 17 +++- .../Utils/MXUIKitBackgroundModeHandler.m | 48 +++++++-- MatrixSDK/Utils/MXUIKitBackgroundTask.h | 10 +- MatrixSDK/Utils/MXUIKitBackgroundTask.m | 99 ++++++++++++++----- .../MatrixSDKTests-Bridging-Header.h | 3 + 9 files changed, 204 insertions(+), 48 deletions(-) create mode 100644 MatrixSDK/Utils/MXApplicationProtocol.h diff --git a/MatrixSDK.xcodeproj/project.pbxproj b/MatrixSDK.xcodeproj/project.pbxproj index 980522289b..b08915689f 100644 --- a/MatrixSDK.xcodeproj/project.pbxproj +++ b/MatrixSDK.xcodeproj/project.pbxproj @@ -466,8 +466,8 @@ 32A31BC920D401FC005916C7 /* MXRoomFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 32A31BC720D401FC005916C7 /* MXRoomFilter.m */; }; 32A9770421626E5C00919CC0 /* MXServerNotices.h in Headers */ = {isa = PBXBuildFile; fileRef = 32A9770221626E5C00919CC0 /* MXServerNotices.h */; settings = {ATTRIBUTES = (Public, ); }; }; 32A9770521626E5C00919CC0 /* MXServerNotices.m in Sources */ = {isa = PBXBuildFile; fileRef = 32A9770321626E5C00919CC0 /* MXServerNotices.m */; }; - 32A9E8241EF4026E0081358A /* MXBackgroundModeHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 32A9E8211EF4026E0081358A /* MXBackgroundModeHandler.h */; }; - 32A9E8251EF4026E0081358A /* MXUIKitBackgroundModeHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 32A9E8221EF4026E0081358A /* MXUIKitBackgroundModeHandler.h */; }; + 32A9E8241EF4026E0081358A /* MXBackgroundModeHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 32A9E8211EF4026E0081358A /* MXBackgroundModeHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 32A9E8251EF4026E0081358A /* MXUIKitBackgroundModeHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 32A9E8221EF4026E0081358A /* MXUIKitBackgroundModeHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; 32A9E8261EF4026E0081358A /* MXUIKitBackgroundModeHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 32A9E8231EF4026E0081358A /* MXUIKitBackgroundModeHandler.m */; }; 32A9F8DE244720B10069C65B /* MXThrottler.h in Headers */ = {isa = PBXBuildFile; fileRef = 32A9F8DC244720B10069C65B /* MXThrottler.h */; settings = {ATTRIBUTES = (Public, ); }; }; 32A9F8DF244720B10069C65B /* MXThrottler.h in Headers */ = {isa = PBXBuildFile; fileRef = 32A9F8DC244720B10069C65B /* MXThrottler.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -986,7 +986,7 @@ B14EF2A72397E90400758AF0 /* MXPushRuleConditionChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = 32DC15CC1A8CF7AE006F9AD3 /* MXPushRuleConditionChecker.h */; settings = {ATTRIBUTES = (Public, ); }; }; B14EF2A82397E90400758AF0 /* MXServiceTermsRestClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 3294FD9B22F321B0007F1E60 /* MXServiceTermsRestClient.h */; }; B14EF2A92397E90400758AF0 /* MXServerNoticeContent.h in Headers */ = {isa = PBXBuildFile; fileRef = 32954017216385F100E300FC /* MXServerNoticeContent.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B14EF2AB2397E90400758AF0 /* MXUIKitBackgroundTask.h in Headers */ = {isa = PBXBuildFile; fileRef = B17B2BDA2369FC81009D6650 /* MXUIKitBackgroundTask.h */; }; + B14EF2AB2397E90400758AF0 /* MXUIKitBackgroundTask.h in Headers */ = {isa = PBXBuildFile; fileRef = B17B2BDA2369FC81009D6650 /* MXUIKitBackgroundTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; B14EF2AC2397E90400758AF0 /* MXMemoryStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 32D7767B1A27860600FC4AA2 /* MXMemoryStore.h */; settings = {ATTRIBUTES = (Public, ); }; }; B14EF2AD2397E90400758AF0 /* MXEventAnnotationChunk.h in Headers */ = {isa = PBXBuildFile; fileRef = 327E9AD32284803000A98BC1 /* MXEventAnnotationChunk.h */; settings = {ATTRIBUTES = (Public, ); }; }; B14EF2AF2397E90400758AF0 /* MXWellKnown.h in Headers */ = {isa = PBXBuildFile; fileRef = 323547D32226D3F500F15F94 /* MXWellKnown.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -1057,7 +1057,7 @@ B14EF2F52397E90400758AF0 /* MXSDKOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = F0C34CB91C18C80000C36F09 /* MXSDKOptions.h */; settings = {ATTRIBUTES = (Public, ); }; }; B14EF2F62397E90400758AF0 /* MXJSONModels.h in Headers */ = {isa = PBXBuildFile; fileRef = 3281E8B519E42DFE00976E1A /* MXJSONModels.h */; settings = {ATTRIBUTES = (Public, ); }; }; B14EF2F72397E90400758AF0 /* MXRoomEventFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 323F3F9220D3F0C700D26D6A /* MXRoomEventFilter.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B14EF2F82397E90400758AF0 /* MXUIKitBackgroundModeHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 32A9E8221EF4026E0081358A /* MXUIKitBackgroundModeHandler.h */; }; + B14EF2F82397E90400758AF0 /* MXUIKitBackgroundModeHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 32A9E8221EF4026E0081358A /* MXUIKitBackgroundModeHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; B14EF2F92397E90400758AF0 /* MXCrypto_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 325D1C251DFECE0D0070B8BF /* MXCrypto_Private.h */; }; B14EF2FA2397E90400758AF0 /* MXEventReplace.h in Headers */ = {isa = PBXBuildFile; fileRef = B10AFB4122A970060092E6AF /* MXEventReplace.h */; }; B14EF2FB2397E90400758AF0 /* MXOlmSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 32E402B721C957D2004E87A6 /* MXOlmSession.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -1107,7 +1107,7 @@ B14EF3282397E90400758AF0 /* MXMegolmDecryption.h in Headers */ = {isa = PBXBuildFile; fileRef = 32A151241DABB0CB00400192 /* MXMegolmDecryption.h */; settings = {ATTRIBUTES = (Public, ); }; }; B14EF3292397E90400758AF0 /* MXAutoDiscovery.h in Headers */ = {isa = PBXBuildFile; fileRef = 32720D9A222EAA6F0086FFF5 /* MXAutoDiscovery.h */; settings = {ATTRIBUTES = (Public, ); }; }; B14EF32A2397E90400758AF0 /* MXSessionEventListener.h in Headers */ = {isa = PBXBuildFile; fileRef = 3220094319EFBF30008DE41D /* MXSessionEventListener.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B14EF32B2397E90400758AF0 /* MXBackgroundModeHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 32A9E8211EF4026E0081358A /* MXBackgroundModeHandler.h */; }; + B14EF32B2397E90400758AF0 /* MXBackgroundModeHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 32A9E8211EF4026E0081358A /* MXBackgroundModeHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; B14EF32C2397E90400758AF0 /* MXRoomPredecessorInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = B17982EF2119E49F001FD722 /* MXRoomPredecessorInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; B14EF32D2397E90400758AF0 /* MXCallStack.h in Headers */ = {isa = PBXBuildFile; fileRef = 32BED28E1B00A23F00E668FE /* MXCallStack.h */; settings = {ATTRIBUTES = (Public, ); }; }; B14EF32E2397E90400758AF0 /* MXMediaLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F03EF4FA1DF014D9009DF592 /* MXMediaLoader.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -1339,6 +1339,12 @@ EC11658E270F3ABF0089FA56 /* RLMRealm+MatrixSDK.h in Headers */ = {isa = PBXBuildFile; fileRef = EC11658B270F3ABF0089FA56 /* RLMRealm+MatrixSDK.h */; }; EC11658F270F3ABF0089FA56 /* RLMRealm+MatrixSDK.m in Sources */ = {isa = PBXBuildFile; fileRef = EC11658C270F3ABF0089FA56 /* RLMRealm+MatrixSDK.m */; }; EC116590270F3ABF0089FA56 /* RLMRealm+MatrixSDK.m in Sources */ = {isa = PBXBuildFile; fileRef = EC11658C270F3ABF0089FA56 /* RLMRealm+MatrixSDK.m */; }; + EC116593270FB6970089FA56 /* MXBackgroundTaskUnitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC116591270FB6890089FA56 /* MXBackgroundTaskUnitTests.swift */; }; + EC116595270FBF090089FA56 /* MXApplicationProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = EC116594270FBF090089FA56 /* MXApplicationProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EC116596270FBF090089FA56 /* MXApplicationProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = EC116594270FBF090089FA56 /* MXApplicationProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EC116598270FCA8B0089FA56 /* MXBackgroundTaskUnitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC116591270FB6890089FA56 /* MXBackgroundTaskUnitTests.swift */; }; + EC116599270FCF740089FA56 /* MXBackgroundTask.h in Headers */ = {isa = PBXBuildFile; fileRef = B11976FD236B27220001EC86 /* MXBackgroundTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EC11659A270FCF750089FA56 /* MXBackgroundTask.h in Headers */ = {isa = PBXBuildFile; fileRef = B11976FD236B27220001EC86 /* MXBackgroundTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; EC1848C52685F64D00865E16 /* MXiOSAudioOutputRoute.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC1848C42685F64D00865E16 /* MXiOSAudioOutputRoute.swift */; }; EC1848C72686174E00865E16 /* MXiOSAudioOutputRouteType.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC1848C62686174E00865E16 /* MXiOSAudioOutputRouteType.swift */; }; EC1848C92686176D00865E16 /* MXiOSAudioOutputRouterDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC1848C82686176D00865E16 /* MXiOSAudioOutputRouterDelegate.swift */; }; @@ -2288,6 +2294,8 @@ EC054972260123BE0047ECD7 /* MXRoomAccountDataUpdating.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXRoomAccountDataUpdating.h; sourceTree = ""; }; EC11658B270F3ABF0089FA56 /* RLMRealm+MatrixSDK.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RLMRealm+MatrixSDK.h"; sourceTree = ""; }; EC11658C270F3ABF0089FA56 /* RLMRealm+MatrixSDK.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "RLMRealm+MatrixSDK.m"; sourceTree = ""; }; + EC116591270FB6890089FA56 /* MXBackgroundTaskUnitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXBackgroundTaskUnitTests.swift; sourceTree = ""; }; + EC116594270FBF090089FA56 /* MXApplicationProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXApplicationProtocol.h; sourceTree = ""; }; EC1848C42685F64D00865E16 /* MXiOSAudioOutputRoute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXiOSAudioOutputRoute.swift; sourceTree = ""; }; EC1848C62686174E00865E16 /* MXiOSAudioOutputRouteType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXiOSAudioOutputRouteType.swift; sourceTree = ""; }; EC1848C82686176D00865E16 /* MXiOSAudioOutputRouterDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXiOSAudioOutputRouterDelegate.swift; sourceTree = ""; }; @@ -2605,6 +2613,7 @@ C6FE1EEF1E65C4F7008587E4 /* MXAnalyticsDelegate.h */, 32B090E1261F709B002924AA /* MXAsyncTaskQueue.swift */, 32A9E8211EF4026E0081358A /* MXBackgroundModeHandler.h */, + EC116594270FBF090089FA56 /* MXApplicationProtocol.h */, B11976FD236B27220001EC86 /* MXBackgroundTask.h */, B1798D0424091A0100308A8F /* MXBase64Tools.h */, B1798D0524091A0100308A8F /* MXBase64Tools.m */, @@ -3537,6 +3546,7 @@ B1F939F426289F2600D0E525 /* MXSpaceChildContentTests.swift */, 3A7B8CFD267FCD9B00D9DD96 /* MXDehydrationTests.m */, ECB6FA8D267CFF4300A941E4 /* MXCredentialsUnitTests.swift */, + EC116591270FB6890089FA56 /* MXBackgroundTaskUnitTests.swift */, 322985CD26FAFC58001890BC /* MatrixSDKTestsSwiftHeader.h */, ); path = MatrixSDKTests; @@ -4192,6 +4202,7 @@ buildActionMask = 2147483647; files = ( 32F9FA7D1DBA0CF0009D98A6 /* MXDecryptionResult.h in Headers */, + EC116599270FCF740089FA56 /* MXBackgroundTask.h in Headers */, EC8A539F25B1BC77004E0802 /* MXCallHangupEventContent.h in Headers */, 3271877D1DA7CB2F0071C818 /* MXDecrypting.h in Headers */, EC8A539925B1BC77004E0802 /* MXCallNegotiateEventContent.h in Headers */, @@ -4335,6 +4346,7 @@ EC60EDDA265CFF0600B39A4E /* MXInvitedRoomSync.h in Headers */, B146D47F21A59E2400D8C2C6 /* MXEventScan.h in Headers */, B146D4E121A5AEF200D8C2C6 /* MXRealmMediaScanMapper.h in Headers */, + EC116595270FBF090089FA56 /* MXApplicationProtocol.h in Headers */, 1838927E2702F553003F0C4F /* MXSendReplyEventDefaultStringLocalizer.h in Headers */, 32C78B6C256CFC4D008130B1 /* MXCryptoMigration.h in Headers */, F08B8D5C1E014711006171A8 /* NSData+MatrixSDK.h in Headers */, @@ -4543,6 +4555,7 @@ B14EF2C52397E90400758AF0 /* MXPushRuleDisplayNameCondtionChecker.h in Headers */, B14EF30E2397E90400758AF0 /* MXPushRuleRoomMemberCountConditionChecker.h in Headers */, B14EF3182397E90400758AF0 /* MXPushRuleSenderNotificationPermissionConditionChecker.h in Headers */, + EC11659A270FCF750089FA56 /* MXBackgroundTask.h in Headers */, EC60ED5E265CFC2C00B39A4E /* MXSyncResponse.h in Headers */, B14EF3272397E90400758AF0 /* MXPushRuleEventMatchConditionChecker.h in Headers */, EC60EDA9265CFE3B00B39A4E /* MXRoomSyncTimeline.h in Headers */, @@ -4733,6 +4746,7 @@ 324DD2B7246C21C700377005 /* MXSecretStorageKeyCreationInfo.h in Headers */, B14EF30F2397E90400758AF0 /* SwiftMatrixSDK.h in Headers */, B14EF3102397E90400758AF0 /* MXEmojiRepresentation.h in Headers */, + EC116596270FBF090089FA56 /* MXApplicationProtocol.h in Headers */, ECF29BCD264194AE0053E6D6 /* MXCallAssertedIdentityEventContent.h in Headers */, B14EF3112397E90400758AF0 /* MXMegolmExportEncryption.h in Headers */, B14EF3122397E90400758AF0 /* MXIdentityServerRestClient.h in Headers */, @@ -5527,6 +5541,7 @@ 32B477852638133C00EA5800 /* MXAggregatedEditsUnitTests.m in Sources */, ECB6FA8E267CFF4300A941E4 /* MXCredentialsUnitTests.swift in Sources */, 3A108E6725826F52005EEBE9 /* MXKeyProviderUnitTests.m in Sources */, + EC116593270FB6970089FA56 /* MXBackgroundTaskUnitTests.swift in Sources */, B11BD45C22CB8ABC0064D8B0 /* MXReplyEventParserUnitTests.m in Sources */, ECAE7AEC24ED75F1002FA813 /* MXHTTPAdditionalHeadersUnitTests.m in Sources */, 32AF9292241112850008A0FD /* MXCryptoSecretShareTests.m in Sources */, @@ -5997,6 +6012,7 @@ A816248525F60D0300A46F05 /* MXDeviceListOperationsPoolUnitTests.swift in Sources */, B1E09A312397FD750057C069 /* MXSessionTests.m in Sources */, 32B477902638133D00EA5800 /* MXAggregatedReferenceUnitTests.m in Sources */, + EC116598270FCA8B0089FA56 /* MXBackgroundTaskUnitTests.swift in Sources */, B1E09A322397FD750057C069 /* MXRoomTests.m in Sources */, 322985CC26FAF898001890BC /* MXSession.swift in Sources */, 32C78BA8256D227D008130B1 /* MXCryptoMigrationTests.m in Sources */, diff --git a/MatrixSDK/MatrixSDK.h b/MatrixSDK/MatrixSDK.h index 9639c0925c..4f643b6548 100644 --- a/MatrixSDK/MatrixSDK.h +++ b/MatrixSDK/MatrixSDK.h @@ -131,6 +131,9 @@ FOUNDATION_EXPORT NSString *MatrixSDKVersion; #import "MXSpaceChildContent.h" #import "MXRoomLastMessage.h" +#import "MXBackgroundModeHandler.h" +#import "MXUIKitBackgroundTask.h" +#import "MXUIKitBackgroundModeHandler.h" // Bridging to Swift #import "MXCryptoStore.h" diff --git a/MatrixSDK/Utils/MXApplicationProtocol.h b/MatrixSDK/Utils/MXApplicationProtocol.h new file mode 100644 index 0000000000..06b64267ed --- /dev/null +++ b/MatrixSDK/Utils/MXApplicationProtocol.h @@ -0,0 +1,39 @@ +// +// Copyright 2021 The Matrix.org Foundation C.I.C +// +// 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. +// + +#ifndef MXApplicationProtocol_h +#define MXApplicationProtocol_h + +#import + +#if TARGET_OS_IPHONE +#import +#else +typedef NSInteger UIBackgroundTaskIdentifier NS_TYPED_ENUM; +#endif + +/** + Protocol to mock `UIApplication` class. + */ +@protocol MXApplicationProtocol + +- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void(^ __nullable)(void))handler; +- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithName:(nullable NSString *)taskName expirationHandler:(void(^ __nullable)(void))handler; +- (void)endBackgroundTask:(UIBackgroundTaskIdentifier)identifier; + +@end + +#endif /* MXApplicationProtocol_h */ diff --git a/MatrixSDK/Utils/MXBackgroundTask.h b/MatrixSDK/Utils/MXBackgroundTask.h index a8a2f1b4ec..e9c8ce7678 100644 --- a/MatrixSDK/Utils/MXBackgroundTask.h +++ b/MatrixSDK/Utils/MXBackgroundTask.h @@ -44,7 +44,12 @@ typedef void (^MXBackgroundTaskExpirationHandler)(void); @property (nonatomic, readonly, getter=isReusable) BOOL reusable; /** - Stop the background task. Cannot be started anymore. + Method to be called when a task reused one more time. Should only be valid for reusable tasks. + */ +- (void)reuse; + +/** + Stop the background task. Cannot be started anymore. For reusable tasks, should be called same number of times `reuse` called. */ - (void)stop; diff --git a/MatrixSDK/Utils/MXUIKitBackgroundModeHandler.h b/MatrixSDK/Utils/MXUIKitBackgroundModeHandler.h index 83c5ade952..b3b02a3d50 100644 --- a/MatrixSDK/Utils/MXUIKitBackgroundModeHandler.h +++ b/MatrixSDK/Utils/MXUIKitBackgroundModeHandler.h @@ -17,11 +17,24 @@ #import #import "MXBackgroundModeHandler.h" +#import "MXUIKitBackgroundTask.h" -#if TARGET_OS_IPHONE +NS_ASSUME_NONNULL_BEGIN @interface MXUIKitBackgroundModeHandler : NSObject +/** + Default initializer. Application will be got via `-[UIApplication sharedApplication]` for TARGET_OS_IPHONE, otherwise will be nil. + */ +- (instancetype)init; + +/** + Initializer with custom application getter block + + @param applicationBlock block will be used when an application is required. + */ +- (instancetype)initWithApplicationBlock:(MXApplicationGetterBlock)applicationBlock; + @end -#endif +NS_ASSUME_NONNULL_END diff --git a/MatrixSDK/Utils/MXUIKitBackgroundModeHandler.m b/MatrixSDK/Utils/MXUIKitBackgroundModeHandler.m index 45bb67c8d6..134fffa4e3 100644 --- a/MatrixSDK/Utils/MXUIKitBackgroundModeHandler.m +++ b/MatrixSDK/Utils/MXUIKitBackgroundModeHandler.m @@ -18,29 +18,35 @@ #import "MXUIKitBackgroundModeHandler.h" #if TARGET_OS_IPHONE - #import +#endif + #import "MXUIKitBackgroundTask.h" #import "MatrixSDKSwiftHeader.h" - +#if TARGET_OS_IPHONE /** Time threshold to be able to start a background task. So, if application's `backgroundTimeRemaining` returns less than this value, the task won't be started at all and expirationHandler will be called immediately. @note This value only considered if the application is in background state. @see -[UIApplication backgroundTimeRemaining] */ static const NSTimeInterval BackgroundTimeRemainingThresholdToStartTasks = 5.0; +#endif @interface MXUIKitBackgroundModeHandler () { +#if TARGET_OS_IPHONE MXUIKitApplicationStateService *applicationStateService; - +#endif /** Cache to store reusable background tasks. */ NSMapTable> *reusableTasks; } + +@property (nonatomic, copy) MXApplicationGetterBlock applicationBlock; + @end @@ -48,11 +54,27 @@ @implementation MXUIKitBackgroundModeHandler - (instancetype)init { - self = [super init]; - if (self) +#if TARGET_OS_IPHONE + self = [self initWithApplicationBlock:^id _Nullable{ + return [UIApplication performSelector:@selector(sharedApplication)]; + }]; +#else + self = [self initWithApplicationBlock:^id _Nullable{ + return nil; + }]; +#endif + return self; +} + +- (instancetype)initWithApplicationBlock:(MXApplicationGetterBlock)applicationBlock +{ + if (self = [super init]) { +#if TARGET_OS_IPHONE applicationStateService = [MXUIKitApplicationStateService new]; +#endif reusableTasks = [NSMapTable weakToWeakObjectsMapTable]; + self.applicationBlock = applicationBlock; } return self; } @@ -76,6 +98,7 @@ - (instancetype)init expirationHandler:(nullable MXBackgroundTaskExpirationHandler)expirationHandler { +#if TARGET_OS_IPHONE // application is in background and not enough time to start this task if (applicationStateService.applicationState == UIApplicationStateBackground && applicationStateService.backgroundTimeRemaining < BackgroundTimeRemainingThresholdToStartTasks) @@ -89,6 +112,7 @@ - (instancetype)init } return nil; } +#endif BOOL created = NO; @@ -114,7 +138,7 @@ - (instancetype)init { expirationHandler(); } - }]; + } applicationBlock:self.applicationBlock]; created = YES; // cache the task if successfully created @@ -123,27 +147,33 @@ - (instancetype)init [reusableTasks setObject:backgroundTask forKey:name]; } } + else + { + // reusing an existing task + [backgroundTask reuse]; + } } else { // not reusable, just create one and continue. Do not store non-reusable tasks in the cache backgroundTask = [[MXUIKitBackgroundTask alloc] initAndStartWithName:name reusable:reusable - expirationHandler:expirationHandler]; + expirationHandler:expirationHandler + applicationBlock:self.applicationBlock]; created = YES; } if (backgroundTask) { +#if TARGET_OS_IPHONE NSString *readableAppState = [MXUIKitApplicationStateService readableApplicationState:applicationStateService.applicationState]; NSString *readableBackgroundTimeRemaining = [MXUIKitApplicationStateService readableEstimatedBackgroundTimeRemaining:applicationStateService.backgroundTimeRemaining]; MXLogDebug(@"[MXBackgroundTask] Background task %@ %@ with app state: %@ and estimated background time remaining: %@", backgroundTask.name, (created ? @"started" : @"reused"), readableAppState, readableBackgroundTimeRemaining); +#endif } return backgroundTask; } @end - -#endif diff --git a/MatrixSDK/Utils/MXUIKitBackgroundTask.h b/MatrixSDK/Utils/MXUIKitBackgroundTask.h index 32a1257fff..41fb9e4228 100644 --- a/MatrixSDK/Utils/MXUIKitBackgroundTask.h +++ b/MatrixSDK/Utils/MXUIKitBackgroundTask.h @@ -16,11 +16,12 @@ #import #import "MXBackgroundTask.h" - -#if TARGET_OS_IPHONE +#import "MXApplicationProtocol.h" NS_ASSUME_NONNULL_BEGIN +typedef id _Nullable (^MXApplicationGetterBlock)(void); + /** MXUIKitBackgroundTask is a concrete implementation of MXBackgroundTask using UIApplication background task. */ @@ -28,10 +29,9 @@ NS_ASSUME_NONNULL_BEGIN - (nullable instancetype)initAndStartWithName:(NSString*)name reusable:(BOOL)reusable - expirationHandler:(nullable MXBackgroundTaskExpirationHandler)expirationHandler; + expirationHandler:(nullable MXBackgroundTaskExpirationHandler)expirationHandler + applicationBlock:(MXApplicationGetterBlock)applicationBlock; @end NS_ASSUME_NONNULL_END - -#endif diff --git a/MatrixSDK/Utils/MXUIKitBackgroundTask.m b/MatrixSDK/Utils/MXUIKitBackgroundTask.m index ef01b841a9..b7cf367e0a 100644 --- a/MatrixSDK/Utils/MXUIKitBackgroundTask.m +++ b/MatrixSDK/Utils/MXUIKitBackgroundTask.m @@ -17,8 +17,10 @@ #import "MXUIKitBackgroundTask.h" #if TARGET_OS_IPHONE - #import +#else +static const UIBackgroundTaskIdentifier UIBackgroundTaskInvalid = -1; +#endif #import "MXTools.h" @@ -27,8 +29,10 @@ @interface MXUIKitBackgroundTask () @property (nonatomic) UIBackgroundTaskIdentifier identifier; @property (nonatomic, copy) NSString *name; @property (nonatomic, copy, nullable) MXBackgroundTaskExpirationHandler expirationHandler; -@property (nonatomic, assign) BOOL reusable; +@property (nonatomic, assign, getter=isReusable) BOOL reusable; @property (nonatomic, strong, nullable) NSDate *startDate; +@property (nonatomic, assign) NSInteger useCounter; +@property (nonatomic, copy) MXApplicationGetterBlock applicationBlock; @end @@ -39,6 +43,7 @@ @implementation MXUIKitBackgroundTask - (instancetype)initWithName:(NSString*)name reusable:(BOOL)reusable expirationHandler:(MXBackgroundTaskExpirationHandler)expirationHandler + applicationBlock:(MXApplicationGetterBlock)applicationBlock { self = [super init]; if (self) @@ -47,6 +52,11 @@ - (instancetype)initWithName:(NSString*)name self.name = name; self.reusable = reusable; self.expirationHandler = expirationHandler; + @synchronized (self) + { + self.useCounter = 0; + } + self.applicationBlock = applicationBlock; } return self; } @@ -54,19 +64,20 @@ - (instancetype)initWithName:(NSString*)name - (nullable instancetype)initAndStartWithName:(NSString*)name reusable:(BOOL)reusable expirationHandler:(nullable MXBackgroundTaskExpirationHandler)expirationHandler + applicationBlock:(MXApplicationGetterBlock)applicationBlock { - self = [self initWithName:name reusable:reusable expirationHandler:expirationHandler]; + self = [self initWithName:name reusable:reusable expirationHandler:expirationHandler applicationBlock:applicationBlock]; if (self) { - UIApplication *sharedApplication = [self sharedApplication]; - if (sharedApplication) + id application = self.applicationBlock(); + if (application) { // we assume this task can start now self.startDate = [NSDate date]; MXWeakify(self); - self.identifier = [sharedApplication beginBackgroundTaskWithName:self.name expirationHandler:^{ + self.identifier = [application beginBackgroundTaskWithName:self.name expirationHandler:^{ MXStrongifyAndReturnIfNil(self); @@ -79,7 +90,7 @@ - (nullable instancetype)initAndStartWithName:(NSString*)name } // be sure to call endBackgroundTask - [self stop]; + [self endTask]; }]; // our assumption is wrong, OS declined it @@ -94,12 +105,17 @@ - (nullable instancetype)initAndStartWithName:(NSString*)name } return nil; } + else if (self.isReusable) + { + // creation itself is a use + [self reuse]; + } MXLogDebug(@"[MXBackgroundTask] Start background task #%lu - %@", (unsigned long)self.identifier, self.name); } else { - MXLogDebug(@"[MXBackgroundTask] Background task creation failed. UIApplication.shared is nil"); + MXLogDebug(@"[MXBackgroundTask] Background task creation failed. Application is nil"); // we're probably in an app extension here. // Do not call expiration handler as it'll cause some network requests to be cancelled, @@ -116,38 +132,76 @@ - (nullable instancetype)initAndStartWithName:(NSString*)name - (void)dealloc { - [self stop]; + [self endTask]; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"<%@: %p, #%lu - %@>", NSStringFromClass([self class]), self, (unsigned long)self.identifier, self.name]; } +#pragma Public + - (BOOL)isRunning { return self.identifier != UIBackgroundTaskInvalid; } -- (NSString *)description +- (void)reuse { - return [NSString stringWithFormat:@"<%@: %p, #%lu - %@>", NSStringFromClass([self class]), self, (unsigned long)self.identifier, self.name]; + // only valid for reusable tasks + NSParameterAssert(self.isReusable); + + // increment reuse counter safely + @synchronized (self) + { + self.useCounter++; + } } - -#pragma Public - (void)stop +{ + if (self.isReusable) + { + // decrement reuse counter safely and decide to really end the task + BOOL endTask = NO; + @synchronized (self) + { + self.useCounter--; + if (self.useCounter <= 0) + { + endTask = YES; + } + } + + if (endTask) + { + [self endTask]; + } + } + else + { + [self endTask]; + } +} + +#pragma Private + +- (void)endTask { if (self.identifier != UIBackgroundTaskInvalid) { - UIApplication *sharedApplication = [self sharedApplication]; - if (sharedApplication) + id application = self.applicationBlock(); + if (application) { - MXLogDebug(@"[MXBackgroundTask] Stop background task #%lu - %@ after %.3fms", (unsigned long)self.identifier, self.name, self.elapsedTime); + MXLogDebug(@"[MXBackgroundTask] End background task #%lu - %@ after %.3fms", (unsigned long)self.identifier, self.name, self.elapsedTime); - [sharedApplication endBackgroundTask:self.identifier]; + [application endBackgroundTask:self.identifier]; self.identifier = UIBackgroundTaskInvalid; } } } -#pragma Private - - (NSTimeInterval)elapsedTime { NSTimeInterval elapasedTime = 0; @@ -160,11 +214,4 @@ - (NSTimeInterval)elapsedTime return elapasedTime; } -- (UIApplication*)sharedApplication -{ - return [UIApplication performSelector:@selector(sharedApplication)]; -} - @end - -#endif diff --git a/MatrixSDKTests/MatrixSDKTests-Bridging-Header.h b/MatrixSDKTests/MatrixSDKTests-Bridging-Header.h index 9acd248115..c2735b2730 100644 --- a/MatrixSDKTests/MatrixSDKTests-Bridging-Header.h +++ b/MatrixSDKTests/MatrixSDKTests-Bridging-Header.h @@ -20,5 +20,8 @@ #import "MatrixSDKTestsData.h" #import "MatrixSDKTestsE2EData.h" #import "MXDeviceListOperationsPool.h" +#import "MXBackgroundTask.h" +#import "MXUIKitBackgroundModeHandler.h" +#import "MXApplicationProtocol.h" #endif /* MatrixSDKTests_Bridging_Header_h */ From 65cef2a352e1ad1eea3994e5b124a9817b27a4b0 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Fri, 8 Oct 2021 04:11:32 +0300 Subject: [PATCH 39/42] Introduce background task unit tests --- .../MXBackgroundTaskUnitTests.swift | 180 ++++++++++++++++++ MatrixSDKTests/TestPlans/UnitTests.xctestplan | 6 +- .../UnitTestsWithSanitizers.xctestplan | 6 +- 3 files changed, 184 insertions(+), 8 deletions(-) create mode 100644 MatrixSDKTests/MXBackgroundTaskUnitTests.swift diff --git a/MatrixSDKTests/MXBackgroundTaskUnitTests.swift b/MatrixSDKTests/MXBackgroundTaskUnitTests.swift new file mode 100644 index 0000000000..dcbc496811 --- /dev/null +++ b/MatrixSDKTests/MXBackgroundTaskUnitTests.swift @@ -0,0 +1,180 @@ +// +// Copyright 2021 The Matrix.org Foundation C.I.C +// +// 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 XCTest + +@testable import MatrixSDK + +class MXBackgroundTaskUnitTests: XCTestCase { + + private enum Constants { + static let bgTaskName: String = "test" + } + + func testInitAndStop() { + let bgModeHandler = MXUIKitBackgroundModeHandler { + return MockApplication() + } + guard let task = bgModeHandler.startBackgroundTask(withName: Constants.bgTaskName) else { + XCTFail("Failed to setup test conditions") + return + } + + XCTAssertEqual(task.name, Constants.bgTaskName, "Task name should be persisted") + XCTAssertFalse(task.isReusable, "Task should be not reusable by default") + XCTAssertTrue(task.isRunning, "Task should be running") + + task.stop() + + XCTAssertFalse(task.isRunning, "Task should be stopped") + } + + func testNotReusableInit() { + let bgModeHandler = MXUIKitBackgroundModeHandler { + return MockApplication() + } + + // create two not reusable task with the same name + guard let task1 = bgModeHandler.startBackgroundTask(withName: Constants.bgTaskName), + let task2 = bgModeHandler.startBackgroundTask(withName: Constants.bgTaskName) else { + XCTFail("Failed to setup test conditions") + return + } + + // task1 & task2 should be different instances + XCTAssertNotEqual(Unmanaged.passUnretained(task1).toOpaque(), + Unmanaged.passUnretained(task2).toOpaque(), + "Handler should create different tasks when reusability disabled") + } + + func testReusableInit() { + let bgModeHandler = MXUIKitBackgroundModeHandler { + return MockApplication() + } + + // create two reusable task with the same name + guard let task1 = bgModeHandler.startBackgroundTask(withName: Constants.bgTaskName, reusable: true), + let task2 = bgModeHandler.startBackgroundTask(withName: Constants.bgTaskName, reusable: true) else { + XCTFail("Failed to setup test conditions") + return + } + + // task1 and task2 should be the same instance + XCTAssertEqual(Unmanaged.passUnretained(task1).toOpaque(), + Unmanaged.passUnretained(task2).toOpaque(), + "Handler should create different tasks when reusability disabled") + + XCTAssertEqual(task1.name, Constants.bgTaskName, "Task name should be persisted") + XCTAssertTrue(task1.isReusable, "Task should be reusable") + XCTAssertTrue(task1.isRunning, "Task should be running") + } + + func testMultipleStops() { + let bgModeHandler = MXUIKitBackgroundModeHandler { + return MockApplication() + } + + // create two reusable task with the same name + guard let task = bgModeHandler.startBackgroundTask(withName: Constants.bgTaskName, reusable: true), + let _ = bgModeHandler.startBackgroundTask(withName: Constants.bgTaskName, reusable: true) else { + XCTFail("Failed to setup test conditions") + return + } + + XCTAssertTrue(task.isRunning, "Task should be running") + + task.stop() + + XCTAssertTrue(task.isRunning, "Task should be still running after one stop call") + + task.stop() + + XCTAssertFalse(task.isRunning, "Task should be stopped after two stop calls") + } + + func testNotValidReuse() { + let bgModeHandler = MXUIKitBackgroundModeHandler { + return MockApplication() + } + + // create two reusable task with the same name + guard let task = bgModeHandler.startBackgroundTask(withName: Constants.bgTaskName, reusable: true) else { + XCTFail("Failed to setup test conditions") + return + } + + XCTAssertTrue(task.isRunning, "Task should be running") + + task.stop() + + XCTAssertFalse(task.isRunning, "Task should be stopped after stop") + + task.reuse() + + XCTAssertFalse(task.isRunning, "Task should be stopped after one stop call, even if reuse is called after") + } + + func testValidReuse() { + let bgModeHandler = MXUIKitBackgroundModeHandler { + return MockApplication() + } + + // create two reusable task with the same name + guard let task = bgModeHandler.startBackgroundTask(withName: Constants.bgTaskName, reusable: true) else { + XCTFail("Failed to setup test conditions") + return + } + + XCTAssertTrue(task.isRunning, "Task should be running") + + task.reuse() + + XCTAssertTrue(task.isRunning, "Task should be still running") + + task.stop() + + XCTAssertTrue(task.isRunning, "Task should be still running after one stop call") + + task.stop() + + XCTAssertFalse(task.isRunning, "Task should be stopped after two stop calls") + } + +} + +fileprivate class MockApplication: MXApplicationProtocol { + + private static var bgTaskIdentifier: Int = 0 + + var bgTasks: [UIBackgroundTaskIdentifier: Bool] = [:] + + func beginBackgroundTask(expirationHandler handler: (() -> Void)? = nil) -> UIBackgroundTaskIdentifier { + return beginBackgroundTask(withName: nil, expirationHandler: handler) + } + + func beginBackgroundTask(withName taskName: String?, expirationHandler handler: (() -> Void)? = nil) -> UIBackgroundTaskIdentifier { + Self.bgTaskIdentifier += 1 + + let identifier = UIBackgroundTaskIdentifier(rawValue: Self.bgTaskIdentifier) + bgTasks[identifier] = true + return identifier + } + + func endBackgroundTask(_ identifier: UIBackgroundTaskIdentifier) { + bgTasks.removeValue(forKey: identifier) + } + +} diff --git a/MatrixSDKTests/TestPlans/UnitTests.xctestplan b/MatrixSDKTests/TestPlans/UnitTests.xctestplan index 9f7d519082..3cc9b17639 100644 --- a/MatrixSDKTests/TestPlans/UnitTests.xctestplan +++ b/MatrixSDKTests/TestPlans/UnitTests.xctestplan @@ -34,10 +34,8 @@ "MXAggregatedReferenceUnitTests", "MXAsyncTaskQueueUnitTests", "MXAuthenticationSessionUnitTests", - "MXCredentialsUnitTests\/testEqualHashes()", - "MXCredentialsUnitTests\/testEquality()", - "MXCredentialsUnitTests\/testNotEqualHashes()", - "MXCredentialsUnitTests\/testNotEquality()", + "MXBackgroundTaskUnitTests", + "MXCredentialsUnitTests", "MXDeviceListOperationsPoolUnitTests", "MXErrorUnitTests", "MXEventAnnotationUnitTests", diff --git a/MatrixSDKTests/TestPlans/UnitTestsWithSanitizers.xctestplan b/MatrixSDKTests/TestPlans/UnitTestsWithSanitizers.xctestplan index b00c980bbc..fe0bb30758 100644 --- a/MatrixSDKTests/TestPlans/UnitTestsWithSanitizers.xctestplan +++ b/MatrixSDKTests/TestPlans/UnitTestsWithSanitizers.xctestplan @@ -44,10 +44,8 @@ "MXAggregatedReferenceUnitTests", "MXAsyncTaskQueueUnitTests", "MXAuthenticationSessionUnitTests", - "MXCredentialsUnitTests\/testEqualHashes()", - "MXCredentialsUnitTests\/testEquality()", - "MXCredentialsUnitTests\/testNotEqualHashes()", - "MXCredentialsUnitTests\/testNotEquality()", + "MXBackgroundTaskUnitTests", + "MXCredentialsUnitTests", "MXDeviceListOperationsPoolUnitTests", "MXErrorUnitTests", "MXEventAnnotationUnitTests", From e3b9fb4fc78ecd4ce7c88fdf83d34b6109c85bd1 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Fri, 8 Oct 2021 04:23:13 +0300 Subject: [PATCH 40/42] Update MXBackgroundTaskUnitTests.swift --- MatrixSDKTests/MXBackgroundTaskUnitTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MatrixSDKTests/MXBackgroundTaskUnitTests.swift b/MatrixSDKTests/MXBackgroundTaskUnitTests.swift index dcbc496811..fce358cc86 100644 --- a/MatrixSDKTests/MXBackgroundTaskUnitTests.swift +++ b/MatrixSDKTests/MXBackgroundTaskUnitTests.swift @@ -159,7 +159,7 @@ fileprivate class MockApplication: MXApplicationProtocol { private static var bgTaskIdentifier: Int = 0 - var bgTasks: [UIBackgroundTaskIdentifier: Bool] = [:] + private var bgTasks: [UIBackgroundTaskIdentifier: Bool] = [:] func beginBackgroundTask(expirationHandler handler: (() -> Void)? = nil) -> UIBackgroundTaskIdentifier { return beginBackgroundTask(withName: nil, expirationHandler: handler) From 2bdb496f486a157573d08865486b9483e221158c Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 8 Oct 2021 15:15:03 +0200 Subject: [PATCH 41/42] version++ --- CHANGES.md | 23 +++++++++++++++++++++++ MatrixSDK.podspec | 2 +- MatrixSDK/MatrixSDKVersion.m | 2 +- changelog.d/4451.api | 1 - changelog.d/4875.change | 1 - changelog.d/4898.bugfix | 1 - changelog.d/4899.api | 1 - changelog.d/4899.change | 1 - changelog.d/4939.change | 1 - changelog.d/4951.build | 1 - changelog.d/4964.change | 1 - 11 files changed, 25 insertions(+), 10 deletions(-) delete mode 100644 changelog.d/4451.api delete mode 100644 changelog.d/4875.change delete mode 100644 changelog.d/4898.bugfix delete mode 100644 changelog.d/4899.api delete mode 100644 changelog.d/4899.change delete mode 100644 changelog.d/4939.change delete mode 100644 changelog.d/4951.build delete mode 100644 changelog.d/4964.change diff --git a/CHANGES.md b/CHANGES.md index 4da4a90e9b..b7fd74f49c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,26 @@ +## Changes in 0.20.5 (2021-10-08) + +🙌 Improvements + +- Tests: Improve tests suites execution time by fixing leaked MXSession instances that continued to run in background. ([#4875](https://github.com/vector-im/element-ios/issues/4875)) +- Added dynamism and compile time safety to room name and send reply event localizable strings. ([#4899](https://github.com/vector-im/element-ios/issues/4899)) +- Pods: Update JitsiMeetSDK and Realm. ([#4939](https://github.com/vector-im/element-ios/issues/4939)) +- Start a background task for every Realm transaction. ([#4964](https://github.com/vector-im/element-ios/issues/4964)) + +🐛 Bugfixes + +- Apply threading model for Spaces and cache space graph ([#4898](https://github.com/vector-im/element-ios/issues/4898)) + +⚠️ API Changes + +- MXRoomSummaryUpdater: Combine ignoreMemberProfileChanges and eventsFilterForMessages into a single property called allowedLastMessageEventTypes. ([#4451](https://github.com/vector-im/element-ios/issues/4451)) +- `MXSendReplyEventStringsLocalizable` is now `MXSendReplyEventStringLocalizerProtocol` and `MXRoomNameStringsLocalizable` is now `MXRoomNameStringLocalizerProtocol` ([#4899](https://github.com/vector-im/element-ios/issues/4899)) + +🧱 Build + +- Bundler: Update CocoaPods and fastlane. ([#4951](https://github.com/vector-im/element-ios/issues/4951)) + + ## Changes in 0.20.4 (2021-09-30) 🐛 Bugfixes diff --git a/MatrixSDK.podspec b/MatrixSDK.podspec index 2bd9fa901c..15d8dedf61 100644 --- a/MatrixSDK.podspec +++ b/MatrixSDK.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "MatrixSDK" - s.version = "0.20.4" + s.version = "0.20.5" s.summary = "The iOS SDK to build apps compatible with Matrix (https://www.matrix.org)" s.description = <<-DESC diff --git a/MatrixSDK/MatrixSDKVersion.m b/MatrixSDK/MatrixSDKVersion.m index 7ec41c2ead..91e79b0997 100644 --- a/MatrixSDK/MatrixSDKVersion.m +++ b/MatrixSDK/MatrixSDKVersion.m @@ -16,4 +16,4 @@ #import -NSString *const MatrixSDKVersion = @"0.20.4"; +NSString *const MatrixSDKVersion = @"0.20.5"; diff --git a/changelog.d/4451.api b/changelog.d/4451.api deleted file mode 100644 index 013ad01148..0000000000 --- a/changelog.d/4451.api +++ /dev/null @@ -1 +0,0 @@ -MXRoomSummaryUpdater: Combine ignoreMemberProfileChanges and eventsFilterForMessages into a single property called allowedLastMessageEventTypes. diff --git a/changelog.d/4875.change b/changelog.d/4875.change deleted file mode 100644 index c80c1cdf1c..0000000000 --- a/changelog.d/4875.change +++ /dev/null @@ -1 +0,0 @@ -Tests: Improve tests suites execution time by fixing leaked MXSession instances that continued to run in background. \ No newline at end of file diff --git a/changelog.d/4898.bugfix b/changelog.d/4898.bugfix deleted file mode 100644 index e2fe119500..0000000000 --- a/changelog.d/4898.bugfix +++ /dev/null @@ -1 +0,0 @@ -Apply threading model for Spaces and cache space graph \ No newline at end of file diff --git a/changelog.d/4899.api b/changelog.d/4899.api deleted file mode 100644 index 13ff268335..0000000000 --- a/changelog.d/4899.api +++ /dev/null @@ -1 +0,0 @@ -`MXSendReplyEventStringsLocalizable` is now `MXSendReplyEventStringLocalizerProtocol` and `MXRoomNameStringsLocalizable` is now `MXRoomNameStringLocalizerProtocol` \ No newline at end of file diff --git a/changelog.d/4899.change b/changelog.d/4899.change deleted file mode 100644 index 702de76be3..0000000000 --- a/changelog.d/4899.change +++ /dev/null @@ -1 +0,0 @@ -Added dynamism and compile time safety to room name and send reply event localizable strings. \ No newline at end of file diff --git a/changelog.d/4939.change b/changelog.d/4939.change deleted file mode 100644 index 939a40286c..0000000000 --- a/changelog.d/4939.change +++ /dev/null @@ -1 +0,0 @@ -Pods: Update JitsiMeetSDK and Realm. \ No newline at end of file diff --git a/changelog.d/4951.build b/changelog.d/4951.build deleted file mode 100644 index a4d355372f..0000000000 --- a/changelog.d/4951.build +++ /dev/null @@ -1 +0,0 @@ -Bundler: Update CocoaPods and fastlane. \ No newline at end of file diff --git a/changelog.d/4964.change b/changelog.d/4964.change deleted file mode 100644 index 59f6df0d36..0000000000 --- a/changelog.d/4964.change +++ /dev/null @@ -1 +0,0 @@ -Start a background task for every Realm transaction. From 2cd3f15b01c8dfef47b8ba4065814edb4c668685 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 8 Oct 2021 16:13:49 +0200 Subject: [PATCH 42/42] finish version++ --- Podfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Podfile.lock b/Podfile.lock index 02f1509e80..ea27697c46 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -69,4 +69,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: ea9778919e01b860c6b9fae81f500df82de7ad60 -COCOAPODS: 1.10.1 +COCOAPODS: 1.11.2