mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 10:33:45 +00:00
Create room redesign and refactor (#4942)
This commit is contained in:
@@ -13,17 +13,7 @@ import SwiftUI
|
||||
typealias CreateRoomScreenViewModelType = StateStoreViewModel<CreateRoomScreenViewState, CreateRoomScreenViewAction>
|
||||
|
||||
class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreenViewModelProtocol {
|
||||
struct Parameters {
|
||||
var name = ""
|
||||
var topic = ""
|
||||
var isRoomPrivate = true
|
||||
var isKnockingOnly = false
|
||||
var avatarImageMedia: MediaInfo?
|
||||
var aliasLocalPart: String?
|
||||
}
|
||||
|
||||
private let userSession: UserSessionProtocol
|
||||
private var parameters: Parameters
|
||||
private let mediaUploadingPreprocessor: MediaUploadingPreprocessor
|
||||
private let analytics: AnalyticsService
|
||||
private let userIndicatorController: UserIndicatorControllerProtocol
|
||||
@@ -36,25 +26,24 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
|
||||
actionsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
init(userSession: UserSessionProtocol,
|
||||
initialParameters: Parameters = .init(),
|
||||
init(isSpace: Bool,
|
||||
userSession: UserSessionProtocol,
|
||||
analytics: AnalyticsService,
|
||||
userIndicatorController: UserIndicatorControllerProtocol,
|
||||
appSettings: AppSettings) {
|
||||
self.userSession = userSession
|
||||
parameters = initialParameters
|
||||
mediaUploadingPreprocessor = MediaUploadingPreprocessor(appSettings: appSettings)
|
||||
self.analytics = analytics
|
||||
self.userIndicatorController = userIndicatorController
|
||||
|
||||
let bindings = CreateRoomScreenViewStateBindings(roomTopic: parameters.topic,
|
||||
isRoomPrivate: parameters.isRoomPrivate,
|
||||
isKnockingOnly: appSettings.knockingEnabled ? parameters.isKnockingOnly : false)
|
||||
let bindings = CreateRoomScreenViewStateBindings(roomTopic: "",
|
||||
selectedAccessType: .private)
|
||||
|
||||
super.init(initialViewState: CreateRoomScreenViewState(roomName: parameters.name,
|
||||
super.init(initialViewState: CreateRoomScreenViewState(isSpace: isSpace,
|
||||
roomName: "",
|
||||
serverName: userSession.clientProxy.userIDServerName ?? "",
|
||||
isKnockingFeatureEnabled: appSettings.knockingEnabled,
|
||||
aliasLocalPart: parameters.aliasLocalPart ?? roomAliasNameFromRoomDisplayName(roomName: parameters.name),
|
||||
aliasLocalPart: roomAliasNameFromRoomDisplayName(roomName: ""),
|
||||
bindings: bindings),
|
||||
mediaProvider: userSession.mediaProvider)
|
||||
|
||||
@@ -72,8 +61,7 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
|
||||
case .displayMediaPicker:
|
||||
actionsSubject.send(.displayMediaPicker)
|
||||
case .removeImage:
|
||||
parameters.avatarImageMedia = nil
|
||||
state.avatarURL = nil
|
||||
state.avatarMediaInfo = nil
|
||||
case .updateAliasLocalPart(let aliasLocalPart):
|
||||
state.aliasLocalPart = aliasLocalPart.lowercased()
|
||||
// If this has been called this means that the user wants a custom address not necessarily reflecting the name
|
||||
@@ -104,9 +92,8 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
|
||||
let mediaInfo = try await mediaUploadingPreprocessor.processMedia(at: fileURL, maxUploadSize: maxUploadSize).get()
|
||||
|
||||
switch mediaInfo {
|
||||
case .image(_, let thumbnailURL, _):
|
||||
parameters.avatarImageMedia = mediaInfo
|
||||
state.avatarURL = thumbnailURL
|
||||
case .image:
|
||||
state.avatarMediaInfo = mediaInfo
|
||||
default:
|
||||
break
|
||||
}
|
||||
@@ -123,34 +110,18 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
|
||||
// Reset the state related to public rooms if the user choses the room to be empty
|
||||
context.$viewState
|
||||
.dropFirst()
|
||||
.map(\.bindings.isRoomPrivate)
|
||||
.map(\.bindings.selectedAccessType)
|
||||
.removeDuplicates()
|
||||
.filter { $0 }
|
||||
.filter(\.isPrivate)
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] _ in
|
||||
guard let self else { return }
|
||||
state.bindings.isKnockingOnly = false
|
||||
state.aliasErrors = []
|
||||
state.aliasLocalPart = roomAliasNameFromRoomDisplayName(roomName: state.roomName)
|
||||
syncNameAndAlias = true
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
context.$viewState
|
||||
.throttle(for: 0.5, scheduler: DispatchQueue.main, latest: true)
|
||||
.removeDuplicates { old, new in
|
||||
old.roomName == new.roomName &&
|
||||
old.bindings.roomTopic == new.bindings.roomTopic &&
|
||||
old.bindings.isRoomPrivate == new.bindings.isRoomPrivate &&
|
||||
old.bindings.isKnockingOnly == new.bindings.isKnockingOnly &&
|
||||
old.aliasLocalPart == new.aliasLocalPart
|
||||
}
|
||||
.sink { [weak self] state in
|
||||
guard let self else { return }
|
||||
updateParameters(state: state)
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
context.$viewState
|
||||
.map(\.aliasLocalPart)
|
||||
.removeDuplicates()
|
||||
@@ -160,8 +131,7 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
|
||||
return
|
||||
}
|
||||
|
||||
guard state.isKnockingFeatureEnabled,
|
||||
!state.bindings.isRoomPrivate,
|
||||
guard !state.bindings.selectedAccessType.isPrivate,
|
||||
let canonicalAlias = String.makeCanonicalAlias(aliasLocalPart: aliasLocalPart,
|
||||
serverName: state.serverName) else {
|
||||
// While is empty or private room we don't change or display the error
|
||||
@@ -195,30 +165,15 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
private func updateParameters(state: CreateRoomScreenViewState) {
|
||||
parameters.name = state.roomName
|
||||
parameters.topic = state.bindings.roomTopic
|
||||
parameters.isRoomPrivate = state.bindings.isRoomPrivate
|
||||
parameters.isKnockingOnly = state.bindings.isKnockingOnly
|
||||
if state.isKnockingFeatureEnabled, !state.aliasLocalPart.isEmpty {
|
||||
parameters.aliasLocalPart = state.aliasLocalPart
|
||||
} else {
|
||||
parameters.aliasLocalPart = nil
|
||||
}
|
||||
}
|
||||
|
||||
private func createRoom() async {
|
||||
defer {
|
||||
hideLoadingIndicator()
|
||||
}
|
||||
showLoadingIndicator()
|
||||
|
||||
// Since the parameters are throttled, we need to make sure that the latest values are used
|
||||
updateParameters(state: state)
|
||||
|
||||
// Better to double check the errors also when trying to create the room
|
||||
if state.isKnockingFeatureEnabled, !parameters.isRoomPrivate {
|
||||
guard let canonicalAlias = String.makeCanonicalAlias(aliasLocalPart: parameters.aliasLocalPart,
|
||||
if !state.bindings.selectedAccessType.isPrivate {
|
||||
guard let canonicalAlias = String.makeCanonicalAlias(aliasLocalPart: state.aliasLocalPart,
|
||||
serverName: state.serverName),
|
||||
isRoomAliasFormatValid(alias: canonicalAlias) else {
|
||||
state.aliasErrors = [.invalidSymbols]
|
||||
@@ -238,7 +193,7 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
|
||||
}
|
||||
|
||||
let avatarURL: URL?
|
||||
if let media = parameters.avatarImageMedia {
|
||||
if let media = state.avatarMediaInfo {
|
||||
switch await userSession.clientProxy.uploadMedia(media) {
|
||||
case .success(let url):
|
||||
avatarURL = URL(string: url)
|
||||
@@ -263,14 +218,13 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen
|
||||
avatarURL = nil
|
||||
}
|
||||
|
||||
switch await userSession.clientProxy.createRoom(name: parameters.name,
|
||||
topic: parameters.topic.isBlank ? nil : parameters.topic,
|
||||
isRoomPrivate: parameters.isRoomPrivate,
|
||||
// As of right now we don't want to make private rooms with the knock rule
|
||||
isKnockingOnly: parameters.isRoomPrivate ? false : parameters.isKnockingOnly,
|
||||
switch await userSession.clientProxy.createRoom(name: state.roomName,
|
||||
topic: state.bindings.roomTopic.isBlank ? nil : state.bindings.roomTopic,
|
||||
accessType: state.bindings.selectedAccessType,
|
||||
isSpace: state.isSpace,
|
||||
userIDs: [], // The invite users screen is shown next so we don't need to invite anyone right now.
|
||||
avatarURL: avatarURL,
|
||||
aliasLocalPart: parameters.isRoomPrivate ? nil : parameters.aliasLocalPart) {
|
||||
aliasLocalPart: state.bindings.selectedAccessType.isPrivate ? nil : state.aliasLocalPart) {
|
||||
case .success(let roomID):
|
||||
guard case let .joined(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomID) else {
|
||||
state.bindings.alertInfo = AlertInfo(id: .failedCreatingRoom,
|
||||
|
||||
Reference in New Issue
Block a user