// File created from TemplateAdvancedRoomsExample // $ createSwiftUITwoScreen.sh Spaces/SpaceCreation SpaceCreation SpaceCreationMenu SpaceCreationSettings // // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // import Combine import SwiftUI typealias SpaceCreationSettingsViewModelType = StateStoreViewModel class SpaceCreationSettingsViewModel: SpaceCreationSettingsViewModelType, SpaceCreationSettingsViewModelProtocol { // MARK: - Properties // MARK: Private private let spaceCreationSettingsService: SpaceCreationSettingsServiceProtocol private let creationParameters: SpaceCreationParameters // MARK: Public var callback: ((SpaceCreationSettingsViewModelAction) -> Void)? // MARK: - Setup init(spaceCreationSettingsService: SpaceCreationSettingsServiceProtocol, creationParameters: SpaceCreationParameters) { self.spaceCreationSettingsService = spaceCreationSettingsService self.creationParameters = creationParameters let defaultState = Self.defaultState(creationParameters: creationParameters, validationStatus: spaceCreationSettingsService.addressValidationSubject.value) super.init(initialViewState: defaultState) setupServiceObserving() } private func setupServiceObserving() { spaceCreationSettingsService .defaultAddressSubject .sink(receiveValue: { [weak self] address in self?.state.defaultAddress = address }) .store(in: &cancellables) spaceCreationSettingsService .addressValidationSubject .sink(receiveValue: { [weak self] status in self?.state.addressMessage = status.message self?.state.isAddressValid = status.isValid }) .store(in: &cancellables) spaceCreationSettingsService .avatarViewDataSubject .sink(receiveValue: { [weak self] avatar in self?.state.avatar = avatar }) .store(in: &cancellables) } private static func defaultState(creationParameters: SpaceCreationParameters, validationStatus: SpaceCreationSettingsAddressValidationStatus) -> SpaceCreationSettingsViewState { let bindings = SpaceCreationSettingsViewModelBindings( roomName: creationParameters.name ?? "", topic: creationParameters.topic ?? "", address: creationParameters.userDefinedAddress ?? "" ) return SpaceCreationSettingsViewState( title: creationParameters.isPublic ? VectorL10n.spacesCreationPublicSpaceTitle : VectorL10n.spacesCreationPrivateSpaceTitle, showRoomAddress: creationParameters.showAddress, defaultAddress: creationParameters.address ?? "", roomNameError: nil, addressMessage: validationStatus.message, isAddressValid: validationStatus.isValid, avatar: AvatarInput(mxContentUri: nil, matrixItemId: "", displayName: nil), avatarImage: creationParameters.userSelectedAvatar, bindings: bindings ) } // MARK: - Public func updateAvatarImage(with image: UIImage?) { creationParameters.userSelectedAvatar = image state.avatarImage = image } override func process(viewAction: SpaceCreationSettingsViewAction) { switch viewAction { case .done: done() case .back: back() case .cancel: cancel() case .pickImage(let sourceRect): pickImage(from: sourceRect) case .nameChanged(let newValue): spaceCreationSettingsService.roomName = newValue creationParameters.address = spaceCreationSettingsService.defaultAddressSubject.value creationParameters.name = newValue state.roomNameError = newValue.isEmpty ? VectorL10n.spacesCreationEmptyRoomNameError : nil case .addressChanged(let newValue): spaceCreationSettingsService.userDefinedAddress = newValue creationParameters.userDefinedAddress = newValue case .topicChanged(let newValue): creationParameters.topic = newValue } } // MARK: - Private private func done() { guard !context.roomName.isEmpty else { state.roomNameError = VectorL10n.spacesCreationEmptyRoomNameError return } guard !creationParameters.isPublic || spaceCreationSettingsService.isAddressValid else { return } creationParameters.name = context.roomName creationParameters.topic = context.topic creationParameters.userDefinedAddress = context.address creationParameters.address = spaceCreationSettingsService.defaultAddressSubject.value state.roomNameError = nil callback?(.done) } private func cancel() { callback?(.cancel) } private func back() { callback?(.back) } private func pickImage(from sourceRect: CGRect) { callback?(.pickImage(sourceRect)) } }