mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 01:20:12 +00:00
Introduce the RoomThreadListServiceProxy and expose it from the RoomProxy
Also update the sdk and app mocks and add a simple `RoomThreadListServiceProxyMock` # Conflicts: # ElementX.xcodeproj/project.pbxproj # ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved # SDKMocks/Sources/Generated/SDKGeneratedMocks.swift # project.yml
This commit is contained in:
committed by
Stefan Ceriu
parent
823e2afa97
commit
e97ed6ec5c
@@ -127,6 +127,7 @@
|
||||
12CD8B5CC30A05061228BF9E /* TimelineItemMenuActionProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9E6065FC6BC4A1B4C629E08 /* TimelineItemMenuActionProvider.swift */; };
|
||||
12E6D052D055531A6783E21B /* portrait_test_image.jpg in Resources */ = {isa = PBXBuildFile; fileRef = BC51BF90469412ABDE658CDD /* portrait_test_image.jpg */; };
|
||||
12EC6BC99F373FE5C6EB9B64 /* TimelineMediaPreviewDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 467498BEA681758BE2F80826 /* TimelineMediaPreviewDetailsView.swift */; };
|
||||
12F7172C93873638B23CD6AD /* RoomThreadListServiceProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04EB6035C1F33F25F1EBFB7D /* RoomThreadListServiceProxyProtocol.swift */; };
|
||||
1307268DC41730E5BCF7D9A0 /* PollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 638790D3F915F0909315C47A /* PollView.swift */; };
|
||||
1318721F4E5F307586D98112 /* VoiceMessageButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8516302ACCA94A0E680AB3B /* VoiceMessageButton.swift */; };
|
||||
13C77FDF17C4C6627CFFC205 /* RoomTimelineItemFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D25A35764C7B3DB78954AB5 /* RoomTimelineItemFactoryProtocol.swift */; };
|
||||
@@ -337,6 +338,7 @@
|
||||
388D39ED9FE1122EA6D76BF2 /* Common.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1BC84BA0AF11C2128D58ABD /* Common.swift */; };
|
||||
3895969759E68FAB90C63EF7 /* ElementCallServiceConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 406C90AF8C3E98DF5D4E5430 /* ElementCallServiceConstants.swift */; };
|
||||
38E0F9A4CB5237F039A2EEE6 /* RoomHistorySharingState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 722013E20EEED73553EC6F8D /* RoomHistorySharingState.swift */; };
|
||||
38E8F5CC90DC0D716B799DE1 /* RoomThreadListServiceProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7396A6491DEC64FCB66F60A1 /* RoomThreadListServiceProxyMock.swift */; };
|
||||
3982C505960006B341CFD0C6 /* UserDetailsEditScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27D0EA07BD545CC9F234DB8D /* UserDetailsEditScreenModels.swift */; };
|
||||
3982E60F9C126437D5E488A3 /* PillContextTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31A6314FDC51DA25712D9A81 /* PillContextTests.swift */; };
|
||||
39A987B3E41B976D1DF944C6 /* CallScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37A63A59BFDDC494B1C20119 /* CallScreenViewModel.swift */; };
|
||||
@@ -654,6 +656,7 @@
|
||||
70558528EF68CAAEF09972D5 /* RoomTimelineItemFixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = E96ED747FF90332EA1333C22 /* RoomTimelineItemFixtures.swift */; };
|
||||
706289B086B0A6B0C211763F /* UITestsSignalling.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7F0192CE2F891141A25B49F /* UITestsSignalling.swift */; };
|
||||
707E49BE07E8EB8A13C0EB1E /* SessionVerificationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FACD034DB52525A3CEF2BDF /* SessionVerificationScreen.swift */; };
|
||||
708FC3184CCED825F0A36273 /* RoomThreadListServiceProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCE06F4A71FD46C9D8CD432E /* RoomThreadListServiceProxy.swift */; };
|
||||
709A9B52FC26B4CB86B8B020 /* EncryptedRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F06F70B9C433BAD4BC6B9F5 /* EncryptedRoomTimelineView.swift */; };
|
||||
70B83D44043293B4B77440B9 /* PollFormScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB63761D9F9CE8B23CBD6179 /* PollFormScreenModels.swift */; };
|
||||
71643093F87153F633A1B025 /* ThreadDecorator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DA4F09CB613C54FDC73AE6A /* ThreadDecorator.swift */; };
|
||||
@@ -1602,6 +1605,7 @@
|
||||
048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
04BB8DDE245ED86C489BA983 /* AccessibilityIdentifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityIdentifiers.swift; sourceTree = "<group>"; };
|
||||
04DF593C3F7AF4B2FBAEB05D /* FileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileManager.swift; sourceTree = "<group>"; };
|
||||
04EB6035C1F33F25F1EBFB7D /* RoomThreadListServiceProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomThreadListServiceProxyProtocol.swift; sourceTree = "<group>"; };
|
||||
0516C69708D5CBDE1A8E77EC /* RoomDirectorySearchProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchProxyProtocol.swift; sourceTree = "<group>"; };
|
||||
052A8C0B00FE8AD7C972F2A4 /* LocationSharingScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationSharingScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
052B2F924572AFD70B5F500E /* StartChatScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartChatScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
@@ -2003,7 +2007,7 @@
|
||||
4A2B5274C1D3D2999D643786 /* EncryptionResetPasswordScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
4A5B4CD611DE7E94F5BA87B2 /* AppLockTimerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockTimerTests.swift; sourceTree = "<group>"; };
|
||||
4AB29A2D95D3469B5F016655 /* SecureBackupControllerMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupControllerMock.swift; sourceTree = "<group>"; };
|
||||
4B1F71AC585827E6C416C15A /* AppIcon.icon */ = {isa = PBXFileReference; lastKnownFileType = wrapper.icon; path = AppIcon.icon; sourceTree = "<group>"; };
|
||||
4B1F71AC585827E6C416C15A /* AppIcon.icon */ = {isa = PBXFileReference; path = AppIcon.icon; sourceTree = "<group>"; };
|
||||
4B2B564CA6570E1487A7C7CC /* SpaceRoomListProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceRoomListProxy.swift; sourceTree = "<group>"; };
|
||||
4B2D4EEBE8C098BBADD10939 /* SecureBackupKeyBackupScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupKeyBackupScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
4B41FABA2B0AEF4389986495 /* LoginMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginMode.swift; sourceTree = "<group>"; };
|
||||
@@ -2203,6 +2207,7 @@
|
||||
7310D8DFE01AF45F0689C3AA /* Publisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Publisher.swift; sourceTree = "<group>"; };
|
||||
7367B3B9A8CAF902220F31D1 /* BugReportFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportFlowCoordinator.swift; sourceTree = "<group>"; };
|
||||
739077686814E4EA339B1C83 /* RoomPreviewProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPreviewProxyProtocol.swift; sourceTree = "<group>"; };
|
||||
7396A6491DEC64FCB66F60A1 /* RoomThreadListServiceProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomThreadListServiceProxyMock.swift; sourceTree = "<group>"; };
|
||||
73A5C3F7C9C1DA10CAEC6A98 /* VoiceMessageRecordingComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecordingComposer.swift; sourceTree = "<group>"; };
|
||||
73F3153AB9D628110878E24F /* libMatrixRustSDKMocks.a */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = archive.ar; path = libMatrixRustSDKMocks.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
73FEE625AB52042049DB9268 /* ThreadTimelineScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadTimelineScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
@@ -2708,6 +2713,7 @@
|
||||
CC743C7A85E3171BCBF0A653 /* AvatarHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvatarHeaderView.swift; sourceTree = "<group>"; };
|
||||
CC8E9ECC1118A92FAD5191CD /* SpaceAddRoomsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceAddRoomsScreen.swift; sourceTree = "<group>"; };
|
||||
CCAA1B97A17A750AC706B112 /* SpaceServiceRoom.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpaceServiceRoom.swift; sourceTree = "<group>"; };
|
||||
CCE06F4A71FD46C9D8CD432E /* RoomThreadListServiceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomThreadListServiceProxy.swift; sourceTree = "<group>"; };
|
||||
CCF71646898A2F720C5BFDF5 /* RoomDirectorySearchScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
CD469F7513574341181F7EAA /* ServerSelectionScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionScreen.swift; sourceTree = "<group>"; };
|
||||
CD6613DE16AD26B3A74DA1F5 /* LocationRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineItemContent.swift; sourceTree = "<group>"; };
|
||||
@@ -3714,6 +3720,7 @@
|
||||
E944F717FC10A428D027074D /* RoomPowerLevelsProxyMock.swift */,
|
||||
6695C64F066628411EAD21E9 /* RoomPreviewProxyMock.swift */,
|
||||
FC83F47D2173B7538AA72E0E /* RoomSummaryProviderMock.swift */,
|
||||
7396A6491DEC64FCB66F60A1 /* RoomThreadListServiceProxyMock.swift */,
|
||||
4AB29A2D95D3469B5F016655 /* SecureBackupControllerMock.swift */,
|
||||
248649EBA5BC33DB93698734 /* SessionVerificationControllerProxyMock.swift */,
|
||||
7DB2A5FF1E68BA580A20D405 /* SpaceRoomListProxyMock.swift */,
|
||||
@@ -4087,6 +4094,8 @@
|
||||
CFFA5E881D281810AB428EA3 /* RoomPowerLevelsProxy.swift */,
|
||||
47111410B6E659A697D472B5 /* RoomProxyProtocol.swift */,
|
||||
578AF9CE60816069536C0953 /* RoomRole.swift */,
|
||||
CCE06F4A71FD46C9D8CD432E /* RoomThreadListServiceProxy.swift */,
|
||||
04EB6035C1F33F25F1EBFB7D /* RoomThreadListServiceProxyProtocol.swift */,
|
||||
2C0F49BD446849654C0D24E0 /* RoomMember */,
|
||||
4DC0344D2EBD0AE5D71754A9 /* RoomMembershipDetails */,
|
||||
7FC3F8FA5EA765AC3B000F55 /* RoomPreview */,
|
||||
@@ -7250,6 +7259,7 @@
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 7AE41FCCF9D1352E2770D1F9 /* Build configuration list for PBXProject "ElementX" */;
|
||||
compatibilityVersion = "Xcode 14.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
@@ -7325,7 +7335,6 @@
|
||||
C89CF7729E028671C5DC461E /* XCLocalSwiftPackageReference "compound-ios" */,
|
||||
);
|
||||
preferredProjectObjectVersion = 77;
|
||||
productRefGroup = 681566846AF307E9BA4C72C6 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
@@ -8649,6 +8658,9 @@
|
||||
983896D611ABF52A5C37498D /* RoomSummaryProvider.swift in Sources */,
|
||||
B5899F18AD6C56CE08FE532B /* RoomSummaryProviderMock.swift in Sources */,
|
||||
AA050DF4AEE54A641BA7CA22 /* RoomSummaryProviderProtocol.swift in Sources */,
|
||||
708FC3184CCED825F0A36273 /* RoomThreadListServiceProxy.swift in Sources */,
|
||||
38E8F5CC90DC0D716B799DE1 /* RoomThreadListServiceProxyMock.swift in Sources */,
|
||||
12F7172C93873638B23CD6AD /* RoomThreadListServiceProxyProtocol.swift in Sources */,
|
||||
4E945AD6862C403F74E57755 /* RoomTimelineItemFactory.swift in Sources */,
|
||||
13C77FDF17C4C6627CFFC205 /* RoomTimelineItemFactoryProtocol.swift in Sources */,
|
||||
70558528EF68CAAEF09972D5 /* RoomTimelineItemFixtures.swift in Sources */,
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES"
|
||||
runPostActionsOnFailure = "NO">
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
@@ -30,12 +29,6 @@
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
codeCoverageEnabled = "YES"
|
||||
onlyGenerateCoverageForSpecifiedTargets = "YES">
|
||||
<TestPlans>
|
||||
<TestPlanReference
|
||||
default = "YES"
|
||||
reference = "container:UnitTests/SupportingFiles/UnitTests.xctestplan">
|
||||
</TestPlanReference>
|
||||
</TestPlans>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
@@ -45,10 +38,6 @@
|
||||
ReferencedContainer = "container:ElementX.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<Testables>
|
||||
</Testables>
|
||||
<CommandLineArguments>
|
||||
</CommandLineArguments>
|
||||
<CodeCoverageTargets>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
@@ -58,6 +47,12 @@
|
||||
ReferencedContainer = "container:ElementX.xcodeproj">
|
||||
</BuildableReference>
|
||||
</CodeCoverageTargets>
|
||||
<TestPlans>
|
||||
<TestPlanReference
|
||||
reference = "container:UnitTests/SupportingFiles/UnitTests.xctestplan"
|
||||
default = "YES">
|
||||
</TestPlanReference>
|
||||
</TestPlans>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
@@ -79,8 +74,6 @@
|
||||
ReferencedContainer = "container:ElementX.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<CommandLineArguments>
|
||||
</CommandLineArguments>
|
||||
<EnvironmentVariables>
|
||||
<EnvironmentVariable
|
||||
key = "HTTPS_PROXY"
|
||||
@@ -115,8 +108,6 @@
|
||||
ReferencedContainer = "container:ElementX.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<CommandLineArguments>
|
||||
</CommandLineArguments>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
|
||||
@@ -6930,6 +6930,70 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol, @unchecked Sendable {
|
||||
return threadTimelineEventIDReturnValue
|
||||
}
|
||||
}
|
||||
//MARK: - threadListService
|
||||
|
||||
var threadListServiceUnderlyingCallsCount = 0
|
||||
var threadListServiceCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return threadListServiceUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = threadListServiceUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
threadListServiceUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
threadListServiceUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var threadListServiceCalled: Bool {
|
||||
return threadListServiceCallsCount > 0
|
||||
}
|
||||
|
||||
var threadListServiceUnderlyingReturnValue: RoomThreadListServiceProxyProtocol!
|
||||
var threadListServiceReturnValue: RoomThreadListServiceProxyProtocol! {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return threadListServiceUnderlyingReturnValue
|
||||
} else {
|
||||
var returnValue: RoomThreadListServiceProxyProtocol? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = threadListServiceUnderlyingReturnValue
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
threadListServiceUnderlyingReturnValue = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
threadListServiceUnderlyingReturnValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var threadListServiceClosure: (() async -> RoomThreadListServiceProxyProtocol)?
|
||||
|
||||
func threadListService() async -> RoomThreadListServiceProxyProtocol {
|
||||
threadListServiceCallsCount += 1
|
||||
if let threadListServiceClosure = threadListServiceClosure {
|
||||
return await threadListServiceClosure()
|
||||
} else {
|
||||
return threadListServiceReturnValue
|
||||
}
|
||||
}
|
||||
//MARK: - loadOrFetchEventDetails
|
||||
|
||||
var loadOrFetchEventDetailsForUnderlyingCallsCount = 0
|
||||
@@ -15957,6 +16021,83 @@ class RoomSummaryProviderMock: RoomSummaryProviderProtocol, @unchecked Sendable
|
||||
setRoomListClosure?(roomList)
|
||||
}
|
||||
}
|
||||
class RoomThreadListServiceProxyMock: RoomThreadListServiceProxyProtocol, @unchecked Sendable {
|
||||
var itemsPublisher: CurrentValuePublisher<[RoomThreadListItem], Never> {
|
||||
get { return underlyingItemsPublisher }
|
||||
set(value) { underlyingItemsPublisher = value }
|
||||
}
|
||||
var underlyingItemsPublisher: CurrentValuePublisher<[RoomThreadListItem], Never>!
|
||||
var paginationStatePublisher: CurrentValuePublisher<RoomThreadListPaginationState, Never> {
|
||||
get { return underlyingPaginationStatePublisher }
|
||||
set(value) { underlyingPaginationStatePublisher = value }
|
||||
}
|
||||
var underlyingPaginationStatePublisher: CurrentValuePublisher<RoomThreadListPaginationState, Never>!
|
||||
|
||||
//MARK: - paginate
|
||||
|
||||
var paginateUnderlyingCallsCount = 0
|
||||
var paginateCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return paginateUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = paginateUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
paginateUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
paginateUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var paginateCalled: Bool {
|
||||
return paginateCallsCount > 0
|
||||
}
|
||||
|
||||
var paginateUnderlyingReturnValue: Result<Void, RoomProxyError>!
|
||||
var paginateReturnValue: Result<Void, RoomProxyError>! {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return paginateUnderlyingReturnValue
|
||||
} else {
|
||||
var returnValue: Result<Void, RoomProxyError>? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = paginateUnderlyingReturnValue
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
paginateUnderlyingReturnValue = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
paginateUnderlyingReturnValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var paginateClosure: (() async -> Result<Void, RoomProxyError>)?
|
||||
|
||||
func paginate() async -> Result<Void, RoomProxyError> {
|
||||
paginateCallsCount += 1
|
||||
if let paginateClosure = paginateClosure {
|
||||
return await paginateClosure()
|
||||
} else {
|
||||
return paginateReturnValue
|
||||
}
|
||||
}
|
||||
}
|
||||
class SecureBackupControllerMock: SecureBackupControllerProtocol, @unchecked Sendable {
|
||||
var recoveryState: CurrentValuePublisher<SecureBackupRecoveryState, Never> {
|
||||
get { return underlyingRecoveryState }
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// Copyright 2026 Element Creations Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import Combine
|
||||
|
||||
struct RoomThreadListProxyMockConfiguration {
|
||||
var items: [RoomThreadListItem] = .mocks
|
||||
}
|
||||
|
||||
extension RoomThreadListServiceProxyMock {
|
||||
convenience init(_ configuration: RoomThreadListProxyMockConfiguration) {
|
||||
self.init()
|
||||
|
||||
itemsPublisher = CurrentValueSubject(configuration.items).asCurrentValuePublisher()
|
||||
|
||||
paginateReturnValue = .success(())
|
||||
}
|
||||
}
|
||||
|
||||
extension Array where Element == RoomThreadListItem {
|
||||
static let mocks: [RoomThreadListItem] = [
|
||||
.init(id: "1",
|
||||
rootMessageDetails: .init(sender: .init(id: "@alice:matrix.org", displayName: "Alice", avatarURL: .mockMXCUserAvatar),
|
||||
timestamp: .distantPast,
|
||||
message: .init("Ping")),
|
||||
latestMessageDetails: .init(sender: .init(id: "@bob:matrix.org"),
|
||||
timestamp: .distantFuture,
|
||||
message: .init("Pong")),
|
||||
numberOfReplies: 5),
|
||||
.init(id: "2",
|
||||
rootMessageDetails: .init(sender: .init(id: "@alice:matrix.org", displayName: "Alice", avatarURL: .mockMXCUserAvatar),
|
||||
timestamp: .distantPast,
|
||||
message: .init("Can we schedule a meeting for next week?")),
|
||||
latestMessageDetails: .init(sender: .init(id: "@bob:matrix.org"),
|
||||
timestamp: .distantFuture,
|
||||
message: .init("Looking forward to our next steps!")),
|
||||
numberOfReplies: 10)
|
||||
]
|
||||
}
|
||||
@@ -197,6 +197,18 @@ extension SDKListener: KnockRequestsListener where T == [KnockRequest] {
|
||||
}
|
||||
}
|
||||
|
||||
extension SDKListener: ThreadListEntriesListener where T == [ThreadListUpdate] {
|
||||
func onUpdate(diff: [ThreadListUpdate]) {
|
||||
onUpdateClosure(diff)
|
||||
}
|
||||
}
|
||||
|
||||
extension SDKListener: ThreadListPaginationStateListener where T == ThreadListPaginationState {
|
||||
func onUpdate(state: ThreadListPaginationState) {
|
||||
onUpdateClosure(state)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: TimelineProxy
|
||||
|
||||
extension SDKListener: PaginationStatusListener where T == PaginationStatus {
|
||||
|
||||
@@ -64,6 +64,8 @@ class ClientProxy: ClientProxyProtocol {
|
||||
|
||||
let spaceService: SpaceServiceProxyProtocol
|
||||
|
||||
let eventStringBuilder: RoomEventStringBuilder
|
||||
|
||||
private static var roomCreationPowerLevelOverrides: PowerLevels {
|
||||
.init(usersDefault: nil,
|
||||
eventsDefault: nil,
|
||||
@@ -216,6 +218,7 @@ class ClientProxy: ClientProxyProtocol {
|
||||
roomSummaryProvider = configuredAppService.roomSummaryProvider
|
||||
alternateRoomSummaryProvider = configuredAppService.alternateRoomSummaryProvider
|
||||
staticRoomSummaryProvider = configuredAppService.staticRoomSummaryProvider
|
||||
eventStringBuilder = configuredAppService.eventStringBuilder
|
||||
|
||||
syncServiceStateUpdateTaskHandle = createSyncServiceStateObserver(syncService)
|
||||
roomListStateUpdateTaskHandle = createRoomListServiceObserver(roomListService)
|
||||
@@ -1169,7 +1172,8 @@ class ClientProxy: ClientProxyProtocol {
|
||||
let roomProxy = try await JoinedRoomProxy(roomListService: roomListService,
|
||||
room: room,
|
||||
appSettings: appSettings,
|
||||
analyticsService: analyticsService)
|
||||
analyticsService: analyticsService,
|
||||
eventStringBuilder: eventStringBuilder)
|
||||
|
||||
return .joined(roomProxy)
|
||||
case .left:
|
||||
@@ -1318,6 +1322,7 @@ private struct ClientProxyServices {
|
||||
let roomSummaryProvider: RoomSummaryProviderProtocol
|
||||
let alternateRoomSummaryProvider: RoomSummaryProviderProtocol
|
||||
let staticRoomSummaryProvider: StaticRoomSummaryProviderProtocol
|
||||
let eventStringBuilder: RoomEventStringBuilder
|
||||
|
||||
init(client: ClientProtocol,
|
||||
actionsSubject: PassthroughSubject<ClientProxyAction, Never>,
|
||||
@@ -1334,10 +1339,11 @@ private struct ClientProxyServices {
|
||||
let roomMessageEventStringBuilder = RoomMessageEventStringBuilder(attributedStringBuilder: AttributedStringBuilder(cacheKey: "roomList",
|
||||
mentionBuilder: PlainMentionBuilder()),
|
||||
style: .senderPrefixed)
|
||||
let eventStringBuilder = try RoomEventStringBuilder(stateEventStringBuilder: RoomStateEventStringBuilder(userID: client.userId(), shouldDisambiguateDisplayNames: false),
|
||||
messageEventStringBuilder: roomMessageEventStringBuilder,
|
||||
shouldDisambiguateDisplayNames: false,
|
||||
shouldPrefixSenderName: true)
|
||||
|
||||
eventStringBuilder = try RoomEventStringBuilder(stateEventStringBuilder: RoomStateEventStringBuilder(userID: client.userId(), shouldDisambiguateDisplayNames: false),
|
||||
messageEventStringBuilder: roomMessageEventStringBuilder,
|
||||
shouldDisambiguateDisplayNames: false,
|
||||
shouldPrefixSenderName: true)
|
||||
|
||||
roomSummaryProvider = RoomSummaryProvider(roomListService: roomListService,
|
||||
eventStringBuilder: eventStringBuilder,
|
||||
|
||||
@@ -16,6 +16,7 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
|
||||
private let room: RoomProtocol
|
||||
private let appSettings: AppSettings
|
||||
private let analyticsService: AnalyticsService
|
||||
private let eventStringBuilder: RoomEventStringBuilder
|
||||
|
||||
// periphery:ignore - required for instance retention in the rust codebase
|
||||
private var roomInfoObservationToken: TaskHandle?
|
||||
@@ -78,11 +79,13 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
|
||||
init(roomListService: RoomListServiceProtocol,
|
||||
room: RoomProtocol,
|
||||
appSettings: AppSettings,
|
||||
analyticsService: AnalyticsService) async throws {
|
||||
analyticsService: AnalyticsService,
|
||||
eventStringBuilder: RoomEventStringBuilder) async throws {
|
||||
self.roomListService = roomListService
|
||||
self.room = room
|
||||
self.appSettings = appSettings
|
||||
self.analyticsService = analyticsService
|
||||
self.eventStringBuilder = eventStringBuilder
|
||||
|
||||
infoSubject = try await .init(RoomInfoProxy(roomInfo: room.roomInfo()))
|
||||
|
||||
@@ -200,6 +203,10 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func threadListService() async -> RoomThreadListServiceProxyProtocol {
|
||||
await RoomThreadListProxy(threadListService: room.threadListService(), eventStringBuilder: eventStringBuilder)
|
||||
}
|
||||
|
||||
func loadOrFetchEventDetails(for eventID: String) async -> Result<TimelineEvent, RoomProxyError> {
|
||||
do {
|
||||
let event = try await room.loadOrFetchEvent(eventId: eventID)
|
||||
|
||||
@@ -98,6 +98,8 @@ protocol JoinedRoomProxyProtocol: RoomProxyProtocol {
|
||||
|
||||
func threadTimeline(eventID: String) async -> Result<TimelineProxyProtocol, RoomProxyError>
|
||||
|
||||
func threadListService() async -> RoomThreadListServiceProxyProtocol
|
||||
|
||||
func loadOrFetchEventDetails(for eventID: String) async -> Result<TimelineEvent, RoomProxyError>
|
||||
|
||||
func messageFilteredTimeline(focus: TimelineFocus,
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
//
|
||||
// Copyright 2026 Element Creations Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import Combine
|
||||
import Foundation
|
||||
import MatrixRustSDK
|
||||
|
||||
class RoomThreadListProxy: RoomThreadListServiceProxyProtocol {
|
||||
private let threadListService: ThreadListServiceProtocol
|
||||
private let eventStringBuilder: RoomEventStringBuilder
|
||||
|
||||
private var itemUpdatesHandle: TaskHandle?
|
||||
private let itemsSubject = CurrentValueSubject<[RoomThreadListItem], Never>([])
|
||||
var itemsPublisher: CurrentValuePublisher<[RoomThreadListItem], Never> {
|
||||
itemsSubject.asCurrentValuePublisher()
|
||||
}
|
||||
|
||||
private var paginationStateHandle: TaskHandle?
|
||||
let paginationStatePublisher: CurrentValuePublisher<RoomThreadListPaginationState, Never>
|
||||
|
||||
init(threadListService: ThreadListServiceProtocol, eventStringBuilder: RoomEventStringBuilder, paginationToken: String? = nil) {
|
||||
self.threadListService = threadListService
|
||||
self.eventStringBuilder = eventStringBuilder
|
||||
|
||||
let paginationStateSubject = CurrentValueSubject<RoomThreadListPaginationState, Never>(.init(sdkState: threadListService.paginationState()))
|
||||
paginationStatePublisher = paginationStateSubject.asCurrentValuePublisher()
|
||||
|
||||
paginationStateHandle = threadListService.subscribeToPaginationStateUpdates(listener: SDKListener { state in
|
||||
paginationStateSubject.send(.init(sdkState: state))
|
||||
})
|
||||
|
||||
updateItems()
|
||||
|
||||
itemUpdatesHandle = self.threadListService.subscribeToItemsUpdates(listener: SDKListener { [weak self] _ in
|
||||
self?.updateItems()
|
||||
})
|
||||
}
|
||||
|
||||
func paginate() async -> Result<Void, RoomProxyError> {
|
||||
do {
|
||||
try await threadListService.paginate()
|
||||
return .success(())
|
||||
} catch {
|
||||
MXLog.error("Failed paginating with error: \(error)")
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func updateItems() {
|
||||
let items = threadListService.items().map { item in
|
||||
guard let rootMessageDetails = buildMessageDetails(item.rootEvent) else {
|
||||
fatalError("This should never fail™")
|
||||
}
|
||||
|
||||
let latestMessageDetails = buildMessageDetails(item.latestEvent)
|
||||
|
||||
return RoomThreadListItem(id: item.rootEvent.eventId,
|
||||
rootMessageDetails: rootMessageDetails,
|
||||
latestMessageDetails: latestMessageDetails,
|
||||
numberOfReplies: UInt(item.numReplies))
|
||||
}
|
||||
|
||||
itemsSubject.send(items)
|
||||
}
|
||||
|
||||
private func buildMessageDetails(_ threadListItemEvent: ThreadListItemEvent?) -> RoomThreadListItem.MessageDetails? {
|
||||
guard let threadListItemEvent else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let sender = TimelineItemSender(senderID: threadListItemEvent.sender, senderProfile: threadListItemEvent.senderProfile)
|
||||
let timestamp = Date(timeIntervalSince1970: TimeInterval(threadListItemEvent.timestamp / 1000))
|
||||
|
||||
let message: AttributedString? = if let content = threadListItemEvent.content {
|
||||
eventStringBuilder.buildAttributedString(for: content,
|
||||
sender: sender,
|
||||
isOutgoing: threadListItemEvent.isOwn)
|
||||
} else {
|
||||
nil
|
||||
}
|
||||
|
||||
return .init(sender: sender, timestamp: timestamp, message: message)
|
||||
}
|
||||
}
|
||||
|
||||
extension RoomThreadListPaginationState {
|
||||
init(sdkState: MatrixRustSDK.ThreadListPaginationState) {
|
||||
switch sdkState {
|
||||
case .loading:
|
||||
self = .loading
|
||||
case .idle(let endReached):
|
||||
self = .idle(endReached: endReached)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// Copyright 2026 Element Creations Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import Combine
|
||||
import Foundation
|
||||
|
||||
// sourcery: AutoMockable
|
||||
protocol RoomThreadListServiceProxyProtocol {
|
||||
var itemsPublisher: CurrentValuePublisher<[RoomThreadListItem], Never> { get }
|
||||
|
||||
var paginationStatePublisher: CurrentValuePublisher<RoomThreadListPaginationState, Never> { get }
|
||||
|
||||
func paginate() async -> Result<Void, RoomProxyError>
|
||||
}
|
||||
|
||||
struct RoomThreadListItem: Identifiable {
|
||||
struct MessageDetails {
|
||||
let sender: TimelineItemSender
|
||||
let timestamp: Date
|
||||
let message: AttributedString?
|
||||
}
|
||||
|
||||
let id: String
|
||||
|
||||
let rootMessageDetails: MessageDetails
|
||||
let latestMessageDetails: MessageDetails?
|
||||
|
||||
let numberOfReplies: UInt
|
||||
}
|
||||
|
||||
enum RoomThreadListPaginationState: Equatable {
|
||||
case idle(endReached: Bool)
|
||||
case loading
|
||||
}
|
||||
Reference in New Issue
Block a user