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:
Stefan Ceriu
2026-03-23 17:43:38 +02:00
committed by Stefan Ceriu
parent 823e2afa97
commit e97ed6ec5c
10 changed files with 377 additions and 24 deletions
@@ -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)
]
}