mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:55:59 +00:00
Implemented adding the room to the space after selection, and the editableSpace proxied API. Also updated and added tests.
This commit is contained in:
@@ -17100,6 +17100,70 @@ class SpaceServiceProxyMock: SpaceServiceProxyProtocol, @unchecked Sendable {
|
||||
return joinedParentsChildIDReturnValue
|
||||
}
|
||||
}
|
||||
//MARK: - editableSpaces
|
||||
|
||||
var editableSpacesUnderlyingCallsCount = 0
|
||||
var editableSpacesCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return editableSpacesUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = editableSpacesUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
editableSpacesUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
editableSpacesUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var editableSpacesCalled: Bool {
|
||||
return editableSpacesCallsCount > 0
|
||||
}
|
||||
|
||||
var editableSpacesUnderlyingReturnValue: [SpaceServiceRoomProtocol]!
|
||||
var editableSpacesReturnValue: [SpaceServiceRoomProtocol]! {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return editableSpacesUnderlyingReturnValue
|
||||
} else {
|
||||
var returnValue: [SpaceServiceRoomProtocol]? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = editableSpacesUnderlyingReturnValue
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
editableSpacesUnderlyingReturnValue = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
editableSpacesUnderlyingReturnValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var editableSpacesClosure: (() async -> [SpaceServiceRoomProtocol])?
|
||||
|
||||
func editableSpaces() async -> [SpaceServiceRoomProtocol] {
|
||||
editableSpacesCallsCount += 1
|
||||
if let editableSpacesClosure = editableSpacesClosure {
|
||||
return await editableSpacesClosure()
|
||||
} else {
|
||||
return editableSpacesReturnValue
|
||||
}
|
||||
}
|
||||
//MARK: - addChild
|
||||
|
||||
var addChildToUnderlyingCallsCount = 0
|
||||
|
||||
@@ -111,6 +111,7 @@ extension [SpaceServiceRoomProtocol] {
|
||||
childrenCount: 1,
|
||||
joinedMembersCount: 500,
|
||||
canonicalAlias: "#the-foundation:matrix.org",
|
||||
joinRule: .private,
|
||||
state: .joined)),
|
||||
SpaceServiceRoomMock(.init(id: "space2",
|
||||
name: "The Second Foundation",
|
||||
|
||||
@@ -16,6 +16,7 @@ extension SpaceServiceProxyMock {
|
||||
var topLevelSpaces: [SpaceServiceRoomProtocol] = []
|
||||
var spaceFilters: [SpaceServiceFilter] = []
|
||||
var joinedParentSpaces: [SpaceServiceRoomProtocol] = []
|
||||
var editableSpaces: [SpaceServiceRoomProtocol] = []
|
||||
var spaceRoomLists: [String: SpaceRoomListProxyMock] = [:]
|
||||
var leaveSpaceRooms: [LeaveSpaceRoom] = []
|
||||
}
|
||||
@@ -27,6 +28,7 @@ extension SpaceServiceProxyMock {
|
||||
spaceFilterPublisher = .init(configuration.spaceFilters)
|
||||
|
||||
joinedParentsChildIDReturnValue = .success(configuration.joinedParentSpaces)
|
||||
editableSpacesReturnValue = configuration.editableSpaces
|
||||
spaceRoomListSpaceIDClosure = { spaceID in
|
||||
if let spaceRoomList = configuration.spaceRoomLists[spaceID] {
|
||||
.success(spaceRoomList)
|
||||
|
||||
@@ -31,7 +31,7 @@ struct CreateRoomScreenViewState: BindableState {
|
||||
let isKnockingFeatureEnabled: Bool
|
||||
let canSelectSpace: Bool
|
||||
var aliasLocalPart: String
|
||||
var topLevelSpaces: [SpaceServiceRoomProtocol]
|
||||
var editableSpaces: [SpaceServiceRoomProtocol] = []
|
||||
var bindings: CreateRoomScreenViewStateBindings
|
||||
var avatarMediaInfo: MediaInfo? {
|
||||
didSet {
|
||||
|
||||
@@ -61,11 +61,16 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
|
||||
isKnockingFeatureEnabled: appSettings.knockingEnabled,
|
||||
canSelectSpace: canSelectSpace,
|
||||
aliasLocalPart: roomAliasNameFromRoomDisplayName(roomName: ""),
|
||||
topLevelSpaces: canSelectSpace ? userSession.clientProxy.spaceService.topLevelSpacesPublisher.value : [],
|
||||
bindings: bindings),
|
||||
mediaProvider: userSession.mediaProvider)
|
||||
|
||||
setupBindings()
|
||||
|
||||
if canSelectSpace {
|
||||
Task {
|
||||
state.editableSpaces = await userSession.clientProxy.spaceService.editableSpaces()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
@@ -195,15 +200,6 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
if state.canSelectSpace {
|
||||
userSession
|
||||
.clientProxy
|
||||
.spaceService
|
||||
.topLevelSpacesPublisher
|
||||
.weakAssign(to: \.state.topLevelSpaces, on: self)
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
}
|
||||
|
||||
private func createRoom() async {
|
||||
@@ -277,15 +273,21 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
|
||||
|
||||
var spaceRoomListProxy: SpaceRoomListProxyProtocol?
|
||||
if state.isSpace {
|
||||
switch await userSession.clientProxy.spaceService.spaceRoomList(spaceID: roomProxy.id) {
|
||||
switch await userSession.clientProxy.spaceService.spaceRoomList(spaceID: roomID) {
|
||||
case .success(let value):
|
||||
spaceRoomListProxy = value
|
||||
case .failure:
|
||||
MXLog.error("Failed to get space room list for newly created space with id: \(roomProxy.id)")
|
||||
MXLog.error("Failed to get space room list for newly created space with id: \(roomID)")
|
||||
userIndicatorController.submitIndicator(.init(title: L10n.errorUnknown))
|
||||
}
|
||||
}
|
||||
|
||||
if let selectedSpace = state.bindings.selectedSpace,
|
||||
case .failure = await userSession.clientProxy.spaceService.addChild(roomID, to: selectedSpace.id) {
|
||||
MXLog.error("Failed to add the created room with id: \(roomID) to the space with id: \(selectedSpace.id)")
|
||||
userIndicatorController.submitIndicator(.init(title: L10n.errorUnknown))
|
||||
}
|
||||
|
||||
actionsSubject.send(.createdRoom(roomProxy, spaceRoomListProxy))
|
||||
case .failure:
|
||||
state.bindings.alertInfo = AlertInfo(id: .failedCreatingRoom,
|
||||
|
||||
@@ -236,8 +236,11 @@ struct CreateRoomScreen: View {
|
||||
} else {
|
||||
ListRow(label: .default(title: L10n.screenCreateRoomSpaceSelectionNoSpaceTitle,
|
||||
description: L10n.screenCreateRoomSpaceSelectionNoSpaceDescription,
|
||||
icon: \.home,
|
||||
iconAlignment: .top),
|
||||
icon: CompoundIcon(\.homeSolid, size: .small, relativeTo: .body)
|
||||
.foregroundColor(.compound.iconPrimary)
|
||||
.background(.compound.bgSubtleSecondary)
|
||||
.scaledFrame(size: 32)
|
||||
.clipAvatar(isSpace: true, size: 32)),
|
||||
kind: .navigationLink {
|
||||
context.showSpaceSelectionSheet = true
|
||||
})
|
||||
@@ -446,6 +449,56 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview {
|
||||
viewModel.context.send(viewAction: .updateAliasLocalPart("existing"))
|
||||
return viewModel
|
||||
}()
|
||||
|
||||
static let selectedSpaceViewModel = {
|
||||
AppSettings.resetAllSettings()
|
||||
let mockedSpace = SpaceServiceRoomMock(.init(name: "Awesome Space", isSpace: true, joinRule: .private))
|
||||
let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: "@userid:example.com"))))
|
||||
return CreateRoomScreenViewModel(isSpace: false,
|
||||
spaceSelectionMode: .selected(mockedSpace),
|
||||
shouldShowCancelButton: false,
|
||||
userSession: userSession,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: ServiceLocator.shared.settings)
|
||||
}()
|
||||
|
||||
static let selectedSpaceWithListViewModel = {
|
||||
let clientProxy = ClientProxyMock(.init(userID: "@userid:example.com"))
|
||||
let spaces = [SpaceServiceRoomProtocol].mockJoinedSpaces2
|
||||
clientProxy.spaceService = SpaceServiceProxyMock(.init(editableSpaces: spaces))
|
||||
let userSession = UserSessionMock(.init(clientProxy: clientProxy))
|
||||
|
||||
let viewModel = CreateRoomScreenViewModel(isSpace: false,
|
||||
spaceSelectionMode: .list,
|
||||
shouldShowCancelButton: false,
|
||||
userSession: userSession,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: ServiceLocator.shared.settings)
|
||||
|
||||
viewModel.context.selectedSpace = spaces[0]
|
||||
return viewModel
|
||||
}()
|
||||
|
||||
static let selectedSpaceWithAskToJoinViewModel = {
|
||||
AppSettings.resetAllSettings()
|
||||
let appSettings = AppSettings()
|
||||
appSettings.knockingEnabled = true
|
||||
|
||||
let mockedSpace = SpaceServiceRoomMock(.init(name: "Awesome Space", isSpace: true, joinRule: .private))
|
||||
let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: "@userid:example.com"))))
|
||||
let viewModel = CreateRoomScreenViewModel(isSpace: false,
|
||||
spaceSelectionMode: .selected(mockedSpace),
|
||||
shouldShowCancelButton: false,
|
||||
userSession: userSession,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: appSettings)
|
||||
|
||||
viewModel.context.selectedAccessType = .askToJoinWithSpaceMembers
|
||||
return viewModel
|
||||
}()
|
||||
|
||||
static var previews: some View {
|
||||
NavigationStack {
|
||||
@@ -491,5 +544,20 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview {
|
||||
}
|
||||
.snapshotPreferences(expect: publicRoomExistingAliasViewModel.context.$viewState.map { !$0.aliasErrors.isEmpty })
|
||||
.previewDisplayName("Create Public Room, existing alias")
|
||||
|
||||
NavigationStack {
|
||||
CreateRoomScreen(context: selectedSpaceViewModel.context)
|
||||
}
|
||||
.previewDisplayName("Create Room with already selected Space")
|
||||
|
||||
NavigationStack {
|
||||
CreateRoomScreen(context: selectedSpaceWithListViewModel.context)
|
||||
}
|
||||
.previewDisplayName("Create Room with a selected Space from the list")
|
||||
|
||||
NavigationStack {
|
||||
CreateRoomScreen(context: selectedSpaceWithAskToJoinViewModel.context)
|
||||
}
|
||||
.previewDisplayName("Create Knockable Room with already selected Space")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,12 +26,16 @@ struct CreateRoomSpaceSelectionSheet: View {
|
||||
Section {
|
||||
ListRow(label: .default(title: L10n.screenCreateRoomSpaceSelectionNoSpaceTitle,
|
||||
description: L10n.screenCreateRoomSpaceSelectionNoSpaceDescription,
|
||||
icon: \.home),
|
||||
icon: CompoundIcon(\.homeSolid, size: .small, relativeTo: .body)
|
||||
.foregroundColor(.compound.iconPrimary)
|
||||
.background(.compound.bgSubtleSecondary)
|
||||
.scaledFrame(size: 32)
|
||||
.clipAvatar(isSpace: true, size: 32)),
|
||||
kind: .selection(isSelected: context.selectedSpace == nil) {
|
||||
context.selectedSpace = nil
|
||||
dismiss()
|
||||
})
|
||||
ForEach(context.viewState.topLevelSpaces, id: \.id) { space in
|
||||
ForEach(context.viewState.editableSpaces, id: \.id) { space in
|
||||
ListRow(label: .avatar(title: space.name,
|
||||
description: space.canonicalAlias,
|
||||
icon: RoomAvatarImage(avatar: space.avatar,
|
||||
@@ -66,7 +70,7 @@ struct CreateRoomSpaceSelectionSheet: View {
|
||||
struct CreateRoomSpaceSelectionSheet_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = {
|
||||
let clientProxy = ClientProxyMock(.init(userID: "@userid:example.com"))
|
||||
clientProxy.spaceService = SpaceServiceProxyMock(.init(topLevelSpaces: .mockJoinedSpaces2))
|
||||
clientProxy.spaceService = SpaceServiceProxyMock(.init(editableSpaces: .mockJoinedSpaces2))
|
||||
let userSession = UserSessionMock(.init(clientProxy: clientProxy))
|
||||
|
||||
return CreateRoomScreenViewModel(isSpace: false,
|
||||
@@ -80,5 +84,6 @@ struct CreateRoomSpaceSelectionSheet_Previews: PreviewProvider, TestablePreview
|
||||
|
||||
static var previews: some View {
|
||||
CreateRoomSpaceSelectionSheet(context: viewModel.context)
|
||||
.snapshotPreferences(expect: viewModel.context.$viewState.map { $0.editableSpaces.count > 0 })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,10 @@ class SpaceServiceProxy: SpaceServiceProxyProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func editableSpaces() async -> [SpaceServiceRoomProtocol] {
|
||||
await spaceService.editableSpaces().map(SpaceServiceRoom.init)
|
||||
}
|
||||
|
||||
func addChild(_ childID: String, to spaceID: String) async -> Result<Void, SpaceServiceProxyError> {
|
||||
do {
|
||||
return try await .success(spaceService.addChildToSpace(childId: childID, spaceId: spaceID))
|
||||
@@ -94,7 +98,7 @@ class SpaceServiceProxy: SpaceServiceProxyProtocol {
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func handleSpaceListUpdates(_ updates: [SpaceListUpdate]) {
|
||||
|
||||
@@ -52,6 +52,8 @@ protocol SpaceServiceProxyProtocol {
|
||||
func leaveSpace(spaceID: String) async -> Result<LeaveSpaceHandleProxy, SpaceServiceProxyError>
|
||||
/// Returns all the parent spaces of a child that user has joined.
|
||||
func joinedParents(childID: String) async -> Result<[SpaceServiceRoomProtocol], SpaceServiceProxyError>
|
||||
/// Returns all the parent spaces that can be edited by the user
|
||||
func editableSpaces() async -> [SpaceServiceRoomProtocol]
|
||||
|
||||
/// Adds a room (or space) as a child of another space.
|
||||
func addChild(_ childID: String, to spaceID: String) async -> Result<Void, SpaceServiceProxyError>
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:aa327c6149879d4aa96fa4c5574bac7486fc6abfaa003ae74596c8b88adf6b0b
|
||||
size 156228
|
||||
oid sha256:cd25013fbbabd76733d42f38aeabefbe579800c005892e1201b65d894dba3a71
|
||||
size 165592
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:704b115de7bad6d64ea253ea261a8812e536622dc32280a11e91a3bdc9473340
|
||||
size 186268
|
||||
oid sha256:2a4261ad92874c8d26ff1030dd9dc0b40e4f49c75f535cc4116b56b72a12764f
|
||||
size 200632
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:66f4d91f70ce033d8c6553479ecf7471d53ffdb181986cea4c9032701a595c25
|
||||
size 106657
|
||||
oid sha256:9c848aa3b95b5a7d2bcd21ff7cb84fadd32cfcb7fad9d02a267d7eb20b5cd975
|
||||
size 114307
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0c355007d6ac8f669a701f0ef534e6e381895722d3c495be9e4ef49d20a7de79
|
||||
size 143489
|
||||
oid sha256:b6f0109d908c6f92b2066be1ec631366d6fe170304eee39716c60da61b9a50e8
|
||||
size 134090
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:023c513c47df068c3bc47b4b06f028e630048d7289636dc9b9dac1433abcf442
|
||||
size 139154
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e35b0f0e56364235d60bd8688b7272664ce6c294eb0642d51967d9138289715c
|
||||
size 165021
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2482a63567a5a2ccb6f415e3dca4c05f697affecb9fc05e160c69c17c6020b9e
|
||||
size 89586
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:409ca12c1ad636585be6fef0e1a25cdc17a57a1af00358131ff74995c65e0a26
|
||||
size 120101
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:31efa5cc91a3b0a623056e85e8d5e0c6544a464d959b29ef771e2c9fa2843d7e
|
||||
size 156446
|
||||
oid sha256:783ef584086fb642ea70add67521b336e4bcf48e87d67bbc321bc05cb8801341
|
||||
size 165850
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e638ad86f90e438978096a9fc928f85b6ca0d883f02221978307fe3068e20e35
|
||||
size 188066
|
||||
oid sha256:353482a407588083863c271a0da9fa000e0b2f28db930a1ac355c995377d9cda
|
||||
size 202463
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9b51dfc640af59dd5b3564148d48a1267e9423b1c77fb02edc4607d91d10910b
|
||||
size 108742
|
||||
oid sha256:d6709be30e596cf5ab8a7a36be93ca3710b801e290c0aad8756dd5002fae6cba
|
||||
size 116153
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8b8b277cc422ac3f6fba5b7b555e42c18d2b6ecde65a36eba6c4b63279fb80b5
|
||||
size 145650
|
||||
oid sha256:d478eac4ccdc9e70cb83450b771ec600c1aa944ee246cf2de35a76f34fdba02e
|
||||
size 148446
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b71055f825775861294542ae166fbe7013800fc3672ce4d39ab4419716eedf45
|
||||
size 141129
|
||||
oid sha256:857dac4f0f576d660c86a344a754ae948f1c87344ea02c983ab90f81fc67f2bb
|
||||
size 150715
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d2b85ce0989c5e068e489de22275aeaf723e51fe6b18cb304d16b831e8e8f368
|
||||
size 164236
|
||||
oid sha256:a8ba3dcce7b0b2b1f55a795a0f701882a787b8f2ef8b7cf61aef21fa19b2aff7
|
||||
size 178610
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a5adc15a61b998447a66a4696b59f89413381583c4455be02b1f28594701b986
|
||||
size 89299
|
||||
oid sha256:41b047f803117538ea8bd7cdc15464d825d3e86226ceab49fd7925fa8ca53506
|
||||
size 98304
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5823312ac25afe1b349f8eda8807299d6c30656e961d387c01e544eda40e6c4e
|
||||
size 116112
|
||||
oid sha256:704cc86d9b1ee34f09b9327d935efa3e40654381e4bbbe510167f54ec44afb7f
|
||||
size 127362
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:400c0c0ed48ced1122851b21a6d3e9e48f0985635711fec7e4abe8660994a6b1
|
||||
size 159870
|
||||
oid sha256:2629190bbf8a4101ac0a3cc07ce246d10727c043f6b691c15bdb727ae380f04e
|
||||
size 169245
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:575f32a8b119f2ffbaf6e234b9ea23366850ea245f3f63403a9ba0a2691a2a3b
|
||||
size 195889
|
||||
oid sha256:5f93aab61df326b141ce7ceebde1ff99f0b7fb82610c1c45d7ed7c6a1d636439
|
||||
size 210144
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9002a2ad841596a8e206326fa282b131b750cc556e57a8b8fbf355318106e6ac
|
||||
size 110759
|
||||
oid sha256:b75b9be2f855101eb35fd48c8219b4dcfc4cd3bcc850683297b5ef6aec2f0a6b
|
||||
size 118048
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fab82b9e91cb4b3bad0a3bd13e1b2077a992473889ddb62297d0c902d724e104
|
||||
size 150819
|
||||
oid sha256:cdfac096c01f4cb5ea50c834ecd573d3761a77e20fd71e14ce22368beef01180
|
||||
size 147952
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9db61c6bde46ef08cfd7d1aceb50f379544053024ac4633d1234c863c98c066a
|
||||
size 123222
|
||||
oid sha256:6d19bc6c512bc48a5493b1e3eb8785c33b165daa51a529449c674fed1287ee25
|
||||
size 132860
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e287da07572fd2bd3424894537844637e57629235b372108a8d99ae1b0994b1b
|
||||
size 140788
|
||||
oid sha256:81c651fb4c443c1442fc6b8fccd168e901fb16f994428c44951f57f187a1a38e
|
||||
size 155183
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8b820693bf00b97aaa0a797808106267ce741e495bba57936de8082dc4745bbf
|
||||
size 73369
|
||||
oid sha256:a0ae349c1658b8ff32004e524ff2f16e31c013dae9e6ea9e4a6e3bd0e3756e64
|
||||
size 81447
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ff2841d40e79e09cc472837c7ff350082d6d60894539302056c0d20f645264b1
|
||||
size 90112
|
||||
oid sha256:064a83888029fc47666e0b110fc4260e436499aba4a527c02bfa9493b889a6fa
|
||||
size 100906
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:11421d65287250704b17af8ff783882e61e524f1ad7dd7e332bb308a9fa2b8a0
|
||||
size 148258
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7e45145df3773cfb4f0852576406e6fb9c1ae168539dedaccb000df45681b5af
|
||||
size 168502
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d90ac6bdafa18434682cf09e1434fe73358acea095b388902bbc06a43eb4355d
|
||||
size 95080
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2b46eb0c44ad26ec12798e0e6a55295e11374141766b856f4eca29b67b519578
|
||||
size 115710
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6cd61bb621776260dbb0d91621b0bfaa1aa6d5c19511771fa55b3237130b10ad
|
||||
size 126389
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1406d5b6cff0b0b73f1b012a58ce8bb306de648d1bfff626fbf68ec14cc86301
|
||||
size 145450
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9aff42b3a7cf336f604a40d5f9c5f87aedac8e7656cb9429efb2dbec6ef0738e
|
||||
size 75993
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7830c4f7a205182d1fc62ddedaa79098b869af45366fbf49de08d42bad646a24
|
||||
size 95487
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:dcbee0919af7296c78578076842b77cea64add28137e6d6bf27e1837563c9eab
|
||||
size 156762
|
||||
oid sha256:d4c40aa821fba074dc2c45d68dad1ea5c4133209b940321a8126ae8da4af8b87
|
||||
size 166423
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:dd2792d7127bb9e498a814189fb5c5dfa2b270dd333cea7623ea2b9905ee981f
|
||||
size 174527
|
||||
oid sha256:7ef469565f325404cbbe1ccd024681bf7779a74055b34402666f31df309163c0
|
||||
size 188779
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d9d45b7c4d6aebb9c72558ed440ee099c756eb6b0196a5657d7da85557853d39
|
||||
size 105940
|
||||
oid sha256:a9cb09216e7c5a198c106c2654a34f449e74d536129256fde1ad9a06bb9063c3
|
||||
size 114073
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3be54af6b52da9441294266c11a08bcaf85abfd2005e6ecc795e6e2d1b9b6cf6
|
||||
size 122952
|
||||
oid sha256:f06e5655fe4409ddc5eed23ffec370d3e9bb6e95d5cf60dfcaa8af1a86ef6135
|
||||
size 133808
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:30039d5e15ac969e75c966de760a6e3d28659c29a06555c335f6ba8ab4bd0055
|
||||
size 108672
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:47977fb6d9fb4357cf81cf6724a1a54102ee949a5dd4c4e0fc1ef53160f87328
|
||||
size 111545
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c17b4ed900e67eab1d9ab41496c4dd228c1ddd5aa6ac80bb16d5d99e1c02c884
|
||||
size 65065
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:14ab4d7d5890e6838282885e34d232e520a1ce631eae54d88c09b4cc0fc34700
|
||||
size 67699
|
||||
@@ -15,6 +15,7 @@ import XCTest
|
||||
class CreateRoomScreenViewModelTests: XCTestCase {
|
||||
var viewModel: CreateRoomScreenViewModelProtocol!
|
||||
var clientProxy: ClientProxyMock!
|
||||
var spaceService: SpaceServiceProxyMock!
|
||||
var userSession: UserSessionMock!
|
||||
|
||||
private let usersSubject = CurrentValueSubject<[UserProfileProxy], Never>([])
|
||||
@@ -23,39 +24,31 @@ class CreateRoomScreenViewModelTests: XCTestCase {
|
||||
viewModel.context
|
||||
}
|
||||
|
||||
override func setUpWithError() throws {
|
||||
clientProxy = ClientProxyMock(.init(userIDServerName: "matrix.org", userID: "@a:b.com"))
|
||||
clientProxy.roomForIdentifierClosure = { roomID in .joined(JoinedRoomProxyMock(.init(id: roomID))) }
|
||||
userSession = UserSessionMock(.init(clientProxy: clientProxy))
|
||||
ServiceLocator.shared.settings.knockingEnabled = true
|
||||
let viewModel = CreateRoomScreenViewModel(isSpace: false,
|
||||
spaceSelectionMode: .list,
|
||||
shouldShowCancelButton: false,
|
||||
userSession: userSession,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: ServiceLocator.shared.settings)
|
||||
self.viewModel = viewModel
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
AppSettings.resetAllSettings()
|
||||
viewModel = nil
|
||||
clientProxy = nil
|
||||
spaceService = nil
|
||||
userSession = nil
|
||||
}
|
||||
|
||||
func testDefaultSecurity() {
|
||||
func testDefaultState() {
|
||||
setup()
|
||||
XCTAssertEqual(context.viewState.bindings.selectedAccessType, .private)
|
||||
XCTAssertNil(context.selectedSpace)
|
||||
XCTAssertEqual(context.viewState.availableAccessTypes, [.public, .askToJoin, .private])
|
||||
XCTAssertTrue(context.viewState.canSelectSpace)
|
||||
}
|
||||
|
||||
func testCreateRoomRequirements() {
|
||||
setup()
|
||||
XCTAssertFalse(context.viewState.canCreateRoom)
|
||||
context.send(viewAction: .updateRoomName("A"))
|
||||
XCTAssertTrue(context.viewState.canCreateRoom)
|
||||
}
|
||||
|
||||
func testCreateRoom() async throws {
|
||||
setup()
|
||||
// Given a form with a blank topic.
|
||||
context.send(viewAction: .updateRoomName("A"))
|
||||
context.roomTopic = ""
|
||||
@@ -76,9 +69,11 @@ class CreateRoomScreenViewModelTests: XCTestCase {
|
||||
XCTAssertEqual(clientProxy.createRoomNameTopicAccessTypeIsSpaceUserIDsAvatarURLAliasLocalPartReceivedArguments?.name, "A")
|
||||
XCTAssertNil(clientProxy.createRoomNameTopicAccessTypeIsSpaceUserIDsAvatarURLAliasLocalPartReceivedArguments?.topic,
|
||||
"The topic should be sent as nil when it is empty.")
|
||||
XCTAssertEqual(clientProxy.createRoomNameTopicAccessTypeIsSpaceUserIDsAvatarURLAliasLocalPartReceivedArguments?.accessType, .private)
|
||||
}
|
||||
|
||||
func testCreateSpace() async throws {
|
||||
setup(isSpace: true)
|
||||
clientProxy = ClientProxyMock(.init(userIDServerName: "matrix.org",
|
||||
userID: "@a:b.com",
|
||||
spaceServiceConfiguration: .init(spaceRoomLists: ["1": .init()])))
|
||||
@@ -116,9 +111,11 @@ class CreateRoomScreenViewModelTests: XCTestCase {
|
||||
XCTAssertEqual(clientProxy.createRoomNameTopicAccessTypeIsSpaceUserIDsAvatarURLAliasLocalPartReceivedArguments?.name, "A")
|
||||
XCTAssertNil(clientProxy.createRoomNameTopicAccessTypeIsSpaceUserIDsAvatarURLAliasLocalPartReceivedArguments?.topic,
|
||||
"The topic should be sent as nil when it is empty.")
|
||||
XCTAssertEqual(clientProxy.createRoomNameTopicAccessTypeIsSpaceUserIDsAvatarURLAliasLocalPartReceivedArguments?.accessType, .private)
|
||||
}
|
||||
|
||||
func testCreateKnockingRoom() async {
|
||||
setup()
|
||||
context.send(viewAction: .updateRoomName("A"))
|
||||
context.roomTopic = "B"
|
||||
context.selectedAccessType = .askToJoin
|
||||
@@ -139,6 +136,7 @@ class CreateRoomScreenViewModelTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testCreatePublicRoomFailsForInvalidAlias() async throws {
|
||||
setup()
|
||||
context.send(viewAction: .updateRoomName("A"))
|
||||
context.roomTopic = "B"
|
||||
context.selectedAccessType = .public
|
||||
@@ -161,6 +159,7 @@ class CreateRoomScreenViewModelTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testCreatePublicRoomFailsForExistingAlias() async throws {
|
||||
setup()
|
||||
clientProxy.isAliasAvailableReturnValue = .success(false)
|
||||
context.send(viewAction: .updateRoomName("A"))
|
||||
context.roomTopic = "B"
|
||||
@@ -192,6 +191,7 @@ class CreateRoomScreenViewModelTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testNameAndAddressSync() async {
|
||||
setup()
|
||||
context.selectedAccessType = .private
|
||||
await Task.yield()
|
||||
context.send(viewAction: .updateRoomName("abc"))
|
||||
@@ -221,4 +221,131 @@ class CreateRoomScreenViewModelTests: XCTestCase {
|
||||
XCTAssertEqual(context.viewState.aliasLocalPart, "hello-matrix!")
|
||||
XCTAssertEqual(context.viewState.roomName, "Hello# Matrix!")
|
||||
}
|
||||
|
||||
func testCreateRoomInASelectedSpaceFromTheList() async throws {
|
||||
let spaces = [SpaceServiceRoomProtocol].mockJoinedSpaces2
|
||||
setup()
|
||||
|
||||
// Given a form with a blank topic.
|
||||
context.send(viewAction: .updateRoomName("A"))
|
||||
context.roomTopic = ""
|
||||
context.selectedAccessType = .public
|
||||
XCTAssertTrue(context.viewState.canCreateRoom)
|
||||
XCTAssertNil(context.selectedSpace)
|
||||
XCTAssertEqual(context.viewState.availableAccessTypes, [.public, .askToJoin, .private])
|
||||
XCTAssertTrue(context.viewState.canSelectSpace)
|
||||
|
||||
var deferred = deferFulfillment(context.$viewState) { viewState in
|
||||
viewState.editableSpaces.map(\.id) == spaces.map(\.id)
|
||||
}
|
||||
try await deferred.fulfill()
|
||||
|
||||
context.selectedSpace = spaces[0]
|
||||
deferred = deferFulfillment(context.$viewState) { viewState in
|
||||
viewState.bindings.selectedSpace?.id == spaces[0].id &&
|
||||
viewState.availableAccessTypes == [.spaceMembers, .askToJoinWithSpaceMembers, .private] &&
|
||||
// The value should reset since the original one is not available anymore
|
||||
viewState.bindings.selectedAccessType == .private
|
||||
}
|
||||
try await deferred.fulfill()
|
||||
|
||||
// When creating the room.
|
||||
clientProxy.createRoomNameTopicAccessTypeIsSpaceUserIDsAvatarURLAliasLocalPartReturnValue = .success("1")
|
||||
let expectation = expectation(description: "Wait for the addChild function to be called")
|
||||
spaceService.addChildToClosure = { roomID, spaceID in
|
||||
defer { expectation.fulfill() }
|
||||
XCTAssertEqual(roomID, "1")
|
||||
XCTAssertEqual(spaceID, spaces[0].id)
|
||||
return .success(())
|
||||
}
|
||||
|
||||
let deferredAction = deferFulfillment(viewModel.actions) { action in
|
||||
guard case .createdRoom(let roomProxy, nil) = action, roomProxy.id == "1" else { return false }
|
||||
return true
|
||||
}
|
||||
context.send(viewAction: .createRoom)
|
||||
|
||||
await fulfillment(of: [expectation])
|
||||
try await deferredAction.fulfill()
|
||||
|
||||
// Then the room should be created and a topic should not be set.
|
||||
XCTAssertTrue(clientProxy.createRoomNameTopicAccessTypeIsSpaceUserIDsAvatarURLAliasLocalPartCalled)
|
||||
XCTAssertEqual(clientProxy.createRoomNameTopicAccessTypeIsSpaceUserIDsAvatarURLAliasLocalPartReceivedArguments?.name, "A")
|
||||
XCTAssertEqual(clientProxy.createRoomNameTopicAccessTypeIsSpaceUserIDsAvatarURLAliasLocalPartReceivedArguments?.accessType, .private)
|
||||
XCTAssertNil(clientProxy.createRoomNameTopicAccessTypeIsSpaceUserIDsAvatarURLAliasLocalPartReceivedArguments?.topic,
|
||||
"The topic should be sent as nil when it is empty.")
|
||||
}
|
||||
|
||||
func testCreateRoomInAnAlreadySelectedSpace() async throws {
|
||||
let space = SpaceServiceRoomMock(.init(isSpace: true, joinRule: .private))
|
||||
setup(spacesSelectionMode: .selected(space))
|
||||
|
||||
// Given a form with a blank topic.
|
||||
context.send(viewAction: .updateRoomName("A"))
|
||||
context.roomTopic = ""
|
||||
context.selectedAccessType = .spaceMembers
|
||||
XCTAssertTrue(context.viewState.canCreateRoom)
|
||||
XCTAssertEqual(context.selectedSpace?.id, space.id)
|
||||
XCTAssertEqual(context.viewState.availableAccessTypes, [.spaceMembers, .askToJoinWithSpaceMembers, .private])
|
||||
XCTAssertFalse(context.viewState.canSelectSpace)
|
||||
|
||||
// When creating the room.
|
||||
clientProxy.createRoomNameTopicAccessTypeIsSpaceUserIDsAvatarURLAliasLocalPartReturnValue = .success("1")
|
||||
let expectation = expectation(description: "Wait for the addChild function to be called")
|
||||
spaceService.addChildToClosure = { roomID, spaceID in
|
||||
defer { expectation.fulfill() }
|
||||
XCTAssertEqual(roomID, "1")
|
||||
XCTAssertEqual(spaceID, space.id)
|
||||
return .success(())
|
||||
}
|
||||
|
||||
let deferredAction = deferFulfillment(viewModel.actions) { action in
|
||||
guard case .createdRoom(let roomProxy, nil) = action, roomProxy.id == "1" else { return false }
|
||||
return true
|
||||
}
|
||||
context.send(viewAction: .createRoom)
|
||||
|
||||
await fulfillment(of: [expectation])
|
||||
try await deferredAction.fulfill()
|
||||
|
||||
// Then the room should be created and a topic should not be set.
|
||||
XCTAssertTrue(clientProxy.createRoomNameTopicAccessTypeIsSpaceUserIDsAvatarURLAliasLocalPartCalled)
|
||||
XCTAssertEqual(clientProxy.createRoomNameTopicAccessTypeIsSpaceUserIDsAvatarURLAliasLocalPartReceivedArguments?.name, "A")
|
||||
XCTAssertEqual(clientProxy.createRoomNameTopicAccessTypeIsSpaceUserIDsAvatarURLAliasLocalPartReceivedArguments?.accessType, .spaceMembers(spaceID: space.id))
|
||||
XCTAssertNil(clientProxy.createRoomNameTopicAccessTypeIsSpaceUserIDsAvatarURLAliasLocalPartReceivedArguments?.topic,
|
||||
"The topic should be sent as nil when it is empty.")
|
||||
}
|
||||
|
||||
func testCreateRoomInAnPublicSpaceAvailableTypes() async throws {
|
||||
let space = SpaceServiceRoomMock(.init(isSpace: true, joinRule: .public))
|
||||
setup(spacesSelectionMode: .selected(space))
|
||||
|
||||
// Given a form with a blank topic.
|
||||
context.send(viewAction: .updateRoomName("A"))
|
||||
context.roomTopic = ""
|
||||
context.selectedAccessType = .spaceMembers
|
||||
XCTAssertTrue(context.viewState.canCreateRoom)
|
||||
XCTAssertEqual(context.selectedSpace?.id, space.id)
|
||||
XCTAssertEqual(context.viewState.availableAccessTypes, [.public, .askToJoin, .private])
|
||||
XCTAssertFalse(context.viewState.canSelectSpace)
|
||||
}
|
||||
|
||||
private func setup(isSpace: Bool = false, spacesSelectionMode: CreateRoomScreenSpaceSelectionMode = .list) {
|
||||
spaceService = SpaceServiceProxyMock(.init(editableSpaces: .mockJoinedSpaces2,
|
||||
spaceRoomLists: ["1": .init()]))
|
||||
clientProxy = ClientProxyMock(.init(userIDServerName: "matrix.org",
|
||||
userID: "@a:b.com"))
|
||||
clientProxy.spaceService = spaceService
|
||||
clientProxy.roomForIdentifierClosure = { roomID in .joined(JoinedRoomProxyMock(.init(id: roomID))) }
|
||||
userSession = UserSessionMock(.init(clientProxy: clientProxy))
|
||||
ServiceLocator.shared.settings.knockingEnabled = true
|
||||
let viewModel = CreateRoomScreenViewModel(isSpace: isSpace,
|
||||
spaceSelectionMode: spacesSelectionMode,
|
||||
shouldShowCancelButton: false,
|
||||
userSession: userSession,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: ServiceLocator.shared.settings)
|
||||
self.viewModel = viewModel
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user