mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:55:59 +00:00
started implementing the logic behind the access type and the creation parameters
This commit is contained in:
@@ -29,6 +29,7 @@ struct CreateRoomScreenViewState: BindableState {
|
|||||||
var roomName: String
|
var roomName: String
|
||||||
let serverName: String
|
let serverName: String
|
||||||
let isKnockingFeatureEnabled: Bool
|
let isKnockingFeatureEnabled: Bool
|
||||||
|
let canSelectSpace: Bool
|
||||||
var aliasLocalPart: String
|
var aliasLocalPart: String
|
||||||
var bindings: CreateRoomScreenViewStateBindings
|
var bindings: CreateRoomScreenViewStateBindings
|
||||||
var avatarMediaInfo: MediaInfo? {
|
var avatarMediaInfo: MediaInfo? {
|
||||||
@@ -59,18 +60,46 @@ struct CreateRoomScreenViewState: BindableState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var availableAccessTypes: [CreateRoomAccessType] {
|
var selectedSpace: SpaceServiceRoomProtocol?
|
||||||
var availableTypes = CreateRoomAccessType.allCases
|
|
||||||
if isSpace || !isKnockingFeatureEnabled {
|
var availableAccessTypes: [CreateRoomScreenAccessType] {
|
||||||
availableTypes.removeAll { $0 == .askToJoin }
|
var availableAccessTypes: [CreateRoomScreenAccessType] = []
|
||||||
|
if isSpace {
|
||||||
|
availableAccessTypes = [.public]
|
||||||
|
} else if let selectedSpace, selectedSpace.joinRule != .public {
|
||||||
|
availableAccessTypes = [.spaceMembers]
|
||||||
|
if isKnockingFeatureEnabled {
|
||||||
|
availableAccessTypes.append(.askToJoinWithSpaceMembers)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
availableAccessTypes = [.public]
|
||||||
|
if isKnockingFeatureEnabled {
|
||||||
|
availableAccessTypes.append(.askToJoin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
availableAccessTypes.append(.private)
|
||||||
|
return availableAccessTypes
|
||||||
|
}
|
||||||
|
|
||||||
|
var roomAccessType: CreateRoomAccessType {
|
||||||
|
switch bindings.selectedAccessType {
|
||||||
|
case .public:
|
||||||
|
return .public
|
||||||
|
case .spaceMembers:
|
||||||
|
return .spaceMembers(spaceID: selectedSpace?.id ?? "")
|
||||||
|
case .askToJoinWithSpaceMembers:
|
||||||
|
return .askToJoinWithSpaceMembers(spaceID: selectedSpace?.id ?? "")
|
||||||
|
case .askToJoin:
|
||||||
|
return .askToJoin
|
||||||
|
case .private:
|
||||||
|
return .private
|
||||||
}
|
}
|
||||||
return availableTypes
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CreateRoomScreenViewStateBindings {
|
struct CreateRoomScreenViewStateBindings {
|
||||||
var roomTopic: String
|
var roomTopic: String
|
||||||
var selectedAccessType: CreateRoomAccessType
|
var selectedAccessType: CreateRoomScreenAccessType
|
||||||
var showAttachmentConfirmationDialog = false
|
var showAttachmentConfirmationDialog = false
|
||||||
|
|
||||||
/// Information describing the currently displayed alert.
|
/// Information describing the currently displayed alert.
|
||||||
@@ -102,3 +131,11 @@ extension Set<CreateRoomScreenAliasErrorState> {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum CreateRoomScreenAccessType {
|
||||||
|
case `public`
|
||||||
|
case spaceMembers
|
||||||
|
case askToJoinWithSpaceMembers
|
||||||
|
case askToJoin
|
||||||
|
case `private`
|
||||||
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
|
|||||||
roomName: "",
|
roomName: "",
|
||||||
serverName: userSession.clientProxy.userIDServerName ?? "",
|
serverName: userSession.clientProxy.userIDServerName ?? "",
|
||||||
isKnockingFeatureEnabled: appSettings.knockingEnabled,
|
isKnockingFeatureEnabled: appSettings.knockingEnabled,
|
||||||
|
canSelectSpace: isSpace ? false : appSettings.createSpaceEnabled,
|
||||||
aliasLocalPart: roomAliasNameFromRoomDisplayName(roomName: ""),
|
aliasLocalPart: roomAliasNameFromRoomDisplayName(roomName: ""),
|
||||||
bindings: bindings),
|
bindings: bindings),
|
||||||
mediaProvider: userSession.mediaProvider)
|
mediaProvider: userSession.mediaProvider)
|
||||||
@@ -114,9 +115,9 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
|
|||||||
// Reset the state related to public rooms if the user choses the room to be empty
|
// Reset the state related to public rooms if the user choses the room to be empty
|
||||||
context.$viewState
|
context.$viewState
|
||||||
.dropFirst()
|
.dropFirst()
|
||||||
.map(\.bindings.selectedAccessType)
|
.map(\.roomAccessType)
|
||||||
.removeDuplicates()
|
|
||||||
.filter(\.isPrivate)
|
.filter(\.isPrivate)
|
||||||
|
.removeDuplicates()
|
||||||
.receive(on: DispatchQueue.main)
|
.receive(on: DispatchQueue.main)
|
||||||
.sink { [weak self] _ in
|
.sink { [weak self] _ in
|
||||||
guard let self else { return }
|
guard let self else { return }
|
||||||
@@ -135,7 +136,7 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard !state.bindings.selectedAccessType.isPrivate,
|
guard !state.roomAccessType.isPrivate,
|
||||||
let canonicalAlias = String.makeCanonicalAlias(aliasLocalPart: aliasLocalPart,
|
let canonicalAlias = String.makeCanonicalAlias(aliasLocalPart: aliasLocalPart,
|
||||||
serverName: state.serverName) else {
|
serverName: state.serverName) else {
|
||||||
// While is empty or private room we don't change or display the error
|
// While is empty or private room we don't change or display the error
|
||||||
@@ -167,6 +168,18 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
|
||||||
|
context.$viewState
|
||||||
|
.map(\.availableAccessTypes)
|
||||||
|
.removeDuplicates()
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { [weak self] availableAccessTypes in
|
||||||
|
guard let self else { return }
|
||||||
|
if !availableAccessTypes.contains(state.bindings.selectedAccessType) {
|
||||||
|
state.bindings.selectedAccessType = .private
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func createRoom() async {
|
private func createRoom() async {
|
||||||
@@ -176,7 +189,7 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
|
|||||||
showLoadingIndicator()
|
showLoadingIndicator()
|
||||||
|
|
||||||
// Better to double check the errors also when trying to create the room
|
// Better to double check the errors also when trying to create the room
|
||||||
if !state.bindings.selectedAccessType.isPrivate {
|
if !state.roomAccessType.isPrivate {
|
||||||
guard let canonicalAlias = String.makeCanonicalAlias(aliasLocalPart: state.aliasLocalPart,
|
guard let canonicalAlias = String.makeCanonicalAlias(aliasLocalPart: state.aliasLocalPart,
|
||||||
serverName: state.serverName),
|
serverName: state.serverName),
|
||||||
isRoomAliasFormatValid(alias: canonicalAlias) else {
|
isRoomAliasFormatValid(alias: canonicalAlias) else {
|
||||||
@@ -224,11 +237,11 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
|
|||||||
|
|
||||||
switch await userSession.clientProxy.createRoom(name: state.roomName,
|
switch await userSession.clientProxy.createRoom(name: state.roomName,
|
||||||
topic: state.bindings.roomTopic.isBlank ? nil : state.bindings.roomTopic,
|
topic: state.bindings.roomTopic.isBlank ? nil : state.bindings.roomTopic,
|
||||||
accessType: state.bindings.selectedAccessType,
|
accessType: state.roomAccessType,
|
||||||
isSpace: state.isSpace,
|
isSpace: state.isSpace,
|
||||||
userIDs: [], // The invite users screen is shown next so we don't need to invite anyone right now.
|
userIDs: [], // The invite users screen is shown next so we don't need to invite anyone right now.
|
||||||
avatarURL: avatarURL,
|
avatarURL: avatarURL,
|
||||||
aliasLocalPart: state.bindings.selectedAccessType.isPrivate ? nil : state.aliasLocalPart) {
|
aliasLocalPart: state.roomAccessType.isPrivate ? nil : state.aliasLocalPart) {
|
||||||
case .success(let roomID):
|
case .success(let roomID):
|
||||||
guard case let .joined(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomID) else {
|
guard case let .joined(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomID) else {
|
||||||
state.bindings.alertInfo = AlertInfo(id: .failedCreatingRoom,
|
state.bindings.alertInfo = AlertInfo(id: .failedCreatingRoom,
|
||||||
|
|||||||
@@ -39,8 +39,11 @@ struct CreateRoomScreen: View {
|
|||||||
Form {
|
Form {
|
||||||
roomSection
|
roomSection
|
||||||
topicSection
|
topicSection
|
||||||
|
if context.viewState.canSelectSpace {
|
||||||
|
selectSpaceSection
|
||||||
|
}
|
||||||
roomAccessSection
|
roomAccessSection
|
||||||
if !context.selectedAccessType.isPrivate {
|
if !context.viewState.roomAccessType.isPrivate {
|
||||||
roomAliasSection
|
roomAliasSection
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -181,6 +184,7 @@ struct CreateRoomScreen: View {
|
|||||||
Section {
|
Section {
|
||||||
ForEach(context.viewState.availableAccessTypes, id: \.self) { accessType in
|
ForEach(context.viewState.availableAccessTypes, id: \.self) { accessType in
|
||||||
CreateRoomAccessRow(access: accessType,
|
CreateRoomAccessRow(access: accessType,
|
||||||
|
spaceName: context.viewState.selectedSpace?.name ?? "",
|
||||||
isSelected: context.selectedAccessType == accessType) {
|
isSelected: context.selectedAccessType == accessType) {
|
||||||
context.selectedAccessType = accessType
|
context.selectedAccessType = accessType
|
||||||
}
|
}
|
||||||
@@ -215,6 +219,15 @@ struct CreateRoomScreen: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var selectSpaceSection: some View {
|
||||||
|
Section {
|
||||||
|
EmptyView()
|
||||||
|
} header: {
|
||||||
|
Text(L10n.commonSpace)
|
||||||
|
.compoundListSectionHeader()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ToolbarContentBuilder
|
@ToolbarContentBuilder
|
||||||
private var toolbar: some ToolbarContent {
|
private var toolbar: some ToolbarContent {
|
||||||
if context.viewState.shouldShowCancelButton {
|
if context.viewState.shouldShowCancelButton {
|
||||||
@@ -237,7 +250,8 @@ struct CreateRoomScreen: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private struct CreateRoomAccessRow: View {
|
private struct CreateRoomAccessRow: View {
|
||||||
let access: CreateRoomAccessType
|
let access: CreateRoomScreenAccessType
|
||||||
|
let spaceName: String
|
||||||
let isSelected: Bool
|
let isSelected: Bool
|
||||||
let onSelection: () -> Void
|
let onSelection: () -> Void
|
||||||
|
|
||||||
@@ -249,6 +263,10 @@ private struct CreateRoomAccessRow: View {
|
|||||||
L10n.screenCreateRoomRoomAccessSectionKnockingOptionTitle
|
L10n.screenCreateRoomRoomAccessSectionKnockingOptionTitle
|
||||||
case .private:
|
case .private:
|
||||||
L10n.screenCreateRoomRoomAccessSectionPrivateOptionTitle
|
L10n.screenCreateRoomRoomAccessSectionPrivateOptionTitle
|
||||||
|
case .spaceMembers:
|
||||||
|
L10n.screenCreateRoomRoomAccessSectionRestrictedOptionTitle
|
||||||
|
case .askToJoinWithSpaceMembers:
|
||||||
|
L10n.screenCreateRoomRoomAccessSectionKnockingRestrictedOptionTitle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,6 +278,10 @@ private struct CreateRoomAccessRow: View {
|
|||||||
L10n.screenCreateRoomRoomAccessSectionKnockingOptionDescription
|
L10n.screenCreateRoomRoomAccessSectionKnockingOptionDescription
|
||||||
case .private:
|
case .private:
|
||||||
L10n.screenCreateRoomRoomAccessSectionPrivateOptionDescription
|
L10n.screenCreateRoomRoomAccessSectionPrivateOptionDescription
|
||||||
|
case .spaceMembers:
|
||||||
|
L10n.screenCreateRoomRoomAccessSectionRestrictedOptionDescription(spaceName)
|
||||||
|
case .askToJoinWithSpaceMembers:
|
||||||
|
L10n.screenCreateRoomRoomAccessSectionKnockingRestrictedOptionDescription(spaceName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,6 +293,10 @@ private struct CreateRoomAccessRow: View {
|
|||||||
\.userAdd
|
\.userAdd
|
||||||
case .private:
|
case .private:
|
||||||
\.lock
|
\.lock
|
||||||
|
case .spaceMembers:
|
||||||
|
\.space
|
||||||
|
case .askToJoinWithSpaceMembers:
|
||||||
|
\.userAdd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -513,7 +513,7 @@ class ClientProxy: ClientProxyProtocol {
|
|||||||
Self.standardSpaceCreationPowerLevelOverrides
|
Self.standardSpaceCreationPowerLevelOverrides
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if accessType == .askToJoin {
|
if accessType.isAskToJoin {
|
||||||
Self.knockingRoomCreationPowerLevelOverrides
|
Self.knockingRoomCreationPowerLevelOverrides
|
||||||
} else {
|
} else {
|
||||||
Self.roomCreationPowerLevelOverrides
|
Self.roomCreationPowerLevelOverrides
|
||||||
@@ -1372,7 +1372,7 @@ private extension CreateRoomAccessType {
|
|||||||
switch self {
|
switch self {
|
||||||
case .public:
|
case .public:
|
||||||
false
|
false
|
||||||
case .askToJoin, .private:
|
default:
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1393,8 +1393,21 @@ private extension CreateRoomAccessType {
|
|||||||
switch self {
|
switch self {
|
||||||
case .askToJoin:
|
case .askToJoin:
|
||||||
.knock
|
.knock
|
||||||
|
case .spaceMembers(let spaceID):
|
||||||
|
.restricted(rules: [.roomMembership(roomId: spaceID)])
|
||||||
|
case .askToJoinWithSpaceMembers(let spaceID):
|
||||||
|
.knockRestricted(rules: [.roomMembership(roomId: spaceID)])
|
||||||
case .private, .public:
|
case .private, .public:
|
||||||
nil
|
nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isAskToJoin: Bool {
|
||||||
|
switch self {
|
||||||
|
case .askToJoin, .askToJoinWithSpaceMembers:
|
||||||
|
true
|
||||||
|
default:
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,14 +48,16 @@ enum SlidingSyncConstants {
|
|||||||
static let maximumVisibleRangeSize = 30
|
static let maximumVisibleRangeSize = 30
|
||||||
}
|
}
|
||||||
|
|
||||||
enum CreateRoomAccessType: CaseIterable {
|
enum CreateRoomAccessType: Equatable {
|
||||||
case `public`
|
case `public`
|
||||||
|
case spaceMembers(spaceID: String)
|
||||||
|
case askToJoinWithSpaceMembers(spaceID: String)
|
||||||
case askToJoin
|
case askToJoin
|
||||||
case `private`
|
case `private`
|
||||||
|
|
||||||
var isPrivate: Bool {
|
var isPrivate: Bool {
|
||||||
switch self {
|
switch self {
|
||||||
case .private:
|
case .private, .spaceMembers, .askToJoinWithSpaceMembers:
|
||||||
true
|
true
|
||||||
case .public, .askToJoin:
|
case .public, .askToJoin:
|
||||||
false
|
false
|
||||||
|
|||||||
Reference in New Issue
Block a user