mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 21:33:26 +00:00
Implement Knock Logic (#3573)
* WIP RequestToJoin struct * implemented the logic to display the cells * knock request banner accept flow * mark all knocks as seen implemented * details logic * implemented accept, decline and ban in the list * added a loader and modified the stacked view of the banner * pr suggestions * updated naming and loading strings * added the initial loading state improved code and the tests * updated a string that has changed * code improvement * tests for the room screen view model * room details tests and improved the knock requests tests for the room screen * knock requests list tests * added error state alerts with retry * struct has been renamed on the sdk so I renamed it also on the app side * update SDK
This commit is contained in:
@@ -5974,6 +5974,11 @@ class JoinedRoomProxyMock: JoinedRoomProxyProtocol {
|
||||
set(value) { underlyingIdentityStatusChangesPublisher = value }
|
||||
}
|
||||
var underlyingIdentityStatusChangesPublisher: CurrentValuePublisher<[IdentityStatusChange], Never>!
|
||||
var knockRequestsStatePublisher: CurrentValuePublisher<KnockRequestsState, Never> {
|
||||
get { return underlyingKnockRequestsStatePublisher }
|
||||
set(value) { underlyingKnockRequestsStatePublisher = value }
|
||||
}
|
||||
var underlyingKnockRequestsStatePublisher: CurrentValuePublisher<KnockRequestsState, Never>!
|
||||
var timeline: TimelineProxyProtocol {
|
||||
get { return underlyingTimeline }
|
||||
set(value) { underlyingTimeline = value }
|
||||
@@ -9610,6 +9615,284 @@ class KeychainControllerMock: KeychainControllerProtocol {
|
||||
removePINCodeBiometricStateClosure?()
|
||||
}
|
||||
}
|
||||
class KnockRequestProxyMock: KnockRequestProxyProtocol {
|
||||
var eventID: String {
|
||||
get { return underlyingEventID }
|
||||
set(value) { underlyingEventID = value }
|
||||
}
|
||||
var underlyingEventID: String!
|
||||
var userID: String {
|
||||
get { return underlyingUserID }
|
||||
set(value) { underlyingUserID = value }
|
||||
}
|
||||
var underlyingUserID: String!
|
||||
var displayName: String?
|
||||
var avatarURL: URL?
|
||||
var reason: String?
|
||||
var formattedTimestamp: String?
|
||||
var isSeen: Bool {
|
||||
get { return underlyingIsSeen }
|
||||
set(value) { underlyingIsSeen = value }
|
||||
}
|
||||
var underlyingIsSeen: Bool!
|
||||
|
||||
//MARK: - accept
|
||||
|
||||
var acceptUnderlyingCallsCount = 0
|
||||
var acceptCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return acceptUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = acceptUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
acceptUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
acceptUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var acceptCalled: Bool {
|
||||
return acceptCallsCount > 0
|
||||
}
|
||||
|
||||
var acceptUnderlyingReturnValue: Result<Void, KnockRequestProxyError>!
|
||||
var acceptReturnValue: Result<Void, KnockRequestProxyError>! {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return acceptUnderlyingReturnValue
|
||||
} else {
|
||||
var returnValue: Result<Void, KnockRequestProxyError>? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = acceptUnderlyingReturnValue
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
acceptUnderlyingReturnValue = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
acceptUnderlyingReturnValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var acceptClosure: (() async -> Result<Void, KnockRequestProxyError>)?
|
||||
|
||||
func accept() async -> Result<Void, KnockRequestProxyError> {
|
||||
acceptCallsCount += 1
|
||||
if let acceptClosure = acceptClosure {
|
||||
return await acceptClosure()
|
||||
} else {
|
||||
return acceptReturnValue
|
||||
}
|
||||
}
|
||||
//MARK: - decline
|
||||
|
||||
var declineUnderlyingCallsCount = 0
|
||||
var declineCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return declineUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = declineUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
declineUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
declineUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var declineCalled: Bool {
|
||||
return declineCallsCount > 0
|
||||
}
|
||||
|
||||
var declineUnderlyingReturnValue: Result<Void, KnockRequestProxyError>!
|
||||
var declineReturnValue: Result<Void, KnockRequestProxyError>! {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return declineUnderlyingReturnValue
|
||||
} else {
|
||||
var returnValue: Result<Void, KnockRequestProxyError>? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = declineUnderlyingReturnValue
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
declineUnderlyingReturnValue = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
declineUnderlyingReturnValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var declineClosure: (() async -> Result<Void, KnockRequestProxyError>)?
|
||||
|
||||
func decline() async -> Result<Void, KnockRequestProxyError> {
|
||||
declineCallsCount += 1
|
||||
if let declineClosure = declineClosure {
|
||||
return await declineClosure()
|
||||
} else {
|
||||
return declineReturnValue
|
||||
}
|
||||
}
|
||||
//MARK: - ban
|
||||
|
||||
var banUnderlyingCallsCount = 0
|
||||
var banCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return banUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = banUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
banUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
banUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var banCalled: Bool {
|
||||
return banCallsCount > 0
|
||||
}
|
||||
|
||||
var banUnderlyingReturnValue: Result<Void, KnockRequestProxyError>!
|
||||
var banReturnValue: Result<Void, KnockRequestProxyError>! {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return banUnderlyingReturnValue
|
||||
} else {
|
||||
var returnValue: Result<Void, KnockRequestProxyError>? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = banUnderlyingReturnValue
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
banUnderlyingReturnValue = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
banUnderlyingReturnValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var banClosure: (() async -> Result<Void, KnockRequestProxyError>)?
|
||||
|
||||
func ban() async -> Result<Void, KnockRequestProxyError> {
|
||||
banCallsCount += 1
|
||||
if let banClosure = banClosure {
|
||||
return await banClosure()
|
||||
} else {
|
||||
return banReturnValue
|
||||
}
|
||||
}
|
||||
//MARK: - markAsSeen
|
||||
|
||||
var markAsSeenUnderlyingCallsCount = 0
|
||||
var markAsSeenCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return markAsSeenUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = markAsSeenUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
markAsSeenUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
markAsSeenUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var markAsSeenCalled: Bool {
|
||||
return markAsSeenCallsCount > 0
|
||||
}
|
||||
|
||||
var markAsSeenUnderlyingReturnValue: Result<Void, KnockRequestProxyError>!
|
||||
var markAsSeenReturnValue: Result<Void, KnockRequestProxyError>! {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return markAsSeenUnderlyingReturnValue
|
||||
} else {
|
||||
var returnValue: Result<Void, KnockRequestProxyError>? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = markAsSeenUnderlyingReturnValue
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
markAsSeenUnderlyingReturnValue = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
markAsSeenUnderlyingReturnValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var markAsSeenClosure: (() async -> Result<Void, KnockRequestProxyError>)?
|
||||
|
||||
func markAsSeen() async -> Result<Void, KnockRequestProxyError> {
|
||||
markAsSeenCallsCount += 1
|
||||
if let markAsSeenClosure = markAsSeenClosure {
|
||||
return await markAsSeenClosure()
|
||||
} else {
|
||||
return markAsSeenReturnValue
|
||||
}
|
||||
}
|
||||
}
|
||||
class KnockedRoomProxyMock: KnockedRoomProxyProtocol {
|
||||
var info: BaseRoomInfoProxyProtocol {
|
||||
get { return underlyingInfo }
|
||||
|
||||
@@ -7938,6 +7938,189 @@ open class InReplyToDetailsSDKMock: MatrixRustSDK.InReplyToDetails {
|
||||
}
|
||||
}
|
||||
}
|
||||
open class KnockRequestActionsSDKMock: MatrixRustSDK.KnockRequestActions {
|
||||
init() {
|
||||
super.init(noPointer: .init())
|
||||
}
|
||||
|
||||
public required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) {
|
||||
fatalError("init(unsafeFromRawPointer:) has not been implemented")
|
||||
}
|
||||
|
||||
fileprivate var pointer: UnsafeMutableRawPointer!
|
||||
|
||||
//MARK: - accept
|
||||
|
||||
open var acceptThrowableError: Error?
|
||||
var acceptUnderlyingCallsCount = 0
|
||||
open var acceptCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return acceptUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = acceptUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
acceptUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
acceptUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var acceptCalled: Bool {
|
||||
return acceptCallsCount > 0
|
||||
}
|
||||
open var acceptClosure: (() async throws -> Void)?
|
||||
|
||||
open override func accept() async throws {
|
||||
if let error = acceptThrowableError {
|
||||
throw error
|
||||
}
|
||||
acceptCallsCount += 1
|
||||
try await acceptClosure?()
|
||||
}
|
||||
|
||||
//MARK: - decline
|
||||
|
||||
open var declineReasonThrowableError: Error?
|
||||
var declineReasonUnderlyingCallsCount = 0
|
||||
open var declineReasonCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return declineReasonUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = declineReasonUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
declineReasonUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
declineReasonUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var declineReasonCalled: Bool {
|
||||
return declineReasonCallsCount > 0
|
||||
}
|
||||
open var declineReasonReceivedReason: String?
|
||||
open var declineReasonReceivedInvocations: [String?] = []
|
||||
open var declineReasonClosure: ((String?) async throws -> Void)?
|
||||
|
||||
open override func decline(reason: String?) async throws {
|
||||
if let error = declineReasonThrowableError {
|
||||
throw error
|
||||
}
|
||||
declineReasonCallsCount += 1
|
||||
declineReasonReceivedReason = reason
|
||||
DispatchQueue.main.async {
|
||||
self.declineReasonReceivedInvocations.append(reason)
|
||||
}
|
||||
try await declineReasonClosure?(reason)
|
||||
}
|
||||
|
||||
//MARK: - declineAndBan
|
||||
|
||||
open var declineAndBanReasonThrowableError: Error?
|
||||
var declineAndBanReasonUnderlyingCallsCount = 0
|
||||
open var declineAndBanReasonCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return declineAndBanReasonUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = declineAndBanReasonUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
declineAndBanReasonUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
declineAndBanReasonUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var declineAndBanReasonCalled: Bool {
|
||||
return declineAndBanReasonCallsCount > 0
|
||||
}
|
||||
open var declineAndBanReasonReceivedReason: String?
|
||||
open var declineAndBanReasonReceivedInvocations: [String?] = []
|
||||
open var declineAndBanReasonClosure: ((String?) async throws -> Void)?
|
||||
|
||||
open override func declineAndBan(reason: String?) async throws {
|
||||
if let error = declineAndBanReasonThrowableError {
|
||||
throw error
|
||||
}
|
||||
declineAndBanReasonCallsCount += 1
|
||||
declineAndBanReasonReceivedReason = reason
|
||||
DispatchQueue.main.async {
|
||||
self.declineAndBanReasonReceivedInvocations.append(reason)
|
||||
}
|
||||
try await declineAndBanReasonClosure?(reason)
|
||||
}
|
||||
|
||||
//MARK: - markAsSeen
|
||||
|
||||
open var markAsSeenThrowableError: Error?
|
||||
var markAsSeenUnderlyingCallsCount = 0
|
||||
open var markAsSeenCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return markAsSeenUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = markAsSeenUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
markAsSeenUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
markAsSeenUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var markAsSeenCalled: Bool {
|
||||
return markAsSeenCallsCount > 0
|
||||
}
|
||||
open var markAsSeenClosure: (() async throws -> Void)?
|
||||
|
||||
open override func markAsSeen() async throws {
|
||||
if let error = markAsSeenThrowableError {
|
||||
throw error
|
||||
}
|
||||
markAsSeenCallsCount += 1
|
||||
try await markAsSeenClosure?()
|
||||
}
|
||||
}
|
||||
open class LazyTimelineItemProviderSDKMock: MatrixRustSDK.LazyTimelineItemProvider {
|
||||
init() {
|
||||
super.init(noPointer: .init())
|
||||
@@ -14018,6 +14201,81 @@ open class RoomSDKMock: MatrixRustSDK.Room {
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - subscribeToKnockRequests
|
||||
|
||||
open var subscribeToKnockRequestsListenerThrowableError: Error?
|
||||
var subscribeToKnockRequestsListenerUnderlyingCallsCount = 0
|
||||
open var subscribeToKnockRequestsListenerCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return subscribeToKnockRequestsListenerUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = subscribeToKnockRequestsListenerUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
subscribeToKnockRequestsListenerUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
subscribeToKnockRequestsListenerUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var subscribeToKnockRequestsListenerCalled: Bool {
|
||||
return subscribeToKnockRequestsListenerCallsCount > 0
|
||||
}
|
||||
open var subscribeToKnockRequestsListenerReceivedListener: KnockRequestsListener?
|
||||
open var subscribeToKnockRequestsListenerReceivedInvocations: [KnockRequestsListener] = []
|
||||
|
||||
var subscribeToKnockRequestsListenerUnderlyingReturnValue: TaskHandle!
|
||||
open var subscribeToKnockRequestsListenerReturnValue: TaskHandle! {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return subscribeToKnockRequestsListenerUnderlyingReturnValue
|
||||
} else {
|
||||
var returnValue: TaskHandle? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = subscribeToKnockRequestsListenerUnderlyingReturnValue
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
subscribeToKnockRequestsListenerUnderlyingReturnValue = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
subscribeToKnockRequestsListenerUnderlyingReturnValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var subscribeToKnockRequestsListenerClosure: ((KnockRequestsListener) async throws -> TaskHandle)?
|
||||
|
||||
open override func subscribeToKnockRequests(listener: KnockRequestsListener) async throws -> TaskHandle {
|
||||
if let error = subscribeToKnockRequestsListenerThrowableError {
|
||||
throw error
|
||||
}
|
||||
subscribeToKnockRequestsListenerCallsCount += 1
|
||||
subscribeToKnockRequestsListenerReceivedListener = listener
|
||||
DispatchQueue.main.async {
|
||||
self.subscribeToKnockRequestsListenerReceivedInvocations.append(listener)
|
||||
}
|
||||
if let subscribeToKnockRequestsListenerClosure = subscribeToKnockRequestsListenerClosure {
|
||||
return try await subscribeToKnockRequestsListenerClosure(listener)
|
||||
} else {
|
||||
return subscribeToKnockRequestsListenerReturnValue
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - subscribeToRoomInfoUpdates
|
||||
|
||||
var subscribeToRoomInfoUpdatesListenerUnderlyingCallsCount = 0
|
||||
|
||||
Reference in New Issue
Block a user