mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 21:33:26 +00:00
implemented the logic that displays the space selection CTA
This commit is contained in:
@@ -193,6 +193,7 @@ class StartChatFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
private func presentCreateRoomScreen(isSpace: Bool, isRoot: Bool) {
|
||||
let createParameters = CreateRoomScreenCoordinatorParameters(isSpace: isSpace,
|
||||
spaceSelectionMode: !isSpace && flowParameters.appSettings.createSpaceEnabled ? .list : nil,
|
||||
shouldShowCancelButton: isRoot,
|
||||
userSession: flowParameters.userSession,
|
||||
userIndicatorController: flowParameters.userIndicatorController,
|
||||
|
||||
@@ -156,13 +156,15 @@ enum RoomAvatarSizeOnScreen {
|
||||
case spaceAddRooms
|
||||
case spaceAddRoomsSelected
|
||||
case completionSuggestions
|
||||
case createRoomSelectSpace
|
||||
|
||||
var value: CGFloat {
|
||||
switch self {
|
||||
case .chats, .spaces, .spaceSettings:
|
||||
return 52
|
||||
case .timeline, .leaveSpace, .roomDirectorySearch,
|
||||
.completionSuggestions, .authorizedSpaces, .spaceFilters:
|
||||
.completionSuggestions, .authorizedSpaces,.createRoomSelectSpace,
|
||||
.spaceFilters:
|
||||
return 32
|
||||
case .notificationSettings:
|
||||
return 30
|
||||
|
||||
@@ -32,6 +32,7 @@ enum TestablePreviewsDictionary {
|
||||
"CompletionSuggestion_Previews" : CompletionSuggestion_Previews.self,
|
||||
"ComposerToolbar_Previews" : ComposerToolbar_Previews.self,
|
||||
"CopyTextButton_Previews" : CopyTextButton_Previews.self,
|
||||
"CreateRoomSpaceSelectionSheet_Previews" : CreateRoomSpaceSelectionSheet_Previews.self,
|
||||
"CreateRoom_Previews" : CreateRoom_Previews.self,
|
||||
"DeactivateAccountScreen_Previews" : DeactivateAccountScreen_Previews.self,
|
||||
"DeclineAndBlockScreen_Previews" : DeclineAndBlockScreen_Previews.self,
|
||||
|
||||
@@ -11,6 +11,7 @@ import SwiftUI
|
||||
|
||||
struct CreateRoomScreenCoordinatorParameters {
|
||||
let isSpace: Bool
|
||||
let spaceSelectionMode: CreateRoomScreenSpaceSelectionMode?
|
||||
let shouldShowCancelButton: Bool
|
||||
let userSession: UserSessionProtocol
|
||||
let userIndicatorController: UserIndicatorControllerProtocol
|
||||
@@ -35,6 +36,7 @@ final class CreateRoomScreenCoordinator: CoordinatorProtocol {
|
||||
|
||||
init(parameters: CreateRoomScreenCoordinatorParameters) {
|
||||
viewModel = CreateRoomScreenViewModel(isSpace: parameters.isSpace,
|
||||
spaceSelectionMode: parameters.spaceSelectionMode,
|
||||
shouldShowCancelButton: parameters.shouldShowCancelButton,
|
||||
userSession: parameters.userSession,
|
||||
analytics: parameters.analytics,
|
||||
|
||||
@@ -31,6 +31,7 @@ struct CreateRoomScreenViewState: BindableState {
|
||||
let isKnockingFeatureEnabled: Bool
|
||||
let canSelectSpace: Bool
|
||||
var aliasLocalPart: String
|
||||
var topLevelSpaces: [SpaceServiceRoomProtocol]
|
||||
var bindings: CreateRoomScreenViewStateBindings
|
||||
var avatarMediaInfo: MediaInfo? {
|
||||
didSet {
|
||||
@@ -59,14 +60,12 @@ struct CreateRoomScreenViewState: BindableState {
|
||||
nil
|
||||
}
|
||||
}
|
||||
|
||||
var selectedSpace: SpaceServiceRoomProtocol?
|
||||
|
||||
|
||||
var availableAccessTypes: [CreateRoomScreenAccessType] {
|
||||
var availableAccessTypes: [CreateRoomScreenAccessType] = []
|
||||
if isSpace {
|
||||
availableAccessTypes = [.public]
|
||||
} else if let selectedSpace, selectedSpace.joinRule != .public {
|
||||
} else if let selectedSpace = bindings.selectedSpace, selectedSpace.joinRule != .public {
|
||||
availableAccessTypes = [.spaceMembers]
|
||||
if isKnockingFeatureEnabled {
|
||||
availableAccessTypes.append(.askToJoinWithSpaceMembers)
|
||||
@@ -86,9 +85,9 @@ struct CreateRoomScreenViewState: BindableState {
|
||||
case .public:
|
||||
return .public
|
||||
case .spaceMembers:
|
||||
return .spaceMembers(spaceID: selectedSpace?.id ?? "")
|
||||
return .spaceMembers(spaceID: bindings.selectedSpace?.id ?? "")
|
||||
case .askToJoinWithSpaceMembers:
|
||||
return .askToJoinWithSpaceMembers(spaceID: selectedSpace?.id ?? "")
|
||||
return .askToJoinWithSpaceMembers(spaceID: bindings.selectedSpace?.id ?? "")
|
||||
case .askToJoin:
|
||||
return .askToJoin
|
||||
case .private:
|
||||
@@ -100,7 +99,10 @@ struct CreateRoomScreenViewState: BindableState {
|
||||
struct CreateRoomScreenViewStateBindings {
|
||||
var roomTopic: String
|
||||
var selectedAccessType: CreateRoomScreenAccessType
|
||||
var selectedSpace: SpaceServiceRoomProtocol?
|
||||
|
||||
var showAttachmentConfirmationDialog = false
|
||||
var showSpaceSelectionSheet = false
|
||||
|
||||
/// Information describing the currently displayed alert.
|
||||
var alertInfo: AlertInfo<CreateRoomScreenErrorType>?
|
||||
@@ -139,3 +141,8 @@ enum CreateRoomScreenAccessType {
|
||||
case askToJoin
|
||||
case `private`
|
||||
}
|
||||
|
||||
enum CreateRoomScreenSpaceSelectionMode {
|
||||
case list
|
||||
case selected(SpaceServiceRoomProtocol)
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
|
||||
private let mediaUploadingPreprocessor: MediaUploadingPreprocessor
|
||||
private let analytics: AnalyticsService
|
||||
private let userIndicatorController: UserIndicatorControllerProtocol
|
||||
|
||||
private var syncNameAndAlias = true
|
||||
@CancellableTask private var checkAliasAvailabilityTask: Task<Void, Never>?
|
||||
|
||||
@@ -27,6 +28,7 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
|
||||
}
|
||||
|
||||
init(isSpace: Bool,
|
||||
spaceSelectionMode: CreateRoomScreenSpaceSelectionMode?,
|
||||
shouldShowCancelButton: Bool,
|
||||
userSession: UserSessionProtocol,
|
||||
analytics: AnalyticsService,
|
||||
@@ -37,16 +39,29 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
|
||||
self.analytics = analytics
|
||||
self.userIndicatorController = userIndicatorController
|
||||
|
||||
var selectedSpace: SpaceServiceRoomProtocol?
|
||||
var canSelectSpace = false
|
||||
switch spaceSelectionMode {
|
||||
case .list:
|
||||
canSelectSpace = true
|
||||
case .selected(let value):
|
||||
selectedSpace = value
|
||||
case .none:
|
||||
break
|
||||
}
|
||||
|
||||
let bindings = CreateRoomScreenViewStateBindings(roomTopic: "",
|
||||
selectedAccessType: .private)
|
||||
selectedAccessType: .private,
|
||||
selectedSpace: selectedSpace)
|
||||
|
||||
super.init(initialViewState: CreateRoomScreenViewState(isSpace: isSpace,
|
||||
shouldShowCancelButton: shouldShowCancelButton,
|
||||
roomName: "",
|
||||
serverName: userSession.clientProxy.userIDServerName ?? "",
|
||||
isKnockingFeatureEnabled: appSettings.knockingEnabled,
|
||||
canSelectSpace: isSpace ? false : appSettings.createSpaceEnabled,
|
||||
canSelectSpace: canSelectSpace,
|
||||
aliasLocalPart: roomAliasNameFromRoomDisplayName(roomName: ""),
|
||||
topLevelSpaces: canSelectSpace ? userSession.clientProxy.spaceService.topLevelSpacesPublisher.value : [],
|
||||
bindings: bindings),
|
||||
mediaProvider: userSession.mediaProvider)
|
||||
|
||||
@@ -180,6 +195,15 @@ 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 {
|
||||
|
||||
@@ -55,6 +55,9 @@ struct CreateRoomScreen: View {
|
||||
.toolbar { toolbar }
|
||||
.alert(item: $context.alertInfo)
|
||||
.shouldScrollOnKeyboardDidShow(focus == .alias, to: Focus.alias)
|
||||
.sheet(isPresented: $context.showSpaceSelectionSheet) {
|
||||
CreateRoomSpaceSelectionSheet(context: context)
|
||||
}
|
||||
}
|
||||
|
||||
private var nameTextFieldShape: AnyShape {
|
||||
@@ -184,7 +187,7 @@ struct CreateRoomScreen: View {
|
||||
Section {
|
||||
ForEach(context.viewState.availableAccessTypes, id: \.self) { accessType in
|
||||
CreateRoomAccessRow(access: accessType,
|
||||
spaceName: context.viewState.selectedSpace?.name ?? "",
|
||||
spaceName: context.selectedSpace?.name ?? "",
|
||||
isSelected: context.selectedAccessType == accessType) {
|
||||
context.selectedAccessType = accessType
|
||||
}
|
||||
@@ -221,7 +224,21 @@ struct CreateRoomScreen: View {
|
||||
|
||||
private var selectSpaceSection: some View {
|
||||
Section {
|
||||
EmptyView()
|
||||
if let selectedSpace = context.selectedSpace {
|
||||
ListRow(label: .avatar(title: selectedSpace.name,
|
||||
description: selectedSpace.canonicalAlias,
|
||||
icon: RoomAvatarImage(avatar: selectedSpace.avatar,
|
||||
avatarSize: .room(on: .createRoomSelectSpace),
|
||||
mediaProvider: context.mediaProvider)),
|
||||
kind: .navigationLink {
|
||||
context.showSpaceSelectionSheet = true
|
||||
})
|
||||
} else {
|
||||
ListRow(label: .default(title: "Test", icon: \.home),
|
||||
kind: .navigationLink {
|
||||
context.showSpaceSelectionSheet = true
|
||||
})
|
||||
}
|
||||
} header: {
|
||||
Text(L10n.commonSpace)
|
||||
.compoundListSectionHeader()
|
||||
@@ -317,6 +334,7 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview {
|
||||
AppSettings.resetAllSettings()
|
||||
let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: "@userid:example.com"))))
|
||||
return CreateRoomScreenViewModel(isSpace: false,
|
||||
spaceSelectionMode: .list,
|
||||
shouldShowCancelButton: false,
|
||||
userSession: userSession,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
@@ -328,6 +346,7 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview {
|
||||
AppSettings.resetAllSettings()
|
||||
let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: "@userid:example.com"))))
|
||||
let viewModel = CreateRoomScreenViewModel(isSpace: false,
|
||||
spaceSelectionMode: .list,
|
||||
shouldShowCancelButton: false,
|
||||
userSession: userSession,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
@@ -341,6 +360,7 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview {
|
||||
AppSettings.resetAllSettings()
|
||||
let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: "@userid:example.com"))))
|
||||
return CreateRoomScreenViewModel(isSpace: true,
|
||||
spaceSelectionMode: nil,
|
||||
shouldShowCancelButton: true,
|
||||
userSession: userSession,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
@@ -352,6 +372,7 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview {
|
||||
AppSettings.resetAllSettings()
|
||||
let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userID: "@userid:example.com"))))
|
||||
let viewModel = CreateRoomScreenViewModel(isSpace: true,
|
||||
spaceSelectionMode: nil,
|
||||
shouldShowCancelButton: true,
|
||||
userSession: userSession,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
@@ -365,6 +386,7 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview {
|
||||
AppSettings.resetAllSettings()
|
||||
let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userIDServerName: "example.org", userID: "@userid:example.com"))))
|
||||
let viewModel = CreateRoomScreenViewModel(isSpace: false,
|
||||
spaceSelectionMode: .list,
|
||||
shouldShowCancelButton: false,
|
||||
userSession: userSession,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
@@ -380,6 +402,7 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview {
|
||||
appSettings.knockingEnabled = true
|
||||
let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userIDServerName: "example.org", userID: "@userid:example.com"))))
|
||||
let viewModel = CreateRoomScreenViewModel(isSpace: false,
|
||||
spaceSelectionMode: .list,
|
||||
shouldShowCancelButton: false,
|
||||
userSession: userSession,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
@@ -393,6 +416,7 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview {
|
||||
AppSettings.resetAllSettings()
|
||||
let userSession = UserSessionMock(.init(clientProxy: ClientProxyMock(.init(userIDServerName: "example.org", userID: "@userid:example.com"))))
|
||||
let viewModel = CreateRoomScreenViewModel(isSpace: false,
|
||||
spaceSelectionMode: .list,
|
||||
shouldShowCancelButton: false,
|
||||
userSession: userSession,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
@@ -409,6 +433,7 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview {
|
||||
clientProxy.isAliasAvailableReturnValue = .success(false)
|
||||
let userSession = UserSessionMock(.init(clientProxy: clientProxy))
|
||||
let viewModel = CreateRoomScreenViewModel(isSpace: false,
|
||||
spaceSelectionMode: .list,
|
||||
shouldShowCancelButton: false,
|
||||
userSession: userSession,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// Copyright 2026 Element Creations Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct CreateRoomSpaceSelectionSheet: View {
|
||||
@ObservedObject var context: CreateRoomScreenViewModel.Context
|
||||
|
||||
var body: some View {
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
|
||||
struct CreateRoomSpaceSelectionSheet_Previews: PreviewProvider, TestablePreview {
|
||||
static var previews: some View {
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user