mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 01:20:12 +00:00
Expose a global search service from the client
Wrap the SDK's SearchService in a SearchServiceProxy that publishes typed message results and paginates on demand, expose it on the ClientProxy, and enable the search index store on the session. Also opens up the timeline item factory's message content builder so the proxy can reuse it.
This commit is contained in:
@@ -293,3 +293,11 @@ nonisolated extension SDKListener: RoomDirectorySearchEntriesListener where T ==
|
|||||||
onUpdateClosure(roomEntriesUpdate)
|
onUpdateClosure(roomEntriesUpdate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: SearchServiceProxy
|
||||||
|
|
||||||
|
nonisolated extension SDKListener: SearchServiceResultsListener where T == [SearchServiceResultsUpdate] {
|
||||||
|
func onUpdate(updates: [SearchServiceResultsUpdate]) {
|
||||||
|
onUpdateClosure(updates)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ class ClientProxy: ClientProxyProtocol {
|
|||||||
private(set) var sessionVerificationController: SessionVerificationControllerProxyProtocol?
|
private(set) var sessionVerificationController: SessionVerificationControllerProxyProtocol?
|
||||||
|
|
||||||
let spaceService: SpaceServiceProxyProtocol
|
let spaceService: SpaceServiceProxyProtocol
|
||||||
|
let searchService: SearchServiceProxyProtocol
|
||||||
|
|
||||||
let capabilities: HomeserverCapabilitiesProxyProtocol
|
let capabilities: HomeserverCapabilitiesProxyProtocol
|
||||||
|
|
||||||
@@ -236,6 +237,13 @@ class ClientProxy: ClientProxyProtocol {
|
|||||||
|
|
||||||
spaceService = await SpaceServiceProxy(spaceService: client.spaceService())
|
spaceService = await SpaceServiceProxy(spaceService: client.spaceService())
|
||||||
|
|
||||||
|
let searchUserID = try client.userId()
|
||||||
|
searchService = SearchServiceProxy(searchService: client.searchService(),
|
||||||
|
timelineItemFactory: RoomTimelineItemFactory(userID: searchUserID,
|
||||||
|
attributedStringBuilder: AttributedStringBuilder(cacheKey: "search",
|
||||||
|
mentionBuilder: PlainMentionBuilder()),
|
||||||
|
stateEventStringBuilder: RoomStateEventStringBuilder(userID: searchUserID)))
|
||||||
|
|
||||||
capabilities = HomeserverCapabilitiesProxy(underlyingCapabilities: client.homeserverCapabilities())
|
capabilities = HomeserverCapabilitiesProxy(underlyingCapabilities: client.homeserverCapabilities())
|
||||||
|
|
||||||
let configuredAppService = try await ClientProxyServices(client: client,
|
let configuredAppService = try await ClientProxyServices(client: client,
|
||||||
|
|||||||
@@ -155,6 +155,8 @@ protocol ClientProxyProtocol: AnyObject {
|
|||||||
|
|
||||||
var spaceService: SpaceServiceProxyProtocol { get }
|
var spaceService: SpaceServiceProxyProtocol { get }
|
||||||
|
|
||||||
|
var searchService: SearchServiceProxyProtocol { get }
|
||||||
|
|
||||||
var capabilities: HomeserverCapabilitiesProxyProtocol { get }
|
var capabilities: HomeserverCapabilitiesProxyProtocol { get }
|
||||||
|
|
||||||
var isReportRoomSupported: Bool { get async }
|
var isReportRoomSupported: Bool { get async }
|
||||||
|
|||||||
@@ -0,0 +1,122 @@
|
|||||||
|
// Copyright 2025 Element Creations Ltd.
|
||||||
|
// Copyright 2025 New Vector 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 SearchServiceProxy: SearchServiceProxyProtocol {
|
||||||
|
private let searchService: SearchServiceProtocol
|
||||||
|
private let timelineItemFactory: RoomTimelineItemFactoryProtocol
|
||||||
|
|
||||||
|
// periphery:ignore - required for instance retention in the rust codebase
|
||||||
|
private var resultsHandle: TaskHandle?
|
||||||
|
|
||||||
|
private let resultsSubject = CurrentValueSubject<[SearchServiceResult], Never>([])
|
||||||
|
var resultsPublisher: CurrentValuePublisher<[SearchServiceResult], Never> {
|
||||||
|
resultsSubject.asCurrentValuePublisher()
|
||||||
|
}
|
||||||
|
|
||||||
|
init(searchService: SearchServiceProtocol, timelineItemFactory: RoomTimelineItemFactoryProtocol) {
|
||||||
|
self.searchService = searchService
|
||||||
|
self.timelineItemFactory = timelineItemFactory
|
||||||
|
}
|
||||||
|
|
||||||
|
func setQuery(_ query: String) async -> Result<Void, SearchServiceProxyError> {
|
||||||
|
if resultsHandle == nil {
|
||||||
|
resultsHandle = await searchService.subscribeToResults(listener: SDKListener.onMainActor { [weak self] updates in
|
||||||
|
self?.handleResultUpdates(updates)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
try await searchService.setQuery(query: query)
|
||||||
|
return .success(())
|
||||||
|
} catch {
|
||||||
|
MXLog.error("Failed to set search query: \(error)")
|
||||||
|
return .failure(.sdkError(error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func paginate() async {
|
||||||
|
do {
|
||||||
|
try await searchService.paginate()
|
||||||
|
} catch {
|
||||||
|
MXLog.error("Failed to paginate search results: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Private
|
||||||
|
|
||||||
|
private func handleResultUpdates(_ updates: [SearchServiceResultsUpdate]) {
|
||||||
|
var results = resultsSubject.value
|
||||||
|
|
||||||
|
for update in updates {
|
||||||
|
switch update {
|
||||||
|
case .append(let values):
|
||||||
|
results.append(contentsOf: values.compactMap { self.makeResult($0) })
|
||||||
|
case .clear:
|
||||||
|
results.removeAll()
|
||||||
|
case .pushFront(let value):
|
||||||
|
if let result = makeResult(value) {
|
||||||
|
results.insert(result, at: 0)
|
||||||
|
}
|
||||||
|
case .pushBack(let value):
|
||||||
|
if let result = makeResult(value) {
|
||||||
|
results.append(result)
|
||||||
|
}
|
||||||
|
case .popFront:
|
||||||
|
results.removeFirst()
|
||||||
|
case .popBack:
|
||||||
|
results.removeLast()
|
||||||
|
case .insert(let index, let value):
|
||||||
|
if let result = makeResult(value) {
|
||||||
|
results.insert(result, at: Int(index))
|
||||||
|
}
|
||||||
|
case .set(let index, let value):
|
||||||
|
if let result = makeResult(value) {
|
||||||
|
results[Int(index)] = result
|
||||||
|
}
|
||||||
|
case .remove(let index):
|
||||||
|
results.remove(at: Int(index))
|
||||||
|
case .truncate(let length):
|
||||||
|
results.removeSubrange(Int(length)..<results.count)
|
||||||
|
case .reset(let values):
|
||||||
|
results = values.compactMap { self.makeResult($0) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resultsSubject.send(results)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func makeResult(_ searchResult: MatrixRustSDK.SearchServiceResult) -> SearchServiceResult? {
|
||||||
|
switch searchResult {
|
||||||
|
case .message(let roomID, let result):
|
||||||
|
let sender = TimelineItemSender(senderID: result.sender, senderProfile: result.senderProfile)
|
||||||
|
|
||||||
|
let content: TimelineEventContent
|
||||||
|
switch result.content {
|
||||||
|
case .msgLike(let msgLike):
|
||||||
|
switch msgLike.kind {
|
||||||
|
case .message(let msg):
|
||||||
|
content = .message(timelineItemFactory.buildMessageTimelineItemContent(messageType: msg.msgType,
|
||||||
|
senderID: result.sender,
|
||||||
|
senderDisplayName: sender.displayName))
|
||||||
|
default:
|
||||||
|
content = .message(.text(.init(body: L10n.commonUnsupportedEvent)))
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
content = .message(.text(.init(body: L10n.commonUnsupportedEvent)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return SearchServiceResult(roomID: roomID,
|
||||||
|
eventID: result.eventId,
|
||||||
|
sender: sender,
|
||||||
|
content: content,
|
||||||
|
timestamp: Date(timeIntervalSince1970: TimeInterval(result.timestamp) / 1000))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
// Copyright 2025 Element Creations Ltd.
|
||||||
|
// Copyright 2025 New Vector 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
|
||||||
|
|
||||||
|
enum SearchServiceProxyError: Error {
|
||||||
|
case sdkError(Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sourcery: AutoMockable
|
||||||
|
protocol SearchServiceProxyProtocol {
|
||||||
|
var resultsPublisher: CurrentValuePublisher<[SearchServiceResult], Never> { get }
|
||||||
|
|
||||||
|
func setQuery(_ query: String) async -> Result<Void, SearchServiceProxyError>
|
||||||
|
|
||||||
|
/// Loads the next page of results. No-ops if a page is already loading or the end has been reached.
|
||||||
|
func paginate() async
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SearchServiceResult {
|
||||||
|
let roomID: String
|
||||||
|
let eventID: String
|
||||||
|
let sender: TimelineItemSender
|
||||||
|
let content: TimelineEventContent
|
||||||
|
let timestamp: Date
|
||||||
|
}
|
||||||
@@ -895,7 +895,7 @@ nonisolated struct RoomTimelineItemFactory: RoomTimelineItemFactoryProtocol {
|
|||||||
|
|
||||||
// MARK: - Helpers
|
// MARK: - Helpers
|
||||||
|
|
||||||
private func buildMessageTimelineItemContent(messageType: MessageType?, senderID: String, senderDisplayName: String?) -> EventBasedMessageTimelineItemContentType {
|
func buildMessageTimelineItemContent(messageType: MessageType?, senderID: String, senderDisplayName: String?) -> EventBasedMessageTimelineItemContentType {
|
||||||
switch messageType {
|
switch messageType {
|
||||||
case .audio(let content):
|
case .audio(let content):
|
||||||
if content.voice != nil {
|
if content.voice != nil {
|
||||||
|
|||||||
@@ -12,4 +12,5 @@ import MatrixRustSDK
|
|||||||
nonisolated protocol RoomTimelineItemFactoryProtocol: Sendable {
|
nonisolated protocol RoomTimelineItemFactoryProtocol: Sendable {
|
||||||
func buildTimelineItem(for eventItemProxy: EventTimelineItemProxy, isDM: Bool) -> RoomTimelineItemProtocol?
|
func buildTimelineItem(for eventItemProxy: EventTimelineItemProxy, isDM: Bool) -> RoomTimelineItemProtocol?
|
||||||
func buildTimelineItemReply(_ details: MatrixRustSDK.InReplyToDetails) -> TimelineItemReply
|
func buildTimelineItemReply(_ details: MatrixRustSDK.InReplyToDetails) -> TimelineItemReply
|
||||||
|
func buildMessageTimelineItemContent(messageType: MessageType?, senderID: String, senderDisplayName: String?) -> EventBasedMessageTimelineItemContentType
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,6 +140,8 @@ class UserSessionStore: UserSessionStoreProtocol {
|
|||||||
.sqliteStore(config: .init(dataPath: credentials.restorationToken.sessionDirectories.dataPath,
|
.sqliteStore(config: .init(dataPath: credentials.restorationToken.sessionDirectories.dataPath,
|
||||||
cachePath: credentials.restorationToken.sessionDirectories.cachePath)
|
cachePath: credentials.restorationToken.sessionDirectories.cachePath)
|
||||||
.passphrase(passphrase: credentials.restorationToken.passphrase))
|
.passphrase(passphrase: credentials.restorationToken.passphrase))
|
||||||
|
.withSearchIndexStore(path: credentials.restorationToken.sessionDirectories.dataPath,
|
||||||
|
password: credentials.restorationToken.passphrase)
|
||||||
.username(username: credentials.userID)
|
.username(username: credentials.userID)
|
||||||
.homeserverUrl(url: homeserverURL)
|
.homeserverUrl(url: homeserverURL)
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,21 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
open class BackupSecretsSDKMock: MatrixRustSDK.BackupSecrets, @unchecked Sendable {
|
||||||
|
public init() {
|
||||||
|
super.init(noHandle: .init())
|
||||||
|
}
|
||||||
|
|
||||||
|
public required init(unsafeFromHandle handle: UInt64) {
|
||||||
|
fatalError("init(unsafeFromHandle:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate var handle: UInt64 {
|
||||||
|
get { return underlyingHandle }
|
||||||
|
set(value) { underlyingHandle = value }
|
||||||
|
}
|
||||||
|
fileprivate var underlyingHandle: UInt64!
|
||||||
|
}
|
||||||
open class CheckCodeSenderSDKMock: MatrixRustSDK.CheckCodeSender, @unchecked Sendable {
|
open class CheckCodeSenderSDKMock: MatrixRustSDK.CheckCodeSender, @unchecked Sendable {
|
||||||
public init() {
|
public init() {
|
||||||
super.init(noHandle: .init())
|
super.init(noHandle: .init())
|
||||||
@@ -4173,50 +4188,32 @@ open class ClientSDKMock: MatrixRustSDK.Client, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//MARK: - searchMessages
|
//MARK: - searchService
|
||||||
|
|
||||||
open var searchMessagesQueryFilterThrowableError: Error?
|
private let searchServiceCallsCountLock = NSLock()
|
||||||
private let searchMessagesQueryFilterCallsCountLock = NSLock()
|
private var searchServiceUnderlyingCallsCount = 0
|
||||||
private var searchMessagesQueryFilterUnderlyingCallsCount = 0
|
open var searchServiceCallsCount: Int {
|
||||||
open var searchMessagesQueryFilterCallsCount: Int {
|
get { searchServiceCallsCountLock.withLock { searchServiceUnderlyingCallsCount } }
|
||||||
get { searchMessagesQueryFilterCallsCountLock.withLock { searchMessagesQueryFilterUnderlyingCallsCount } }
|
set { searchServiceCallsCountLock.withLock { searchServiceUnderlyingCallsCount = newValue } }
|
||||||
set { searchMessagesQueryFilterCallsCountLock.withLock { searchMessagesQueryFilterUnderlyingCallsCount = newValue } }
|
|
||||||
}
|
}
|
||||||
open var searchMessagesQueryFilterCalled: Bool {
|
open var searchServiceCalled: Bool {
|
||||||
return searchMessagesQueryFilterCallsCount > 0
|
return searchServiceCallsCount > 0
|
||||||
}
|
|
||||||
private let searchMessagesQueryFilterReceivedArgumentsLock = NSLock()
|
|
||||||
private var searchMessagesQueryFilterUnderlyingReceivedArguments: (query: String, filter: SearchRoomFilter)?
|
|
||||||
open var searchMessagesQueryFilterReceivedArguments: (query: String, filter: SearchRoomFilter)? {
|
|
||||||
get { searchMessagesQueryFilterReceivedArgumentsLock.withLock { searchMessagesQueryFilterUnderlyingReceivedArguments } }
|
|
||||||
set { searchMessagesQueryFilterReceivedArgumentsLock.withLock { searchMessagesQueryFilterUnderlyingReceivedArguments = newValue } }
|
|
||||||
}
|
|
||||||
private let searchMessagesQueryFilterReceivedInvocationsLock = NSLock()
|
|
||||||
private var searchMessagesQueryFilterUnderlyingReceivedInvocations: [(query: String, filter: SearchRoomFilter)] = []
|
|
||||||
open var searchMessagesQueryFilterReceivedInvocations: [(query: String, filter: SearchRoomFilter)] {
|
|
||||||
get { searchMessagesQueryFilterReceivedInvocationsLock.withLock { searchMessagesQueryFilterUnderlyingReceivedInvocations } }
|
|
||||||
set { searchMessagesQueryFilterReceivedInvocationsLock.withLock { searchMessagesQueryFilterUnderlyingReceivedInvocations = newValue } }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private let searchMessagesQueryFilterReturnValueLock = NSLock()
|
private let searchServiceReturnValueLock = NSLock()
|
||||||
open var searchMessagesQueryFilterUnderlyingReturnValue: GlobalSearchIterator!
|
open var searchServiceUnderlyingReturnValue: SearchService!
|
||||||
open var searchMessagesQueryFilterReturnValue: GlobalSearchIterator! {
|
open var searchServiceReturnValue: SearchService! {
|
||||||
get { searchMessagesQueryFilterReturnValueLock.withLock { searchMessagesQueryFilterUnderlyingReturnValue } }
|
get { searchServiceReturnValueLock.withLock { searchServiceUnderlyingReturnValue } }
|
||||||
set { searchMessagesQueryFilterReturnValueLock.withLock { searchMessagesQueryFilterUnderlyingReturnValue = newValue } }
|
set { searchServiceReturnValueLock.withLock { searchServiceUnderlyingReturnValue = newValue } }
|
||||||
}
|
}
|
||||||
open var searchMessagesQueryFilterClosure: ((String, SearchRoomFilter) async throws -> GlobalSearchIterator)?
|
open var searchServiceClosure: (() -> SearchService)?
|
||||||
|
|
||||||
open override func searchMessages(query: String, filter: SearchRoomFilter) async throws -> GlobalSearchIterator {
|
open override func searchService() -> SearchService {
|
||||||
if let error = searchMessagesQueryFilterThrowableError {
|
searchServiceCallsCountLock.withLock { searchServiceUnderlyingCallsCount += 1 }
|
||||||
throw error
|
if let searchServiceClosure = searchServiceClosure {
|
||||||
}
|
return searchServiceClosure()
|
||||||
searchMessagesQueryFilterCallsCountLock.withLock { searchMessagesQueryFilterUnderlyingCallsCount += 1 }
|
|
||||||
searchMessagesQueryFilterReceivedArguments = (query: query, filter: filter)
|
|
||||||
searchMessagesQueryFilterReceivedInvocationsLock.withLock { searchMessagesQueryFilterUnderlyingReceivedInvocations.append((query: query, filter: filter)) }
|
|
||||||
if let searchMessagesQueryFilterClosure = searchMessagesQueryFilterClosure {
|
|
||||||
return try await searchMessagesQueryFilterClosure(query, filter)
|
|
||||||
} else {
|
} else {
|
||||||
return searchMessagesQueryFilterReturnValue
|
return searchServiceReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5421,6 +5418,21 @@ open class ContentScannerSDKMock: MatrixRustSDK.ContentScanner, @unchecked Senda
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
open class CrossSigningSecretsSDKMock: MatrixRustSDK.CrossSigningSecrets, @unchecked Sendable {
|
||||||
|
public init() {
|
||||||
|
super.init(noHandle: .init())
|
||||||
|
}
|
||||||
|
|
||||||
|
public required init(unsafeFromHandle handle: UInt64) {
|
||||||
|
fatalError("init(unsafeFromHandle:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate var handle: UInt64 {
|
||||||
|
get { return underlyingHandle }
|
||||||
|
set(value) { underlyingHandle = value }
|
||||||
|
}
|
||||||
|
fileprivate var underlyingHandle: UInt64!
|
||||||
|
}
|
||||||
open class EncryptionSDKMock: MatrixRustSDK.Encryption, @unchecked Sendable {
|
open class EncryptionSDKMock: MatrixRustSDK.Encryption, @unchecked Sendable {
|
||||||
public init() {
|
public init() {
|
||||||
super.init(noHandle: .init())
|
super.init(noHandle: .init())
|
||||||
@@ -6222,54 +6234,6 @@ open class EncryptionSDKMock: MatrixRustSDK.Encryption, @unchecked Sendable {
|
|||||||
await waitForE2eeInitializationTasksClosure?()
|
await waitForE2eeInitializationTasksClosure?()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
open class GlobalSearchIteratorSDKMock: MatrixRustSDK.GlobalSearchIterator, @unchecked Sendable {
|
|
||||||
public init() {
|
|
||||||
super.init(noHandle: .init())
|
|
||||||
}
|
|
||||||
|
|
||||||
public required init(unsafeFromHandle handle: UInt64) {
|
|
||||||
fatalError("init(unsafeFromHandle:) has not been implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
fileprivate var handle: UInt64 {
|
|
||||||
get { return underlyingHandle }
|
|
||||||
set(value) { underlyingHandle = value }
|
|
||||||
}
|
|
||||||
fileprivate var underlyingHandle: UInt64!
|
|
||||||
|
|
||||||
//MARK: - nextEvents
|
|
||||||
|
|
||||||
open var nextEventsThrowableError: Error?
|
|
||||||
private let nextEventsCallsCountLock = NSLock()
|
|
||||||
private var nextEventsUnderlyingCallsCount = 0
|
|
||||||
open var nextEventsCallsCount: Int {
|
|
||||||
get { nextEventsCallsCountLock.withLock { nextEventsUnderlyingCallsCount } }
|
|
||||||
set { nextEventsCallsCountLock.withLock { nextEventsUnderlyingCallsCount = newValue } }
|
|
||||||
}
|
|
||||||
open var nextEventsCalled: Bool {
|
|
||||||
return nextEventsCallsCount > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
private let nextEventsReturnValueLock = NSLock()
|
|
||||||
open var nextEventsUnderlyingReturnValue: [GlobalSearchResult]?
|
|
||||||
open var nextEventsReturnValue: [GlobalSearchResult]? {
|
|
||||||
get { nextEventsReturnValueLock.withLock { nextEventsUnderlyingReturnValue } }
|
|
||||||
set { nextEventsReturnValueLock.withLock { nextEventsUnderlyingReturnValue = newValue } }
|
|
||||||
}
|
|
||||||
open var nextEventsClosure: (() async throws -> [GlobalSearchResult]?)?
|
|
||||||
|
|
||||||
open override func nextEvents() async throws -> [GlobalSearchResult]? {
|
|
||||||
if let error = nextEventsThrowableError {
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
nextEventsCallsCountLock.withLock { nextEventsUnderlyingCallsCount += 1 }
|
|
||||||
if let nextEventsClosure = nextEventsClosure {
|
|
||||||
return try await nextEventsClosure()
|
|
||||||
} else {
|
|
||||||
return nextEventsReturnValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
open class GrantLoginWithQrCodeHandlerSDKMock: MatrixRustSDK.GrantLoginWithQrCodeHandler, @unchecked Sendable {
|
open class GrantLoginWithQrCodeHandlerSDKMock: MatrixRustSDK.GrantLoginWithQrCodeHandler, @unchecked Sendable {
|
||||||
public init() {
|
public init() {
|
||||||
super.init(noHandle: .init())
|
super.init(noHandle: .init())
|
||||||
@@ -8689,6 +8653,21 @@ open class OAuthAuthorizationDataSDKMock: MatrixRustSDK.OAuthAuthorizationData,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
open class PrivateStringSDKMock: MatrixRustSDK.PrivateString, @unchecked Sendable {
|
||||||
|
public init() {
|
||||||
|
super.init(noHandle: .init())
|
||||||
|
}
|
||||||
|
|
||||||
|
public required init(unsafeFromHandle handle: UInt64) {
|
||||||
|
fatalError("init(unsafeFromHandle:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate var handle: UInt64 {
|
||||||
|
get { return underlyingHandle }
|
||||||
|
set(value) { underlyingHandle = value }
|
||||||
|
}
|
||||||
|
fileprivate var underlyingHandle: UInt64!
|
||||||
|
}
|
||||||
open class QrCodeDataSDKMock: MatrixRustSDK.QrCodeData, @unchecked Sendable {
|
open class QrCodeDataSDKMock: MatrixRustSDK.QrCodeData, @unchecked Sendable {
|
||||||
public init() {
|
public init() {
|
||||||
super.init(noHandle: .init())
|
super.init(noHandle: .init())
|
||||||
@@ -12307,49 +12286,6 @@ open class RoomSDKMock: MatrixRustSDK.Room, @unchecked Sendable {
|
|||||||
withdrawVerificationAndResendUserIdsSendHandleReceivedInvocationsLock.withLock { withdrawVerificationAndResendUserIdsSendHandleUnderlyingReceivedInvocations.append((userIds: userIds, sendHandle: sendHandle)) }
|
withdrawVerificationAndResendUserIdsSendHandleReceivedInvocationsLock.withLock { withdrawVerificationAndResendUserIdsSendHandleUnderlyingReceivedInvocations.append((userIds: userIds, sendHandle: sendHandle)) }
|
||||||
try await withdrawVerificationAndResendUserIdsSendHandleClosure?(userIds, sendHandle)
|
try await withdrawVerificationAndResendUserIdsSendHandleClosure?(userIds, sendHandle)
|
||||||
}
|
}
|
||||||
|
|
||||||
//MARK: - searchMessages
|
|
||||||
|
|
||||||
private let searchMessagesQueryCallsCountLock = NSLock()
|
|
||||||
private var searchMessagesQueryUnderlyingCallsCount = 0
|
|
||||||
open var searchMessagesQueryCallsCount: Int {
|
|
||||||
get { searchMessagesQueryCallsCountLock.withLock { searchMessagesQueryUnderlyingCallsCount } }
|
|
||||||
set { searchMessagesQueryCallsCountLock.withLock { searchMessagesQueryUnderlyingCallsCount = newValue } }
|
|
||||||
}
|
|
||||||
open var searchMessagesQueryCalled: Bool {
|
|
||||||
return searchMessagesQueryCallsCount > 0
|
|
||||||
}
|
|
||||||
private let searchMessagesQueryReceivedQueryLock = NSLock()
|
|
||||||
private var searchMessagesQueryUnderlyingReceivedQuery: String?
|
|
||||||
open var searchMessagesQueryReceivedQuery: String? {
|
|
||||||
get { searchMessagesQueryReceivedQueryLock.withLock { searchMessagesQueryUnderlyingReceivedQuery } }
|
|
||||||
set { searchMessagesQueryReceivedQueryLock.withLock { searchMessagesQueryUnderlyingReceivedQuery = newValue } }
|
|
||||||
}
|
|
||||||
private let searchMessagesQueryReceivedInvocationsLock = NSLock()
|
|
||||||
private var searchMessagesQueryUnderlyingReceivedInvocations: [String] = []
|
|
||||||
open var searchMessagesQueryReceivedInvocations: [String] {
|
|
||||||
get { searchMessagesQueryReceivedInvocationsLock.withLock { searchMessagesQueryUnderlyingReceivedInvocations } }
|
|
||||||
set { searchMessagesQueryReceivedInvocationsLock.withLock { searchMessagesQueryUnderlyingReceivedInvocations = newValue } }
|
|
||||||
}
|
|
||||||
|
|
||||||
private let searchMessagesQueryReturnValueLock = NSLock()
|
|
||||||
open var searchMessagesQueryUnderlyingReturnValue: RoomSearchIterator!
|
|
||||||
open var searchMessagesQueryReturnValue: RoomSearchIterator! {
|
|
||||||
get { searchMessagesQueryReturnValueLock.withLock { searchMessagesQueryUnderlyingReturnValue } }
|
|
||||||
set { searchMessagesQueryReturnValueLock.withLock { searchMessagesQueryUnderlyingReturnValue = newValue } }
|
|
||||||
}
|
|
||||||
open var searchMessagesQueryClosure: ((String) -> RoomSearchIterator)?
|
|
||||||
|
|
||||||
open override func searchMessages(query: String) -> RoomSearchIterator {
|
|
||||||
searchMessagesQueryCallsCountLock.withLock { searchMessagesQueryUnderlyingCallsCount += 1 }
|
|
||||||
searchMessagesQueryReceivedQuery = query
|
|
||||||
searchMessagesQueryReceivedInvocationsLock.withLock { searchMessagesQueryUnderlyingReceivedInvocations.append(query) }
|
|
||||||
if let searchMessagesQueryClosure = searchMessagesQueryClosure {
|
|
||||||
return searchMessagesQueryClosure(query)
|
|
||||||
} else {
|
|
||||||
return searchMessagesQueryReturnValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
open class RoomDirectorySearchSDKMock: MatrixRustSDK.RoomDirectorySearch, @unchecked Sendable {
|
open class RoomDirectorySearchSDKMock: MatrixRustSDK.RoomDirectorySearch, @unchecked Sendable {
|
||||||
public init() {
|
public init() {
|
||||||
@@ -14174,7 +14110,7 @@ open class RoomPreviewSDKMock: MatrixRustSDK.RoomPreview, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
open class RoomSearchIteratorSDKMock: MatrixRustSDK.RoomSearchIterator, @unchecked Sendable {
|
open class SearchServiceSDKMock: MatrixRustSDK.SearchService, @unchecked Sendable {
|
||||||
public init() {
|
public init() {
|
||||||
super.init(noHandle: .init())
|
super.init(noHandle: .init())
|
||||||
}
|
}
|
||||||
@@ -14189,38 +14125,193 @@ open class RoomSearchIteratorSDKMock: MatrixRustSDK.RoomSearchIterator, @uncheck
|
|||||||
}
|
}
|
||||||
fileprivate var underlyingHandle: UInt64!
|
fileprivate var underlyingHandle: UInt64!
|
||||||
|
|
||||||
//MARK: - nextEvents
|
//MARK: - paginate
|
||||||
|
|
||||||
open var nextEventsThrowableError: Error?
|
open var paginateThrowableError: Error?
|
||||||
private let nextEventsCallsCountLock = NSLock()
|
private let paginateCallsCountLock = NSLock()
|
||||||
private var nextEventsUnderlyingCallsCount = 0
|
private var paginateUnderlyingCallsCount = 0
|
||||||
open var nextEventsCallsCount: Int {
|
open var paginateCallsCount: Int {
|
||||||
get { nextEventsCallsCountLock.withLock { nextEventsUnderlyingCallsCount } }
|
get { paginateCallsCountLock.withLock { paginateUnderlyingCallsCount } }
|
||||||
set { nextEventsCallsCountLock.withLock { nextEventsUnderlyingCallsCount = newValue } }
|
set { paginateCallsCountLock.withLock { paginateUnderlyingCallsCount = newValue } }
|
||||||
}
|
}
|
||||||
open var nextEventsCalled: Bool {
|
open var paginateCalled: Bool {
|
||||||
return nextEventsCallsCount > 0
|
return paginateCallsCount > 0
|
||||||
}
|
}
|
||||||
|
open var paginateClosure: (() async throws -> Void)?
|
||||||
|
|
||||||
private let nextEventsReturnValueLock = NSLock()
|
open override func paginate() async throws {
|
||||||
open var nextEventsUnderlyingReturnValue: [RoomSearchResult]?
|
if let error = paginateThrowableError {
|
||||||
open var nextEventsReturnValue: [RoomSearchResult]? {
|
|
||||||
get { nextEventsReturnValueLock.withLock { nextEventsUnderlyingReturnValue } }
|
|
||||||
set { nextEventsReturnValueLock.withLock { nextEventsUnderlyingReturnValue = newValue } }
|
|
||||||
}
|
|
||||||
open var nextEventsClosure: (() async throws -> [RoomSearchResult]?)?
|
|
||||||
|
|
||||||
open override func nextEvents() async throws -> [RoomSearchResult]? {
|
|
||||||
if let error = nextEventsThrowableError {
|
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
nextEventsCallsCountLock.withLock { nextEventsUnderlyingCallsCount += 1 }
|
paginateCallsCountLock.withLock { paginateUnderlyingCallsCount += 1 }
|
||||||
if let nextEventsClosure = nextEventsClosure {
|
try await paginateClosure?()
|
||||||
return try await nextEventsClosure()
|
}
|
||||||
|
|
||||||
|
//MARK: - paginationState
|
||||||
|
|
||||||
|
private let paginationStateCallsCountLock = NSLock()
|
||||||
|
private var paginationStateUnderlyingCallsCount = 0
|
||||||
|
open var paginationStateCallsCount: Int {
|
||||||
|
get { paginationStateCallsCountLock.withLock { paginationStateUnderlyingCallsCount } }
|
||||||
|
set { paginationStateCallsCountLock.withLock { paginationStateUnderlyingCallsCount = newValue } }
|
||||||
|
}
|
||||||
|
open var paginationStateCalled: Bool {
|
||||||
|
return paginationStateCallsCount > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
private let paginationStateReturnValueLock = NSLock()
|
||||||
|
open var paginationStateUnderlyingReturnValue: SearchServicePaginationState!
|
||||||
|
open var paginationStateReturnValue: SearchServicePaginationState! {
|
||||||
|
get { paginationStateReturnValueLock.withLock { paginationStateUnderlyingReturnValue } }
|
||||||
|
set { paginationStateReturnValueLock.withLock { paginationStateUnderlyingReturnValue = newValue } }
|
||||||
|
}
|
||||||
|
open var paginationStateClosure: (() -> SearchServicePaginationState)?
|
||||||
|
|
||||||
|
open override func paginationState() -> SearchServicePaginationState {
|
||||||
|
paginationStateCallsCountLock.withLock { paginationStateUnderlyingCallsCount += 1 }
|
||||||
|
if let paginationStateClosure = paginationStateClosure {
|
||||||
|
return paginationStateClosure()
|
||||||
} else {
|
} else {
|
||||||
return nextEventsReturnValue
|
return paginationStateReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//MARK: - setQuery
|
||||||
|
|
||||||
|
open var setQueryQueryThrowableError: Error?
|
||||||
|
private let setQueryQueryCallsCountLock = NSLock()
|
||||||
|
private var setQueryQueryUnderlyingCallsCount = 0
|
||||||
|
open var setQueryQueryCallsCount: Int {
|
||||||
|
get { setQueryQueryCallsCountLock.withLock { setQueryQueryUnderlyingCallsCount } }
|
||||||
|
set { setQueryQueryCallsCountLock.withLock { setQueryQueryUnderlyingCallsCount = newValue } }
|
||||||
|
}
|
||||||
|
open var setQueryQueryCalled: Bool {
|
||||||
|
return setQueryQueryCallsCount > 0
|
||||||
|
}
|
||||||
|
private let setQueryQueryReceivedQueryLock = NSLock()
|
||||||
|
private var setQueryQueryUnderlyingReceivedQuery: String?
|
||||||
|
open var setQueryQueryReceivedQuery: String? {
|
||||||
|
get { setQueryQueryReceivedQueryLock.withLock { setQueryQueryUnderlyingReceivedQuery } }
|
||||||
|
set { setQueryQueryReceivedQueryLock.withLock { setQueryQueryUnderlyingReceivedQuery = newValue } }
|
||||||
|
}
|
||||||
|
private let setQueryQueryReceivedInvocationsLock = NSLock()
|
||||||
|
private var setQueryQueryUnderlyingReceivedInvocations: [String] = []
|
||||||
|
open var setQueryQueryReceivedInvocations: [String] {
|
||||||
|
get { setQueryQueryReceivedInvocationsLock.withLock { setQueryQueryUnderlyingReceivedInvocations } }
|
||||||
|
set { setQueryQueryReceivedInvocationsLock.withLock { setQueryQueryUnderlyingReceivedInvocations = newValue } }
|
||||||
|
}
|
||||||
|
open var setQueryQueryClosure: ((String) async throws -> Void)?
|
||||||
|
|
||||||
|
open override func setQuery(query: String) async throws {
|
||||||
|
if let error = setQueryQueryThrowableError {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
setQueryQueryCallsCountLock.withLock { setQueryQueryUnderlyingCallsCount += 1 }
|
||||||
|
setQueryQueryReceivedQuery = query
|
||||||
|
setQueryQueryReceivedInvocationsLock.withLock { setQueryQueryUnderlyingReceivedInvocations.append(query) }
|
||||||
|
try await setQueryQueryClosure?(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: - subscribeToPaginationStateUpdates
|
||||||
|
|
||||||
|
private let subscribeToPaginationStateUpdatesListenerCallsCountLock = NSLock()
|
||||||
|
private var subscribeToPaginationStateUpdatesListenerUnderlyingCallsCount = 0
|
||||||
|
open var subscribeToPaginationStateUpdatesListenerCallsCount: Int {
|
||||||
|
get { subscribeToPaginationStateUpdatesListenerCallsCountLock.withLock { subscribeToPaginationStateUpdatesListenerUnderlyingCallsCount } }
|
||||||
|
set { subscribeToPaginationStateUpdatesListenerCallsCountLock.withLock { subscribeToPaginationStateUpdatesListenerUnderlyingCallsCount = newValue } }
|
||||||
|
}
|
||||||
|
open var subscribeToPaginationStateUpdatesListenerCalled: Bool {
|
||||||
|
return subscribeToPaginationStateUpdatesListenerCallsCount > 0
|
||||||
|
}
|
||||||
|
private let subscribeToPaginationStateUpdatesListenerReceivedListenerLock = NSLock()
|
||||||
|
private var subscribeToPaginationStateUpdatesListenerUnderlyingReceivedListener: SearchServicePaginationStateListener?
|
||||||
|
open var subscribeToPaginationStateUpdatesListenerReceivedListener: SearchServicePaginationStateListener? {
|
||||||
|
get { subscribeToPaginationStateUpdatesListenerReceivedListenerLock.withLock { subscribeToPaginationStateUpdatesListenerUnderlyingReceivedListener } }
|
||||||
|
set { subscribeToPaginationStateUpdatesListenerReceivedListenerLock.withLock { subscribeToPaginationStateUpdatesListenerUnderlyingReceivedListener = newValue } }
|
||||||
|
}
|
||||||
|
private let subscribeToPaginationStateUpdatesListenerReceivedInvocationsLock = NSLock()
|
||||||
|
private var subscribeToPaginationStateUpdatesListenerUnderlyingReceivedInvocations: [SearchServicePaginationStateListener] = []
|
||||||
|
open var subscribeToPaginationStateUpdatesListenerReceivedInvocations: [SearchServicePaginationStateListener] {
|
||||||
|
get { subscribeToPaginationStateUpdatesListenerReceivedInvocationsLock.withLock { subscribeToPaginationStateUpdatesListenerUnderlyingReceivedInvocations } }
|
||||||
|
set { subscribeToPaginationStateUpdatesListenerReceivedInvocationsLock.withLock { subscribeToPaginationStateUpdatesListenerUnderlyingReceivedInvocations = newValue } }
|
||||||
|
}
|
||||||
|
|
||||||
|
private let subscribeToPaginationStateUpdatesListenerReturnValueLock = NSLock()
|
||||||
|
open var subscribeToPaginationStateUpdatesListenerUnderlyingReturnValue: TaskHandle!
|
||||||
|
open var subscribeToPaginationStateUpdatesListenerReturnValue: TaskHandle! {
|
||||||
|
get { subscribeToPaginationStateUpdatesListenerReturnValueLock.withLock { subscribeToPaginationStateUpdatesListenerUnderlyingReturnValue } }
|
||||||
|
set { subscribeToPaginationStateUpdatesListenerReturnValueLock.withLock { subscribeToPaginationStateUpdatesListenerUnderlyingReturnValue = newValue } }
|
||||||
|
}
|
||||||
|
open var subscribeToPaginationStateUpdatesListenerClosure: ((SearchServicePaginationStateListener) -> TaskHandle)?
|
||||||
|
|
||||||
|
open override func subscribeToPaginationStateUpdates(listener: SearchServicePaginationStateListener) -> TaskHandle {
|
||||||
|
subscribeToPaginationStateUpdatesListenerCallsCountLock.withLock { subscribeToPaginationStateUpdatesListenerUnderlyingCallsCount += 1 }
|
||||||
|
subscribeToPaginationStateUpdatesListenerReceivedListener = listener
|
||||||
|
subscribeToPaginationStateUpdatesListenerReceivedInvocationsLock.withLock { subscribeToPaginationStateUpdatesListenerUnderlyingReceivedInvocations.append(listener) }
|
||||||
|
if let subscribeToPaginationStateUpdatesListenerClosure = subscribeToPaginationStateUpdatesListenerClosure {
|
||||||
|
return subscribeToPaginationStateUpdatesListenerClosure(listener)
|
||||||
|
} else {
|
||||||
|
return subscribeToPaginationStateUpdatesListenerReturnValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: - subscribeToResults
|
||||||
|
|
||||||
|
private let subscribeToResultsListenerCallsCountLock = NSLock()
|
||||||
|
private var subscribeToResultsListenerUnderlyingCallsCount = 0
|
||||||
|
open var subscribeToResultsListenerCallsCount: Int {
|
||||||
|
get { subscribeToResultsListenerCallsCountLock.withLock { subscribeToResultsListenerUnderlyingCallsCount } }
|
||||||
|
set { subscribeToResultsListenerCallsCountLock.withLock { subscribeToResultsListenerUnderlyingCallsCount = newValue } }
|
||||||
|
}
|
||||||
|
open var subscribeToResultsListenerCalled: Bool {
|
||||||
|
return subscribeToResultsListenerCallsCount > 0
|
||||||
|
}
|
||||||
|
private let subscribeToResultsListenerReceivedListenerLock = NSLock()
|
||||||
|
private var subscribeToResultsListenerUnderlyingReceivedListener: SearchServiceResultsListener?
|
||||||
|
open var subscribeToResultsListenerReceivedListener: SearchServiceResultsListener? {
|
||||||
|
get { subscribeToResultsListenerReceivedListenerLock.withLock { subscribeToResultsListenerUnderlyingReceivedListener } }
|
||||||
|
set { subscribeToResultsListenerReceivedListenerLock.withLock { subscribeToResultsListenerUnderlyingReceivedListener = newValue } }
|
||||||
|
}
|
||||||
|
private let subscribeToResultsListenerReceivedInvocationsLock = NSLock()
|
||||||
|
private var subscribeToResultsListenerUnderlyingReceivedInvocations: [SearchServiceResultsListener] = []
|
||||||
|
open var subscribeToResultsListenerReceivedInvocations: [SearchServiceResultsListener] {
|
||||||
|
get { subscribeToResultsListenerReceivedInvocationsLock.withLock { subscribeToResultsListenerUnderlyingReceivedInvocations } }
|
||||||
|
set { subscribeToResultsListenerReceivedInvocationsLock.withLock { subscribeToResultsListenerUnderlyingReceivedInvocations = newValue } }
|
||||||
|
}
|
||||||
|
|
||||||
|
private let subscribeToResultsListenerReturnValueLock = NSLock()
|
||||||
|
open var subscribeToResultsListenerUnderlyingReturnValue: TaskHandle!
|
||||||
|
open var subscribeToResultsListenerReturnValue: TaskHandle! {
|
||||||
|
get { subscribeToResultsListenerReturnValueLock.withLock { subscribeToResultsListenerUnderlyingReturnValue } }
|
||||||
|
set { subscribeToResultsListenerReturnValueLock.withLock { subscribeToResultsListenerUnderlyingReturnValue = newValue } }
|
||||||
|
}
|
||||||
|
open var subscribeToResultsListenerClosure: ((SearchServiceResultsListener) async -> TaskHandle)?
|
||||||
|
|
||||||
|
open override func subscribeToResults(listener: SearchServiceResultsListener) async -> TaskHandle {
|
||||||
|
subscribeToResultsListenerCallsCountLock.withLock { subscribeToResultsListenerUnderlyingCallsCount += 1 }
|
||||||
|
subscribeToResultsListenerReceivedListener = listener
|
||||||
|
subscribeToResultsListenerReceivedInvocationsLock.withLock { subscribeToResultsListenerUnderlyingReceivedInvocations.append(listener) }
|
||||||
|
if let subscribeToResultsListenerClosure = subscribeToResultsListenerClosure {
|
||||||
|
return await subscribeToResultsListenerClosure(listener)
|
||||||
|
} else {
|
||||||
|
return subscribeToResultsListenerReturnValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
open class SecretsBundleSDKMock: MatrixRustSDK.SecretsBundle, @unchecked Sendable {
|
||||||
|
public init() {
|
||||||
|
super.init(noHandle: .init())
|
||||||
|
}
|
||||||
|
|
||||||
|
public required init(unsafeFromHandle handle: UInt64) {
|
||||||
|
fatalError("init(unsafeFromHandle:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate var handle: UInt64 {
|
||||||
|
get { return underlyingHandle }
|
||||||
|
set(value) { underlyingHandle = value }
|
||||||
|
}
|
||||||
|
fileprivate var underlyingHandle: UInt64!
|
||||||
}
|
}
|
||||||
open class SecretsBundleWithUserIdSDKMock: MatrixRustSDK.SecretsBundleWithUserId, @unchecked Sendable {
|
open class SecretsBundleWithUserIdSDKMock: MatrixRustSDK.SecretsBundleWithUserId, @unchecked Sendable {
|
||||||
public init() {
|
public init() {
|
||||||
|
|||||||
Reference in New Issue
Block a user