mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 21:33:26 +00:00
handle the case where a non parent joined space is already available in the existing restricted join rule
This commit is contained in:
@@ -16568,6 +16568,76 @@ class SpaceServiceProxyMock: SpaceServiceProxyProtocol, @unchecked Sendable {
|
||||
return spaceRoomListSpaceIDReturnValue
|
||||
}
|
||||
}
|
||||
//MARK: - spaceForIdentifier
|
||||
|
||||
var spaceForIdentifierSpaceIDUnderlyingCallsCount = 0
|
||||
var spaceForIdentifierSpaceIDCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return spaceForIdentifierSpaceIDUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = spaceForIdentifierSpaceIDUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
spaceForIdentifierSpaceIDUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
spaceForIdentifierSpaceIDUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var spaceForIdentifierSpaceIDCalled: Bool {
|
||||
return spaceForIdentifierSpaceIDCallsCount > 0
|
||||
}
|
||||
var spaceForIdentifierSpaceIDReceivedSpaceID: String?
|
||||
var spaceForIdentifierSpaceIDReceivedInvocations: [String] = []
|
||||
|
||||
var spaceForIdentifierSpaceIDUnderlyingReturnValue: Result<SpaceRoomProxyProtocol?, SpaceServiceProxyError>!
|
||||
var spaceForIdentifierSpaceIDReturnValue: Result<SpaceRoomProxyProtocol?, SpaceServiceProxyError>! {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return spaceForIdentifierSpaceIDUnderlyingReturnValue
|
||||
} else {
|
||||
var returnValue: Result<SpaceRoomProxyProtocol?, SpaceServiceProxyError>? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = spaceForIdentifierSpaceIDUnderlyingReturnValue
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
spaceForIdentifierSpaceIDUnderlyingReturnValue = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
spaceForIdentifierSpaceIDUnderlyingReturnValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var spaceForIdentifierSpaceIDClosure: ((String) async -> Result<SpaceRoomProxyProtocol?, SpaceServiceProxyError>)?
|
||||
|
||||
func spaceForIdentifier(spaceID: String) async -> Result<SpaceRoomProxyProtocol?, SpaceServiceProxyError> {
|
||||
spaceForIdentifierSpaceIDCallsCount += 1
|
||||
spaceForIdentifierSpaceIDReceivedSpaceID = spaceID
|
||||
DispatchQueue.main.async {
|
||||
self.spaceForIdentifierSpaceIDReceivedInvocations.append(spaceID)
|
||||
}
|
||||
if let spaceForIdentifierSpaceIDClosure = spaceForIdentifierSpaceIDClosure {
|
||||
return await spaceForIdentifierSpaceIDClosure(spaceID)
|
||||
} else {
|
||||
return spaceForIdentifierSpaceIDReturnValue
|
||||
}
|
||||
}
|
||||
//MARK: - leaveSpace
|
||||
|
||||
var leaveSpaceSpaceIDUnderlyingCallsCount = 0
|
||||
|
||||
@@ -23265,6 +23265,81 @@ open class SpaceServiceSDKMock: MatrixRustSDK.SpaceService, @unchecked Sendable
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - getSpaceRoom
|
||||
|
||||
open var getSpaceRoomRoomIdThrowableError: Error?
|
||||
var getSpaceRoomRoomIdUnderlyingCallsCount = 0
|
||||
open var getSpaceRoomRoomIdCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return getSpaceRoomRoomIdUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = getSpaceRoomRoomIdUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
getSpaceRoomRoomIdUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
getSpaceRoomRoomIdUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var getSpaceRoomRoomIdCalled: Bool {
|
||||
return getSpaceRoomRoomIdCallsCount > 0
|
||||
}
|
||||
open var getSpaceRoomRoomIdReceivedRoomId: String?
|
||||
open var getSpaceRoomRoomIdReceivedInvocations: [String] = []
|
||||
|
||||
var getSpaceRoomRoomIdUnderlyingReturnValue: SpaceRoom?
|
||||
open var getSpaceRoomRoomIdReturnValue: SpaceRoom? {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return getSpaceRoomRoomIdUnderlyingReturnValue
|
||||
} else {
|
||||
var returnValue: SpaceRoom?? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = getSpaceRoomRoomIdUnderlyingReturnValue
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
getSpaceRoomRoomIdUnderlyingReturnValue = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
getSpaceRoomRoomIdUnderlyingReturnValue = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
open var getSpaceRoomRoomIdClosure: ((String) async throws -> SpaceRoom?)?
|
||||
|
||||
open override func getSpaceRoom(roomId: String) async throws -> SpaceRoom? {
|
||||
if let error = getSpaceRoomRoomIdThrowableError {
|
||||
throw error
|
||||
}
|
||||
getSpaceRoomRoomIdCallsCount += 1
|
||||
getSpaceRoomRoomIdReceivedRoomId = roomId
|
||||
DispatchQueue.main.async {
|
||||
self.getSpaceRoomRoomIdReceivedInvocations.append(roomId)
|
||||
}
|
||||
if let getSpaceRoomRoomIdClosure = getSpaceRoomRoomIdClosure {
|
||||
return try await getSpaceRoomRoomIdClosure(roomId)
|
||||
} else {
|
||||
return getSpaceRoomRoomIdReturnValue
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - joinedParentsOfChild
|
||||
|
||||
open var joinedParentsOfChildChildIdThrowableError: Error?
|
||||
|
||||
@@ -34,6 +34,9 @@ extension SpaceServiceProxyMock {
|
||||
.success(LeaveSpaceHandleProxy(spaceID: spaceID,
|
||||
leaveHandle: LeaveSpaceHandleSDKMock(.init(rooms: configuration.leaveSpaceRooms))))
|
||||
}
|
||||
spaceForIdentifierSpaceIDClosure = { spaceID in
|
||||
.success(configuration.joinedSpaces.first { $0.id == spaceID })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ enum ManageAuthorizedSpacesScreenViewAction {
|
||||
}
|
||||
|
||||
struct AuthorizedSpacesSelection {
|
||||
let joinedParentSpaces: [SpaceRoomProxyProtocol]
|
||||
let joinedSpaces: [SpaceRoomProxyProtocol]
|
||||
let unknownSpacesIDs: [String]
|
||||
let initialSelectedIDs: Set<String>
|
||||
let selectedIDs: PassthroughSubject<Set<String>, Never> = .init()
|
||||
|
||||
+5
-5
@@ -15,8 +15,8 @@ struct ManageAuthorizedSpacesScreen: View {
|
||||
Form {
|
||||
header
|
||||
|
||||
if !context.viewState.authorizedSpacesSelection.joinedParentSpaces.isEmpty {
|
||||
joinedParentsSection
|
||||
if !context.viewState.authorizedSpacesSelection.joinedSpaces.isEmpty {
|
||||
joinedSpacesSection
|
||||
}
|
||||
|
||||
if !context.viewState.authorizedSpacesSelection.unknownSpacesIDs.isEmpty {
|
||||
@@ -46,9 +46,9 @@ struct ManageAuthorizedSpacesScreen: View {
|
||||
}
|
||||
}
|
||||
|
||||
private var joinedParentsSection: some View {
|
||||
private var joinedSpacesSection: some View {
|
||||
Section {
|
||||
ForEach(context.viewState.authorizedSpacesSelection.joinedParentSpaces, id: \.id) { space in
|
||||
ForEach(context.viewState.authorizedSpacesSelection.joinedSpaces, id: \.id) { space in
|
||||
ListRow(label: .avatar(title: space.name,
|
||||
description: space.canonicalAlias,
|
||||
icon: avatar(space: space)),
|
||||
@@ -102,7 +102,7 @@ struct ManageAuthorizedSpacesScreen: View {
|
||||
// MARK: - Previews
|
||||
|
||||
struct ManageAuthorizedSpacesScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = ManageAuthorizedSpacesScreenViewModel(authorizedSpacesSelection: .init(joinedParentSpaces: .mockJoinedSpaces2,
|
||||
static let viewModel = ManageAuthorizedSpacesScreenViewModel(authorizedSpacesSelection: .init(joinedSpaces: .mockJoinedSpaces2,
|
||||
unknownSpacesIDs: ["!unknown-space-id-1",
|
||||
"!unknown-space-id-2",
|
||||
"!unknown-space-id-3"],
|
||||
|
||||
+10
-9
@@ -38,11 +38,12 @@ struct SecurityAndPrivacyScreenViewState: BindableState {
|
||||
var canEditJoinRule = false
|
||||
var canEnableEncryption = false
|
||||
var canEditHistoryVisibility = false
|
||||
var joinedParentSpaces: [SpaceRoomProxyProtocol] = []
|
||||
/// The union of joined parent spaces and the joined spaces in the current access type
|
||||
var selectableJoinedSpaces: [SpaceRoomProxyProtocol] = []
|
||||
|
||||
/// The count of the intersection between the set of joined parent spaces and the set of spaces in the current access type
|
||||
var selectableSpacesCount: Int {
|
||||
Set(joinedParentSpaces.map(\.id) + currentSettings.accessType.spaceIDs).count
|
||||
Set(selectableJoinedSpaces.map(\.id) + currentSettings.accessType.spaceIDs).count
|
||||
}
|
||||
|
||||
private var hasChanges: Bool {
|
||||
@@ -85,8 +86,8 @@ struct SecurityAndPrivacyScreenViewState: BindableState {
|
||||
var spaceMembersDescription: String {
|
||||
if isSpaceMembersOptionSelectable {
|
||||
switch spaceSelection {
|
||||
case .singleJoined(let joinedParentSpace):
|
||||
L10n.screenSecurityAndPrivacyRoomAccessSpaceMembersOptionSingleParentDescription(joinedParentSpace.name)
|
||||
case .singleJoined(let joinedSpace):
|
||||
L10n.screenSecurityAndPrivacyRoomAccessSpaceMembersOptionSingleParentDescription(joinedSpace.name)
|
||||
case .singleUnknown(let id):
|
||||
L10n.screenSecurityAndPrivacyRoomAccessSpaceMembersOptionSingleParentDescription(id)
|
||||
case .multiple, .empty:
|
||||
@@ -100,8 +101,8 @@ struct SecurityAndPrivacyScreenViewState: BindableState {
|
||||
var askToJoinWithSpaceMembersDescription: String {
|
||||
if isAskToJoinWithSpaceMembersOptionSelectable {
|
||||
switch spaceSelection {
|
||||
case .singleJoined(let joinedParentSpace):
|
||||
L10n.screenSecurityAndPrivacyAskToJoinSingleSpaceMembersOptionDescription(joinedParentSpace.name)
|
||||
case .singleJoined(let joinedSpace):
|
||||
L10n.screenSecurityAndPrivacyAskToJoinSingleSpaceMembersOptionDescription(joinedSpace.name)
|
||||
case .singleUnknown(let id):
|
||||
L10n.screenSecurityAndPrivacyAskToJoinSingleSpaceMembersOptionDescription(id)
|
||||
case .multiple, .empty:
|
||||
@@ -140,17 +141,17 @@ struct SecurityAndPrivacyScreenViewState: BindableState {
|
||||
.empty
|
||||
} else if selectableSpacesCount > 1 {
|
||||
.multiple
|
||||
} else if let joinedParent = joinedParentSpaces.first {
|
||||
} else if let joinedSpace = selectableJoinedSpaces.first {
|
||||
if currentSettings.accessType.isSpaceMembers || currentSettings.accessType.isAskToJoinWithSpaceMembers {
|
||||
if currentSettings.accessType.spaceIDs.isEmpty {
|
||||
// Edge case where the access type is already space members, but it does not contain any id
|
||||
// So if the user wants to add their own parent they need to do it from the selection menu
|
||||
.multiple
|
||||
} else {
|
||||
.singleJoined(joinedParent)
|
||||
.singleJoined(joinedSpace)
|
||||
}
|
||||
} else {
|
||||
.singleJoined(joinedParent)
|
||||
.singleJoined(joinedSpace)
|
||||
}
|
||||
} else if let unknownSpaceID = currentSettings.accessType.spaceIDs.first {
|
||||
// The space is not joined by the user but is currently selected
|
||||
|
||||
+32
-13
@@ -47,12 +47,7 @@ class SecurityAndPrivacyScreenViewModel: SecurityAndPrivacyScreenViewModelType,
|
||||
setupRoomDirectoryVisibility()
|
||||
setupSubscriptions()
|
||||
Task {
|
||||
switch await clientProxy.spaceService.joinedParents(childID: roomProxy.id) {
|
||||
case .success(let joinedParentSpaces):
|
||||
state.joinedParentSpaces = joinedParentSpaces
|
||||
case .failure:
|
||||
break
|
||||
}
|
||||
await setupSelectableJoinedSpaces()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,6 +228,8 @@ class SecurityAndPrivacyScreenViewModel: SecurityAndPrivacyScreenViewModelType,
|
||||
|
||||
if shouldDismiss, !hasFailures {
|
||||
actionsSubject.send(.dismiss)
|
||||
} else if !shouldDismiss {
|
||||
await setupSelectableJoinedSpaces()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,8 +240,8 @@ class SecurityAndPrivacyScreenViewModel: SecurityAndPrivacyScreenViewModelType,
|
||||
}
|
||||
|
||||
switch state.spaceSelection {
|
||||
case .singleJoined(let joinedParent):
|
||||
state.bindings.desiredSettings.accessType = .spaceMembers(spaceIDs: [joinedParent.id])
|
||||
case .singleJoined(let joinedSpace):
|
||||
state.bindings.desiredSettings.accessType = .spaceMembers(spaceIDs: [joinedSpace.id])
|
||||
case .singleUnknown(let id):
|
||||
state.bindings.desiredSettings.accessType = .spaceMembers(spaceIDs: [id])
|
||||
case .empty:
|
||||
@@ -261,8 +258,8 @@ class SecurityAndPrivacyScreenViewModel: SecurityAndPrivacyScreenViewModelType,
|
||||
}
|
||||
|
||||
switch state.spaceSelection {
|
||||
case .singleJoined(let joinedParent):
|
||||
state.bindings.desiredSettings.accessType = .askToJoinWithSpaceMembers(spaceIDs: [joinedParent.id])
|
||||
case .singleJoined(let joinedSpace):
|
||||
state.bindings.desiredSettings.accessType = .askToJoinWithSpaceMembers(spaceIDs: [joinedSpace.id])
|
||||
case .singleUnknown(let id):
|
||||
state.bindings.desiredSettings.accessType = .askToJoinWithSpaceMembers(spaceIDs: [id])
|
||||
case .empty:
|
||||
@@ -273,12 +270,12 @@ class SecurityAndPrivacyScreenViewModel: SecurityAndPrivacyScreenViewModelType,
|
||||
}
|
||||
|
||||
private func displayManageAuthorizedSpacesScreen(isAskToJoin: Bool) {
|
||||
let joinedParentSpaces = state.joinedParentSpaces
|
||||
let joinedSpaces = state.selectableJoinedSpaces
|
||||
let unknownSpaceIDs = state.currentSettings.accessType.spaceIDs.filter { id in
|
||||
!joinedParentSpaces.contains { $0.id == id }
|
||||
!joinedSpaces.contains { $0.id == id }
|
||||
}
|
||||
let selectedIDs = Set(state.bindings.desiredSettings.accessType.spaceIDs)
|
||||
let authorizedSpacesSelection = AuthorizedSpacesSelection(joinedParentSpaces: joinedParentSpaces,
|
||||
let authorizedSpacesSelection = AuthorizedSpacesSelection(joinedSpaces: joinedSpaces,
|
||||
unknownSpacesIDs: unknownSpaceIDs,
|
||||
initialSelectedIDs: selectedIDs)
|
||||
authorizedSpacesSelection.selectedIDs
|
||||
@@ -291,6 +288,28 @@ class SecurityAndPrivacyScreenViewModel: SecurityAndPrivacyScreenViewModelType,
|
||||
actionsSubject.send(.displayManageAuthorizedSpacesScreen(authorizedSpacesSelection))
|
||||
}
|
||||
|
||||
private func setupSelectableJoinedSpaces() async {
|
||||
var joinedParentSpaces: [SpaceRoomProxyProtocol] = []
|
||||
switch await clientProxy.spaceService.joinedParents(childID: roomProxy.id) {
|
||||
case .success(let value):
|
||||
joinedParentSpaces = value
|
||||
case .failure:
|
||||
break
|
||||
}
|
||||
|
||||
var nonParentJoinedSpaces: [SpaceRoomProxyProtocol] = []
|
||||
for spaceID in state.currentSettings.accessType.spaceIDs where !joinedParentSpaces.contains(where: { $0.id == spaceID }) {
|
||||
if case let .success(.some(space)) = await clientProxy.spaceService.spaceForIdentifier(spaceID: spaceID) {
|
||||
nonParentJoinedSpaces.append(space)
|
||||
}
|
||||
}
|
||||
|
||||
// By default we only want to allow selection among joined parents but
|
||||
// if there is a non parent joined space already set in the access type
|
||||
// we also include it in the known spaces selection list.
|
||||
state.selectableJoinedSpaces = joinedParentSpaces + nonParentJoinedSpaces
|
||||
}
|
||||
|
||||
private static let loadingIndicatorIdentifier = "\(EditRoomAddressScreenViewModel.self)-Loading"
|
||||
|
||||
private func showLoadingIndicator() {
|
||||
|
||||
@@ -40,6 +40,15 @@ class SpaceServiceProxy: SpaceServiceProxyProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func spaceForIdentifier(spaceID: String) async -> Result<SpaceRoomProxyProtocol?, SpaceServiceProxyError> {
|
||||
do {
|
||||
return try await .success(spaceService.getSpaceRoom(roomId: spaceID).map(SpaceRoomProxy.init))
|
||||
} catch {
|
||||
MXLog.error("Failed getting space room for \(spaceID): \(error)")
|
||||
return .failure(.sdkError(error))
|
||||
}
|
||||
}
|
||||
|
||||
func leaveSpace(spaceID: String) async -> Result<LeaveSpaceHandleProxy, SpaceServiceProxyError> {
|
||||
do {
|
||||
return try await .success(.init(spaceID: spaceID, leaveHandle: spaceService.leaveSpace(spaceId: spaceID)))
|
||||
|
||||
@@ -18,6 +18,8 @@ protocol SpaceServiceProxyProtocol {
|
||||
var joinedSpacesPublisher: CurrentValuePublisher<[SpaceRoomProxyProtocol], Never> { get }
|
||||
|
||||
func spaceRoomList(spaceID: String) async -> Result<SpaceRoomListProxyProtocol, SpaceServiceProxyError>
|
||||
/// Returns a joined space given its identifier
|
||||
func spaceForIdentifier(spaceID: String) async -> Result<SpaceRoomProxyProtocol?, SpaceServiceProxyError>
|
||||
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<[SpaceRoomProxyProtocol], SpaceServiceProxyError>
|
||||
|
||||
Reference in New Issue
Block a user