mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-05 11:58:32 +00:00
Bump the SDK to v25.06.13 and add thread support to the ComposerDraftService
This commit is contained in:
committed by
Stefan Ceriu
parent
719676875f
commit
eaf14eaaac
@@ -8736,7 +8736,7 @@
|
|||||||
repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift";
|
repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift";
|
||||||
requirement = {
|
requirement = {
|
||||||
kind = exactVersion;
|
kind = exactVersion;
|
||||||
version = "25.06.12-2";
|
version = 25.06.13;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = {
|
701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = {
|
||||||
|
|||||||
@@ -158,8 +158,8 @@
|
|||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/element-hq/matrix-rust-components-swift",
|
"location" : "https://github.com/element-hq/matrix-rust-components-swift",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "0f239a906115a792bdca0741ca20fc59a64b8e39",
|
"revision" : "d0e83c772c0e52b18e50502b9e50f551077502f9",
|
||||||
"version" : "25.6.12-2"
|
"version" : "25.6.13"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -500,7 +500,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
|
|
||||||
let completionSuggestionService = CompletionSuggestionService(roomProxy: roomProxy,
|
let completionSuggestionService = CompletionSuggestionService(roomProxy: roomProxy,
|
||||||
roomListPublisher: userSession.clientProxy.staticRoomSummaryProvider.roomListPublisher.eraseToAnyPublisher())
|
roomListPublisher: userSession.clientProxy.staticRoomSummaryProvider.roomListPublisher.eraseToAnyPublisher())
|
||||||
let composerDraftService = ComposerDraftService(roomProxy: roomProxy, timelineItemfactory: timelineItemFactory)
|
let composerDraftService = ComposerDraftService(roomProxy: roomProxy,
|
||||||
|
timelineItemfactory: timelineItemFactory,
|
||||||
|
threadRootEventID: nil)
|
||||||
|
|
||||||
let parameters = RoomScreenCoordinatorParameters(clientProxy: userSession.clientProxy,
|
let parameters = RoomScreenCoordinatorParameters(clientProxy: userSession.clientProxy,
|
||||||
roomProxy: roomProxy,
|
roomProxy: roomProxy,
|
||||||
@@ -581,11 +583,11 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
|
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
|
||||||
stateEventStringBuilder: RoomStateEventStringBuilder(userID: userSession.clientProxy.userID))
|
stateEventStringBuilder: RoomStateEventStringBuilder(userID: userSession.clientProxy.userID))
|
||||||
|
|
||||||
guard let eventID = itemID.eventID else {
|
guard let threadRootEventID = itemID.eventID else {
|
||||||
fatalError("Invalid thread event ID")
|
fatalError("Invalid thread event ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
guard case let .success(timelineController) = await timelineControllerFactory.buildThreadTimelineController(eventID: eventID,
|
guard case let .success(timelineController) = await timelineControllerFactory.buildThreadTimelineController(eventID: threadRootEventID,
|
||||||
roomProxy: roomProxy,
|
roomProxy: roomProxy,
|
||||||
timelineItemFactory: timelineItemFactory,
|
timelineItemFactory: timelineItemFactory,
|
||||||
mediaProvider: userSession.mediaProvider) else {
|
mediaProvider: userSession.mediaProvider) else {
|
||||||
@@ -595,7 +597,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
|
|
||||||
let completionSuggestionService = CompletionSuggestionService(roomProxy: roomProxy,
|
let completionSuggestionService = CompletionSuggestionService(roomProxy: roomProxy,
|
||||||
roomListPublisher: userSession.clientProxy.staticRoomSummaryProvider.roomListPublisher.eraseToAnyPublisher())
|
roomListPublisher: userSession.clientProxy.staticRoomSummaryProvider.roomListPublisher.eraseToAnyPublisher())
|
||||||
let composerDraftService = ComposerDraftService(roomProxy: roomProxy, timelineItemfactory: timelineItemFactory)
|
let composerDraftService = ComposerDraftService(roomProxy: roomProxy,
|
||||||
|
timelineItemfactory: timelineItemFactory,
|
||||||
|
threadRootEventID: threadRootEventID)
|
||||||
|
|
||||||
let coordinator = ThreadTimelineScreenCoordinator(parameters: .init(clientProxy: userSession.clientProxy,
|
let coordinator = ThreadTimelineScreenCoordinator(parameters: .init(clientProxy: userSession.clientProxy,
|
||||||
roomProxy: roomProxy,
|
roomProxy: roomProxy,
|
||||||
|
|||||||
@@ -10121,15 +10121,15 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
//MARK: - saveDraft
|
//MARK: - saveDraft
|
||||||
|
|
||||||
var saveDraftUnderlyingCallsCount = 0
|
var saveDraftThreadRootEventIDUnderlyingCallsCount = 0
|
||||||
var saveDraftCallsCount: Int {
|
var saveDraftThreadRootEventIDCallsCount: Int {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return saveDraftUnderlyingCallsCount
|
return saveDraftThreadRootEventIDUnderlyingCallsCount
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Int? = nil
|
var returnValue: Int? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = saveDraftUnderlyingCallsCount
|
returnValue = saveDraftThreadRootEventIDUnderlyingCallsCount
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -10137,29 +10137,29 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
saveDraftUnderlyingCallsCount = newValue
|
saveDraftThreadRootEventIDUnderlyingCallsCount = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
saveDraftUnderlyingCallsCount = newValue
|
saveDraftThreadRootEventIDUnderlyingCallsCount = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var saveDraftCalled: Bool {
|
var saveDraftThreadRootEventIDCalled: Bool {
|
||||||
return saveDraftCallsCount > 0
|
return saveDraftThreadRootEventIDCallsCount > 0
|
||||||
}
|
}
|
||||||
var saveDraftReceivedDraft: ComposerDraft?
|
var saveDraftThreadRootEventIDReceivedArguments: (draft: ComposerDraft, threadRootEventID: String?)?
|
||||||
var saveDraftReceivedInvocations: [ComposerDraft] = []
|
var saveDraftThreadRootEventIDReceivedInvocations: [(draft: ComposerDraft, threadRootEventID: String?)] = []
|
||||||
|
|
||||||
var saveDraftUnderlyingReturnValue: Result<Void, RoomProxyError>!
|
var saveDraftThreadRootEventIDUnderlyingReturnValue: Result<Void, RoomProxyError>!
|
||||||
var saveDraftReturnValue: Result<Void, RoomProxyError>! {
|
var saveDraftThreadRootEventIDReturnValue: Result<Void, RoomProxyError>! {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return saveDraftUnderlyingReturnValue
|
return saveDraftThreadRootEventIDUnderlyingReturnValue
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Result<Void, RoomProxyError>? = nil
|
var returnValue: Result<Void, RoomProxyError>? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = saveDraftUnderlyingReturnValue
|
returnValue = saveDraftThreadRootEventIDUnderlyingReturnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -10167,39 +10167,39 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
saveDraftUnderlyingReturnValue = newValue
|
saveDraftThreadRootEventIDUnderlyingReturnValue = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
saveDraftUnderlyingReturnValue = newValue
|
saveDraftThreadRootEventIDUnderlyingReturnValue = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var saveDraftClosure: ((ComposerDraft) async -> Result<Void, RoomProxyError>)?
|
var saveDraftThreadRootEventIDClosure: ((ComposerDraft, String?) async -> Result<Void, RoomProxyError>)?
|
||||||
|
|
||||||
func saveDraft(_ draft: ComposerDraft) async -> Result<Void, RoomProxyError> {
|
func saveDraft(_ draft: ComposerDraft, threadRootEventID: String?) async -> Result<Void, RoomProxyError> {
|
||||||
saveDraftCallsCount += 1
|
saveDraftThreadRootEventIDCallsCount += 1
|
||||||
saveDraftReceivedDraft = draft
|
saveDraftThreadRootEventIDReceivedArguments = (draft: draft, threadRootEventID: threadRootEventID)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.saveDraftReceivedInvocations.append(draft)
|
self.saveDraftThreadRootEventIDReceivedInvocations.append((draft: draft, threadRootEventID: threadRootEventID))
|
||||||
}
|
}
|
||||||
if let saveDraftClosure = saveDraftClosure {
|
if let saveDraftThreadRootEventIDClosure = saveDraftThreadRootEventIDClosure {
|
||||||
return await saveDraftClosure(draft)
|
return await saveDraftThreadRootEventIDClosure(draft, threadRootEventID)
|
||||||
} else {
|
} else {
|
||||||
return saveDraftReturnValue
|
return saveDraftThreadRootEventIDReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//MARK: - loadDraft
|
//MARK: - loadDraft
|
||||||
|
|
||||||
var loadDraftUnderlyingCallsCount = 0
|
var loadDraftThreadRootEventIDUnderlyingCallsCount = 0
|
||||||
var loadDraftCallsCount: Int {
|
var loadDraftThreadRootEventIDCallsCount: Int {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return loadDraftUnderlyingCallsCount
|
return loadDraftThreadRootEventIDUnderlyingCallsCount
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Int? = nil
|
var returnValue: Int? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = loadDraftUnderlyingCallsCount
|
returnValue = loadDraftThreadRootEventIDUnderlyingCallsCount
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -10207,27 +10207,29 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
loadDraftUnderlyingCallsCount = newValue
|
loadDraftThreadRootEventIDUnderlyingCallsCount = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
loadDraftUnderlyingCallsCount = newValue
|
loadDraftThreadRootEventIDUnderlyingCallsCount = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var loadDraftCalled: Bool {
|
var loadDraftThreadRootEventIDCalled: Bool {
|
||||||
return loadDraftCallsCount > 0
|
return loadDraftThreadRootEventIDCallsCount > 0
|
||||||
}
|
}
|
||||||
|
var loadDraftThreadRootEventIDReceivedThreadRootEventID: String?
|
||||||
|
var loadDraftThreadRootEventIDReceivedInvocations: [String?] = []
|
||||||
|
|
||||||
var loadDraftUnderlyingReturnValue: Result<ComposerDraft?, RoomProxyError>!
|
var loadDraftThreadRootEventIDUnderlyingReturnValue: Result<ComposerDraft?, RoomProxyError>!
|
||||||
var loadDraftReturnValue: Result<ComposerDraft?, RoomProxyError>! {
|
var loadDraftThreadRootEventIDReturnValue: Result<ComposerDraft?, RoomProxyError>! {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return loadDraftUnderlyingReturnValue
|
return loadDraftThreadRootEventIDUnderlyingReturnValue
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Result<ComposerDraft?, RoomProxyError>? = nil
|
var returnValue: Result<ComposerDraft?, RoomProxyError>? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = loadDraftUnderlyingReturnValue
|
returnValue = loadDraftThreadRootEventIDUnderlyingReturnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -10235,35 +10237,39 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
loadDraftUnderlyingReturnValue = newValue
|
loadDraftThreadRootEventIDUnderlyingReturnValue = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
loadDraftUnderlyingReturnValue = newValue
|
loadDraftThreadRootEventIDUnderlyingReturnValue = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var loadDraftClosure: (() async -> Result<ComposerDraft?, RoomProxyError>)?
|
var loadDraftThreadRootEventIDClosure: ((String?) async -> Result<ComposerDraft?, RoomProxyError>)?
|
||||||
|
|
||||||
func loadDraft() async -> Result<ComposerDraft?, RoomProxyError> {
|
func loadDraft(threadRootEventID: String?) async -> Result<ComposerDraft?, RoomProxyError> {
|
||||||
loadDraftCallsCount += 1
|
loadDraftThreadRootEventIDCallsCount += 1
|
||||||
if let loadDraftClosure = loadDraftClosure {
|
loadDraftThreadRootEventIDReceivedThreadRootEventID = threadRootEventID
|
||||||
return await loadDraftClosure()
|
DispatchQueue.main.async {
|
||||||
|
self.loadDraftThreadRootEventIDReceivedInvocations.append(threadRootEventID)
|
||||||
|
}
|
||||||
|
if let loadDraftThreadRootEventIDClosure = loadDraftThreadRootEventIDClosure {
|
||||||
|
return await loadDraftThreadRootEventIDClosure(threadRootEventID)
|
||||||
} else {
|
} else {
|
||||||
return loadDraftReturnValue
|
return loadDraftThreadRootEventIDReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//MARK: - clearDraft
|
//MARK: - clearDraft
|
||||||
|
|
||||||
var clearDraftUnderlyingCallsCount = 0
|
var clearDraftThreadRootEventIDUnderlyingCallsCount = 0
|
||||||
var clearDraftCallsCount: Int {
|
var clearDraftThreadRootEventIDCallsCount: Int {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return clearDraftUnderlyingCallsCount
|
return clearDraftThreadRootEventIDUnderlyingCallsCount
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Int? = nil
|
var returnValue: Int? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = clearDraftUnderlyingCallsCount
|
returnValue = clearDraftThreadRootEventIDUnderlyingCallsCount
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -10271,27 +10277,29 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
clearDraftUnderlyingCallsCount = newValue
|
clearDraftThreadRootEventIDUnderlyingCallsCount = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
clearDraftUnderlyingCallsCount = newValue
|
clearDraftThreadRootEventIDUnderlyingCallsCount = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var clearDraftCalled: Bool {
|
var clearDraftThreadRootEventIDCalled: Bool {
|
||||||
return clearDraftCallsCount > 0
|
return clearDraftThreadRootEventIDCallsCount > 0
|
||||||
}
|
}
|
||||||
|
var clearDraftThreadRootEventIDReceivedThreadRootEventID: String?
|
||||||
|
var clearDraftThreadRootEventIDReceivedInvocations: [String?] = []
|
||||||
|
|
||||||
var clearDraftUnderlyingReturnValue: Result<Void, RoomProxyError>!
|
var clearDraftThreadRootEventIDUnderlyingReturnValue: Result<Void, RoomProxyError>!
|
||||||
var clearDraftReturnValue: Result<Void, RoomProxyError>! {
|
var clearDraftThreadRootEventIDReturnValue: Result<Void, RoomProxyError>! {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return clearDraftUnderlyingReturnValue
|
return clearDraftThreadRootEventIDUnderlyingReturnValue
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Result<Void, RoomProxyError>? = nil
|
var returnValue: Result<Void, RoomProxyError>? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = clearDraftUnderlyingReturnValue
|
returnValue = clearDraftThreadRootEventIDUnderlyingReturnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -10299,22 +10307,26 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
clearDraftUnderlyingReturnValue = newValue
|
clearDraftThreadRootEventIDUnderlyingReturnValue = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
clearDraftUnderlyingReturnValue = newValue
|
clearDraftThreadRootEventIDUnderlyingReturnValue = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var clearDraftClosure: (() async -> Result<Void, RoomProxyError>)?
|
var clearDraftThreadRootEventIDClosure: ((String?) async -> Result<Void, RoomProxyError>)?
|
||||||
|
|
||||||
func clearDraft() async -> Result<Void, RoomProxyError> {
|
func clearDraft(threadRootEventID: String?) async -> Result<Void, RoomProxyError> {
|
||||||
clearDraftCallsCount += 1
|
clearDraftThreadRootEventIDCallsCount += 1
|
||||||
if let clearDraftClosure = clearDraftClosure {
|
clearDraftThreadRootEventIDReceivedThreadRootEventID = threadRootEventID
|
||||||
return await clearDraftClosure()
|
DispatchQueue.main.async {
|
||||||
|
self.clearDraftThreadRootEventIDReceivedInvocations.append(threadRootEventID)
|
||||||
|
}
|
||||||
|
if let clearDraftThreadRootEventIDClosure = clearDraftThreadRootEventIDClosure {
|
||||||
|
return await clearDraftThreadRootEventIDClosure(threadRootEventID)
|
||||||
} else {
|
} else {
|
||||||
return clearDraftReturnValue
|
return clearDraftThreadRootEventIDReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12618,16 +12618,16 @@ open class RoomSDKMock: MatrixRustSDK.Room, @unchecked Sendable {
|
|||||||
|
|
||||||
//MARK: - clearComposerDraft
|
//MARK: - clearComposerDraft
|
||||||
|
|
||||||
open var clearComposerDraftThrowableError: Error?
|
open var clearComposerDraftThreadRootThrowableError: Error?
|
||||||
var clearComposerDraftUnderlyingCallsCount = 0
|
var clearComposerDraftThreadRootUnderlyingCallsCount = 0
|
||||||
open var clearComposerDraftCallsCount: Int {
|
open var clearComposerDraftThreadRootCallsCount: Int {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return clearComposerDraftUnderlyingCallsCount
|
return clearComposerDraftThreadRootUnderlyingCallsCount
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Int? = nil
|
var returnValue: Int? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = clearComposerDraftUnderlyingCallsCount
|
returnValue = clearComposerDraftThreadRootUnderlyingCallsCount
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -12635,25 +12635,31 @@ open class RoomSDKMock: MatrixRustSDK.Room, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
clearComposerDraftUnderlyingCallsCount = newValue
|
clearComposerDraftThreadRootUnderlyingCallsCount = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
clearComposerDraftUnderlyingCallsCount = newValue
|
clearComposerDraftThreadRootUnderlyingCallsCount = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
open var clearComposerDraftCalled: Bool {
|
open var clearComposerDraftThreadRootCalled: Bool {
|
||||||
return clearComposerDraftCallsCount > 0
|
return clearComposerDraftThreadRootCallsCount > 0
|
||||||
}
|
}
|
||||||
open var clearComposerDraftClosure: (() async throws -> Void)?
|
open var clearComposerDraftThreadRootReceivedThreadRoot: String?
|
||||||
|
open var clearComposerDraftThreadRootReceivedInvocations: [String?] = []
|
||||||
|
open var clearComposerDraftThreadRootClosure: ((String?) async throws -> Void)?
|
||||||
|
|
||||||
open override func clearComposerDraft() async throws {
|
open override func clearComposerDraft(threadRoot: String?) async throws {
|
||||||
if let error = clearComposerDraftThrowableError {
|
if let error = clearComposerDraftThreadRootThrowableError {
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
clearComposerDraftCallsCount += 1
|
clearComposerDraftThreadRootCallsCount += 1
|
||||||
try await clearComposerDraftClosure?()
|
clearComposerDraftThreadRootReceivedThreadRoot = threadRoot
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.clearComposerDraftThreadRootReceivedInvocations.append(threadRoot)
|
||||||
|
}
|
||||||
|
try await clearComposerDraftThreadRootClosure?(threadRoot)
|
||||||
}
|
}
|
||||||
|
|
||||||
//MARK: - clearEventCacheStorage
|
//MARK: - clearEventCacheStorage
|
||||||
@@ -14291,16 +14297,16 @@ open class RoomSDKMock: MatrixRustSDK.Room, @unchecked Sendable {
|
|||||||
|
|
||||||
//MARK: - loadComposerDraft
|
//MARK: - loadComposerDraft
|
||||||
|
|
||||||
open var loadComposerDraftThrowableError: Error?
|
open var loadComposerDraftThreadRootThrowableError: Error?
|
||||||
var loadComposerDraftUnderlyingCallsCount = 0
|
var loadComposerDraftThreadRootUnderlyingCallsCount = 0
|
||||||
open var loadComposerDraftCallsCount: Int {
|
open var loadComposerDraftThreadRootCallsCount: Int {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return loadComposerDraftUnderlyingCallsCount
|
return loadComposerDraftThreadRootUnderlyingCallsCount
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Int? = nil
|
var returnValue: Int? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = loadComposerDraftUnderlyingCallsCount
|
returnValue = loadComposerDraftThreadRootUnderlyingCallsCount
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -14308,27 +14314,29 @@ open class RoomSDKMock: MatrixRustSDK.Room, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
loadComposerDraftUnderlyingCallsCount = newValue
|
loadComposerDraftThreadRootUnderlyingCallsCount = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
loadComposerDraftUnderlyingCallsCount = newValue
|
loadComposerDraftThreadRootUnderlyingCallsCount = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
open var loadComposerDraftCalled: Bool {
|
open var loadComposerDraftThreadRootCalled: Bool {
|
||||||
return loadComposerDraftCallsCount > 0
|
return loadComposerDraftThreadRootCallsCount > 0
|
||||||
}
|
}
|
||||||
|
open var loadComposerDraftThreadRootReceivedThreadRoot: String?
|
||||||
|
open var loadComposerDraftThreadRootReceivedInvocations: [String?] = []
|
||||||
|
|
||||||
var loadComposerDraftUnderlyingReturnValue: ComposerDraft?
|
var loadComposerDraftThreadRootUnderlyingReturnValue: ComposerDraft?
|
||||||
open var loadComposerDraftReturnValue: ComposerDraft? {
|
open var loadComposerDraftThreadRootReturnValue: ComposerDraft? {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return loadComposerDraftUnderlyingReturnValue
|
return loadComposerDraftThreadRootUnderlyingReturnValue
|
||||||
} else {
|
} else {
|
||||||
var returnValue: ComposerDraft?? = nil
|
var returnValue: ComposerDraft?? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = loadComposerDraftUnderlyingReturnValue
|
returnValue = loadComposerDraftThreadRootUnderlyingReturnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -14336,25 +14344,29 @@ open class RoomSDKMock: MatrixRustSDK.Room, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
loadComposerDraftUnderlyingReturnValue = newValue
|
loadComposerDraftThreadRootUnderlyingReturnValue = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
loadComposerDraftUnderlyingReturnValue = newValue
|
loadComposerDraftThreadRootUnderlyingReturnValue = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
open var loadComposerDraftClosure: (() async throws -> ComposerDraft?)?
|
open var loadComposerDraftThreadRootClosure: ((String?) async throws -> ComposerDraft?)?
|
||||||
|
|
||||||
open override func loadComposerDraft() async throws -> ComposerDraft? {
|
open override func loadComposerDraft(threadRoot: String?) async throws -> ComposerDraft? {
|
||||||
if let error = loadComposerDraftThrowableError {
|
if let error = loadComposerDraftThreadRootThrowableError {
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
loadComposerDraftCallsCount += 1
|
loadComposerDraftThreadRootCallsCount += 1
|
||||||
if let loadComposerDraftClosure = loadComposerDraftClosure {
|
loadComposerDraftThreadRootReceivedThreadRoot = threadRoot
|
||||||
return try await loadComposerDraftClosure()
|
DispatchQueue.main.async {
|
||||||
|
self.loadComposerDraftThreadRootReceivedInvocations.append(threadRoot)
|
||||||
|
}
|
||||||
|
if let loadComposerDraftThreadRootClosure = loadComposerDraftThreadRootClosure {
|
||||||
|
return try await loadComposerDraftThreadRootClosure(threadRoot)
|
||||||
} else {
|
} else {
|
||||||
return loadComposerDraftReturnValue
|
return loadComposerDraftThreadRootReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15858,16 +15870,16 @@ open class RoomSDKMock: MatrixRustSDK.Room, @unchecked Sendable {
|
|||||||
|
|
||||||
//MARK: - saveComposerDraft
|
//MARK: - saveComposerDraft
|
||||||
|
|
||||||
open var saveComposerDraftDraftThrowableError: Error?
|
open var saveComposerDraftDraftThreadRootThrowableError: Error?
|
||||||
var saveComposerDraftDraftUnderlyingCallsCount = 0
|
var saveComposerDraftDraftThreadRootUnderlyingCallsCount = 0
|
||||||
open var saveComposerDraftDraftCallsCount: Int {
|
open var saveComposerDraftDraftThreadRootCallsCount: Int {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return saveComposerDraftDraftUnderlyingCallsCount
|
return saveComposerDraftDraftThreadRootUnderlyingCallsCount
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Int? = nil
|
var returnValue: Int? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = saveComposerDraftDraftUnderlyingCallsCount
|
returnValue = saveComposerDraftDraftThreadRootUnderlyingCallsCount
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -15875,31 +15887,31 @@ open class RoomSDKMock: MatrixRustSDK.Room, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
saveComposerDraftDraftUnderlyingCallsCount = newValue
|
saveComposerDraftDraftThreadRootUnderlyingCallsCount = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
saveComposerDraftDraftUnderlyingCallsCount = newValue
|
saveComposerDraftDraftThreadRootUnderlyingCallsCount = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
open var saveComposerDraftDraftCalled: Bool {
|
open var saveComposerDraftDraftThreadRootCalled: Bool {
|
||||||
return saveComposerDraftDraftCallsCount > 0
|
return saveComposerDraftDraftThreadRootCallsCount > 0
|
||||||
}
|
}
|
||||||
open var saveComposerDraftDraftReceivedDraft: ComposerDraft?
|
open var saveComposerDraftDraftThreadRootReceivedArguments: (draft: ComposerDraft, threadRoot: String?)?
|
||||||
open var saveComposerDraftDraftReceivedInvocations: [ComposerDraft] = []
|
open var saveComposerDraftDraftThreadRootReceivedInvocations: [(draft: ComposerDraft, threadRoot: String?)] = []
|
||||||
open var saveComposerDraftDraftClosure: ((ComposerDraft) async throws -> Void)?
|
open var saveComposerDraftDraftThreadRootClosure: ((ComposerDraft, String?) async throws -> Void)?
|
||||||
|
|
||||||
open override func saveComposerDraft(draft: ComposerDraft) async throws {
|
open override func saveComposerDraft(draft: ComposerDraft, threadRoot: String?) async throws {
|
||||||
if let error = saveComposerDraftDraftThrowableError {
|
if let error = saveComposerDraftDraftThreadRootThrowableError {
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
saveComposerDraftDraftCallsCount += 1
|
saveComposerDraftDraftThreadRootCallsCount += 1
|
||||||
saveComposerDraftDraftReceivedDraft = draft
|
saveComposerDraftDraftThreadRootReceivedArguments = (draft: draft, threadRoot: threadRoot)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.saveComposerDraftDraftReceivedInvocations.append(draft)
|
self.saveComposerDraftDraftThreadRootReceivedInvocations.append((draft: draft, threadRoot: threadRoot))
|
||||||
}
|
}
|
||||||
try await saveComposerDraftDraftClosure?(draft)
|
try await saveComposerDraftDraftThreadRootClosure?(draft, threadRoot)
|
||||||
}
|
}
|
||||||
|
|
||||||
//MARK: - sendCallNotification
|
//MARK: - sendCallNotification
|
||||||
@@ -20955,6 +20967,71 @@ open class ThreadSummarySDKMock: MatrixRustSDK.ThreadSummary, @unchecked Sendabl
|
|||||||
return latestEventReturnValue
|
return latestEventReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//MARK: - numReplies
|
||||||
|
|
||||||
|
var numRepliesUnderlyingCallsCount = 0
|
||||||
|
open var numRepliesCallsCount: Int {
|
||||||
|
get {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
return numRepliesUnderlyingCallsCount
|
||||||
|
} else {
|
||||||
|
var returnValue: Int? = nil
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
returnValue = numRepliesUnderlyingCallsCount
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnValue!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
numRepliesUnderlyingCallsCount = newValue
|
||||||
|
} else {
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
numRepliesUnderlyingCallsCount = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
open var numRepliesCalled: Bool {
|
||||||
|
return numRepliesCallsCount > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
var numRepliesUnderlyingReturnValue: UInt64!
|
||||||
|
open var numRepliesReturnValue: UInt64! {
|
||||||
|
get {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
return numRepliesUnderlyingReturnValue
|
||||||
|
} else {
|
||||||
|
var returnValue: UInt64? = nil
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
returnValue = numRepliesUnderlyingReturnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnValue!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
numRepliesUnderlyingReturnValue = newValue
|
||||||
|
} else {
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
numRepliesUnderlyingReturnValue = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
open var numRepliesClosure: (() -> UInt64)?
|
||||||
|
|
||||||
|
open override func numReplies() -> UInt64 {
|
||||||
|
numRepliesCallsCount += 1
|
||||||
|
if let numRepliesClosure = numRepliesClosure {
|
||||||
|
return numRepliesClosure()
|
||||||
|
} else {
|
||||||
|
return numRepliesReturnValue
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
open class TimelineSDKMock: MatrixRustSDK.Timeline, @unchecked Sendable {
|
open class TimelineSDKMock: MatrixRustSDK.Timeline, @unchecked Sendable {
|
||||||
init() {
|
init() {
|
||||||
|
|||||||
@@ -135,8 +135,8 @@ extension JoinedRoomProxyMock {
|
|||||||
|
|
||||||
matrixToPermalinkReturnValue = .success(.homeDirectory)
|
matrixToPermalinkReturnValue = .success(.homeDirectory)
|
||||||
matrixToEventPermalinkReturnValue = .success(.homeDirectory)
|
matrixToEventPermalinkReturnValue = .success(.homeDirectory)
|
||||||
loadDraftReturnValue = .success(nil)
|
loadDraftThreadRootEventIDReturnValue = .success(nil)
|
||||||
clearDraftReturnValue = .success(())
|
clearDraftThreadRootEventIDReturnValue = .success(())
|
||||||
sendTypingNotificationIsTypingReturnValue = .success(())
|
sendTypingNotificationIsTypingReturnValue = .success(())
|
||||||
isVisibleInRoomDirectoryReturnValue = .success(configuration.isVisibleInPublicDirectory)
|
isVisibleInRoomDirectoryReturnValue = .success(configuration.isVisibleInPublicDirectory)
|
||||||
|
|
||||||
|
|||||||
@@ -11,16 +11,20 @@ import MatrixRustSDK
|
|||||||
|
|
||||||
final class ComposerDraftService: ComposerDraftServiceProtocol {
|
final class ComposerDraftService: ComposerDraftServiceProtocol {
|
||||||
private let roomProxy: JoinedRoomProxyProtocol
|
private let roomProxy: JoinedRoomProxyProtocol
|
||||||
|
private let threadRootEventID: String?
|
||||||
private let timelineItemfactory: RoomTimelineItemFactoryProtocol
|
private let timelineItemfactory: RoomTimelineItemFactoryProtocol
|
||||||
private var volatileDraft: ComposerDraftProxy?
|
private var volatileDraft: ComposerDraftProxy?
|
||||||
|
|
||||||
init(roomProxy: JoinedRoomProxyProtocol, timelineItemfactory: RoomTimelineItemFactoryProtocol) {
|
init(roomProxy: JoinedRoomProxyProtocol,
|
||||||
|
timelineItemfactory: RoomTimelineItemFactoryProtocol,
|
||||||
|
threadRootEventID: String?) {
|
||||||
self.roomProxy = roomProxy
|
self.roomProxy = roomProxy
|
||||||
|
self.threadRootEventID = threadRootEventID
|
||||||
self.timelineItemfactory = timelineItemfactory
|
self.timelineItemfactory = timelineItemfactory
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveDraft(_ draft: ComposerDraftProxy) async -> Result<Void, ComposerDraftServiceError> {
|
func saveDraft(_ draft: ComposerDraftProxy) async -> Result<Void, ComposerDraftServiceError> {
|
||||||
switch await roomProxy.saveDraft(draft.toRust) {
|
switch await roomProxy.saveDraft(draft.toRust, threadRootEventID: threadRootEventID) {
|
||||||
case .success:
|
case .success:
|
||||||
MXLog.info("Successfully saved draft")
|
MXLog.info("Successfully saved draft")
|
||||||
return .success(())
|
return .success(())
|
||||||
@@ -31,7 +35,7 @@ final class ComposerDraftService: ComposerDraftServiceProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func loadDraft() async -> Result<ComposerDraftProxy?, ComposerDraftServiceError> {
|
func loadDraft() async -> Result<ComposerDraftProxy?, ComposerDraftServiceError> {
|
||||||
switch await roomProxy.loadDraft() {
|
switch await roomProxy.loadDraft(threadRootEventID: threadRootEventID) {
|
||||||
case .success(let draft):
|
case .success(let draft):
|
||||||
guard let draft else {
|
guard let draft else {
|
||||||
return .success(nil)
|
return .success(nil)
|
||||||
@@ -54,7 +58,7 @@ final class ComposerDraftService: ComposerDraftServiceProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func clearDraft() async -> Result<Void, ComposerDraftServiceError> {
|
func clearDraft() async -> Result<Void, ComposerDraftServiceError> {
|
||||||
switch await roomProxy.clearDraft() {
|
switch await roomProxy.clearDraft(threadRootEventID: threadRootEventID) {
|
||||||
case .success:
|
case .success:
|
||||||
MXLog.info("Successfully cleared draft")
|
MXLog.info("Successfully cleared draft")
|
||||||
return .success(())
|
return .success(())
|
||||||
|
|||||||
@@ -772,9 +772,9 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
|
|||||||
|
|
||||||
// MARK: - Drafts
|
// MARK: - Drafts
|
||||||
|
|
||||||
func saveDraft(_ draft: ComposerDraft) async -> Result<Void, RoomProxyError> {
|
func saveDraft(_ draft: ComposerDraft, threadRootEventID: String?) async -> Result<Void, RoomProxyError> {
|
||||||
do {
|
do {
|
||||||
try await room.saveComposerDraft(draft: draft)
|
try await room.saveComposerDraft(draft: draft, threadRoot: threadRootEventID)
|
||||||
return .success(())
|
return .success(())
|
||||||
} catch {
|
} catch {
|
||||||
MXLog.error("Failed saving draft with error: \(error)")
|
MXLog.error("Failed saving draft with error: \(error)")
|
||||||
@@ -782,18 +782,18 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadDraft() async -> Result<ComposerDraft?, RoomProxyError> {
|
func loadDraft(threadRootEventID: String?) async -> Result<ComposerDraft?, RoomProxyError> {
|
||||||
do {
|
do {
|
||||||
return try await .success(room.loadComposerDraft())
|
return try await .success(room.loadComposerDraft(threadRoot: threadRootEventID))
|
||||||
} catch {
|
} catch {
|
||||||
MXLog.error("Failed restoring draft with error: \(error)")
|
MXLog.error("Failed restoring draft with error: \(error)")
|
||||||
return .failure(.sdkError(error))
|
return .failure(.sdkError(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func clearDraft() async -> Result<Void, RoomProxyError> {
|
func clearDraft(threadRootEventID: String?) async -> Result<Void, RoomProxyError> {
|
||||||
do {
|
do {
|
||||||
try await room.clearComposerDraft()
|
try await room.clearComposerDraft(threadRoot: threadRootEventID)
|
||||||
return .success(())
|
return .success(())
|
||||||
} catch {
|
} catch {
|
||||||
MXLog.error("Failed clearing draft with error: \(error)")
|
MXLog.error("Failed clearing draft with error: \(error)")
|
||||||
|
|||||||
@@ -187,9 +187,9 @@ protocol JoinedRoomProxyProtocol: RoomProxyProtocol {
|
|||||||
|
|
||||||
// MARK: - Drafts
|
// MARK: - Drafts
|
||||||
|
|
||||||
func saveDraft(_ draft: ComposerDraft) async -> Result<Void, RoomProxyError>
|
func saveDraft(_ draft: ComposerDraft, threadRootEventID: String?) async -> Result<Void, RoomProxyError>
|
||||||
func loadDraft() async -> Result<ComposerDraft?, RoomProxyError>
|
func loadDraft(threadRootEventID: String?) async -> Result<ComposerDraft?, RoomProxyError>
|
||||||
func clearDraft() async -> Result<Void, RoomProxyError>
|
func clearDraft(threadRootEventID: String?) async -> Result<Void, RoomProxyError>
|
||||||
}
|
}
|
||||||
|
|
||||||
extension JoinedRoomProxyProtocol {
|
extension JoinedRoomProxyProtocol {
|
||||||
|
|||||||
+1
-1
@@ -65,7 +65,7 @@ packages:
|
|||||||
# Element/Matrix dependencies
|
# Element/Matrix dependencies
|
||||||
MatrixRustSDK:
|
MatrixRustSDK:
|
||||||
url: https://github.com/element-hq/matrix-rust-components-swift
|
url: https://github.com/element-hq/matrix-rust-components-swift
|
||||||
exactVersion: 25.06.12-2
|
exactVersion: 25.06.13
|
||||||
# path: ../matrix-rust-sdk
|
# path: ../matrix-rust-sdk
|
||||||
Compound:
|
Compound:
|
||||||
url: https://github.com/element-hq/compound-ios
|
url: https://github.com/element-hq/compound-ios
|
||||||
|
|||||||
Reference in New Issue
Block a user