mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-21 17:12:45 +02:00
Configured and applied SwiftFormat
This commit is contained in:
committed by
Stefan Ceriu
parent
ff2e6ddfa7
commit
43c28d23b7
+19
-19
@@ -24,7 +24,6 @@ enum SpaceSettingsModalCoordinatorAction {
|
||||
|
||||
@objcMembers
|
||||
final class SpaceSettingsModalCoordinator: Coordinator {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
@@ -36,7 +35,7 @@ final class SpaceSettingsModalCoordinator: Coordinator {
|
||||
}
|
||||
|
||||
private var navigationRouter: NavigationRouterType {
|
||||
return self.parameters.navigationRouter
|
||||
parameters.navigationRouter
|
||||
}
|
||||
|
||||
// MARK: Public
|
||||
@@ -50,31 +49,30 @@ final class SpaceSettingsModalCoordinator: Coordinator {
|
||||
|
||||
init(parameters: SpaceSettingsModalCoordinatorParameters) {
|
||||
self.parameters = parameters
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
|
||||
func start() {
|
||||
MXLog.debug("[SpaceSettingsModalCoordinator] did start.")
|
||||
let rootCoordinator = self.createSpaceSettingsCoordinator()
|
||||
let rootCoordinator = createSpaceSettingsCoordinator()
|
||||
rootCoordinator.start()
|
||||
|
||||
self.add(childCoordinator: rootCoordinator)
|
||||
add(childCoordinator: rootCoordinator)
|
||||
|
||||
if self.navigationRouter.modules.isEmpty == false {
|
||||
self.navigationRouter.push(rootCoordinator, animated: true, popCompletion: { [weak self] in
|
||||
if navigationRouter.modules.isEmpty == false {
|
||||
navigationRouter.push(rootCoordinator, animated: true, popCompletion: { [weak self] in
|
||||
self?.remove(childCoordinator: rootCoordinator)
|
||||
})
|
||||
} else {
|
||||
self.navigationRouter.setRootModule(rootCoordinator) { [weak self] in
|
||||
navigationRouter.setRootModule(rootCoordinator) { [weak self] in
|
||||
self?.remove(childCoordinator: rootCoordinator)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func toPresentable() -> UIViewController {
|
||||
return self.navigationRouter.toPresentable()
|
||||
navigationRouter.toPresentable()
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
@@ -82,7 +80,7 @@ final class SpaceSettingsModalCoordinator: Coordinator {
|
||||
func pushScreen(with coordinator: Coordinator & Presentable) {
|
||||
add(childCoordinator: coordinator)
|
||||
|
||||
self.navigationRouter.push(coordinator, animated: true, popCompletion: { [weak self] in
|
||||
navigationRouter.push(coordinator, animated: true, popCompletion: { [weak self] in
|
||||
self?.remove(childCoordinator: coordinator)
|
||||
})
|
||||
|
||||
@@ -110,12 +108,12 @@ final class SpaceSettingsModalCoordinator: Coordinator {
|
||||
switch optionType {
|
||||
case .rooms:
|
||||
Analytics.shared.viewRoomTrigger = .spaceSettings
|
||||
exploreRooms(ofSpaceWithId: self.parameters.spaceId)
|
||||
exploreRooms(ofSpaceWithId: parameters.spaceId)
|
||||
case .members:
|
||||
Analytics.shared.viewRoomTrigger = .spaceSettings
|
||||
showMembers(ofSpaceWithId: self.parameters.spaceId)
|
||||
showMembers(ofSpaceWithId: parameters.spaceId)
|
||||
case .visibility:
|
||||
showAccess(ofSpaceWithId: self.parameters.spaceId)
|
||||
showAccess(ofSpaceWithId: parameters.spaceId)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +122,7 @@ final class SpaceSettingsModalCoordinator: Coordinator {
|
||||
coordinator.delegate = self
|
||||
add(childCoordinator: coordinator)
|
||||
coordinator.start()
|
||||
self.navigationRouter.present(coordinator.toPresentable(), animated: true)
|
||||
navigationRouter.present(coordinator.toPresentable(), animated: true)
|
||||
}
|
||||
|
||||
private func showMembers(ofSpaceWithId spaceId: String) {
|
||||
@@ -132,7 +130,7 @@ final class SpaceSettingsModalCoordinator: Coordinator {
|
||||
coordinator.delegate = self
|
||||
add(childCoordinator: coordinator)
|
||||
coordinator.start()
|
||||
self.navigationRouter.present(coordinator.toPresentable(), animated: true)
|
||||
navigationRouter.present(coordinator.toPresentable(), animated: true)
|
||||
}
|
||||
|
||||
private func showAccess(ofSpaceWithId spaceId: String) {
|
||||
@@ -158,23 +156,25 @@ final class SpaceSettingsModalCoordinator: Coordinator {
|
||||
}
|
||||
add(childCoordinator: coordinator)
|
||||
coordinator.start()
|
||||
self.navigationRouter.present(coordinator.toPresentable(), animated: true)
|
||||
navigationRouter.present(coordinator.toPresentable(), animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - ExploreRoomCoordinatorDelegate
|
||||
|
||||
extension SpaceSettingsModalCoordinator: ExploreRoomCoordinatorDelegate {
|
||||
func exploreRoomCoordinatorDidComplete(_ coordinator: ExploreRoomCoordinatorType) {
|
||||
self.navigationRouter.dismissModule(animated: true, completion: {
|
||||
navigationRouter.dismissModule(animated: true, completion: {
|
||||
self.remove(childCoordinator: coordinator)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - SpaceMembersCoordinatorDelegate
|
||||
|
||||
extension SpaceSettingsModalCoordinator: SpaceMembersCoordinatorDelegate {
|
||||
func spaceMembersCoordinatorDidCancel(_ coordinator: SpaceMembersCoordinatorType) {
|
||||
self.navigationRouter.dismissModule(animated: true, completion: {
|
||||
navigationRouter.dismissModule(animated: true, completion: {
|
||||
self.remove(childCoordinator: coordinator)
|
||||
})
|
||||
}
|
||||
|
||||
+2
-5
@@ -27,7 +27,6 @@ import UIKit
|
||||
/// Each bridge should be removed once the underlying Coordinator has been integrated by another Coordinator.
|
||||
@objcMembers
|
||||
final class SpaceSettingsModalCoordinatorBridgePresenter: NSObject {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
@@ -75,7 +74,7 @@ final class SpaceSettingsModalCoordinatorBridgePresenter: NSObject {
|
||||
}
|
||||
|
||||
func dismiss(animated: Bool, completion: (() -> Void)?) {
|
||||
guard let coordinator = self.coordinator else {
|
||||
guard let coordinator = coordinator else {
|
||||
return
|
||||
}
|
||||
coordinator.toPresentable().dismiss(animated: animated) {
|
||||
@@ -91,9 +90,7 @@ final class SpaceSettingsModalCoordinatorBridgePresenter: NSObject {
|
||||
// MARK: - UIAdaptivePresentationControllerDelegate
|
||||
|
||||
extension SpaceSettingsModalCoordinatorBridgePresenter: UIAdaptivePresentationControllerDelegate {
|
||||
|
||||
func roomNotificationSettingsCoordinatorDidComplete(_ presentationController: UIPresentationController) {
|
||||
self.delegate?.spaceSettingsModalCoordinatorBridgePresenterDelegateDidCancel(self)
|
||||
delegate?.spaceSettingsModalCoordinatorBridgePresenterDelegateDidCancel(self)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-1
@@ -18,7 +18,6 @@ import Foundation
|
||||
|
||||
/// SpaceSettingsModalCoordinator input parameters
|
||||
struct SpaceSettingsModalCoordinatorParameters {
|
||||
|
||||
/// The Matrix session
|
||||
let session: MXSession
|
||||
|
||||
|
||||
+3
-3
@@ -22,7 +22,6 @@ struct SpaceSettingsCoordinatorParameters {
|
||||
}
|
||||
|
||||
final class SpaceSettingsCoordinator: Coordinator, Presentable {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
@@ -77,9 +76,9 @@ final class SpaceSettingsCoordinator: Coordinator, Presentable {
|
||||
}
|
||||
|
||||
func toPresentable() -> UIViewController {
|
||||
return self.spaceSettingsHostingController
|
||||
|
||||
spaceSettingsHostingController
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func pickImage(from sourceRect: CGRect) {
|
||||
@@ -90,6 +89,7 @@ final class SpaceSettingsCoordinator: Coordinator, Presentable {
|
||||
}
|
||||
|
||||
// MARK: - SingleImagePickerPresenterDelegate
|
||||
|
||||
extension SpaceSettingsCoordinator: SingleImagePickerPresenterDelegate {
|
||||
func singleImagePickerPresenter(_ presenter: SingleImagePickerPresenter, didSelectImageData imageData: Data, withUTI uti: MXKUTI?) {
|
||||
spaceSettingsViewModel.updateAvatarImage(with: UIImage(data: imageData))
|
||||
|
||||
+6
-4
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -38,7 +38,7 @@ enum MockSpaceSettingsScreenState: MockScreenState, CaseIterable {
|
||||
}
|
||||
|
||||
/// Generate the view struct for the screen state.
|
||||
var screenView: ([Any], AnyView) {
|
||||
var screenView: ([Any], AnyView) {
|
||||
let service: MockSpaceSettingsService
|
||||
switch self {
|
||||
case .visibility(let visibility):
|
||||
@@ -53,7 +53,8 @@ enum MockSpaceSettingsScreenState: MockScreenState, CaseIterable {
|
||||
isNameEditable: true,
|
||||
isTopicEditable: true,
|
||||
isAddressEditable: true,
|
||||
isAccessEditable: true)
|
||||
isAccessEditable: true
|
||||
)
|
||||
service = MockSpaceSettingsService(roomProperties: roomProperties)
|
||||
case .notEditable:
|
||||
let roomProperties = SpaceSettingsRoomProperties(
|
||||
@@ -67,7 +68,8 @@ enum MockSpaceSettingsScreenState: MockScreenState, CaseIterable {
|
||||
isNameEditable: false,
|
||||
isTopicEditable: false,
|
||||
isAddressEditable: false,
|
||||
isAccessEditable: false)
|
||||
isAccessEditable: false
|
||||
)
|
||||
service = MockSpaceSettingsService(roomProperties: roomProperties)
|
||||
}
|
||||
let viewModel = SpaceSettingsViewModel.makeSpaceSettingsViewModel(service: service)
|
||||
|
||||
+55
-55
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -14,12 +14,11 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
import Foundation
|
||||
import MatrixSDK
|
||||
|
||||
class SpaceSettingsService: SpaceSettingsServiceProtocol {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
var userDefinedAddress: String? {
|
||||
@@ -36,6 +35,7 @@ class SpaceSettingsService: SpaceSettingsServiceProtocol {
|
||||
updateRoomProperties()
|
||||
}
|
||||
}
|
||||
|
||||
private let room: MXRoom?
|
||||
private var roomEventListener: Any?
|
||||
|
||||
@@ -88,12 +88,12 @@ class SpaceSettingsService: SpaceSettingsServiceProtocol {
|
||||
init(session: MXSession, spaceId: String) {
|
||||
self.session = session
|
||||
self.spaceId = spaceId
|
||||
self.room = session.room(withRoomId: spaceId)
|
||||
self.isLoadingSubject = CurrentValueSubject(false)
|
||||
self.showPostProcessAlert = CurrentValueSubject(false)
|
||||
self.roomPropertiesSubject = CurrentValueSubject(self.roomProperties)
|
||||
self.addressValidationSubject = CurrentValueSubject(.none("#"))
|
||||
self.defaultAddress = ""
|
||||
room = session.room(withRoomId: spaceId)
|
||||
isLoadingSubject = CurrentValueSubject(false)
|
||||
showPostProcessAlert = CurrentValueSubject(false)
|
||||
roomPropertiesSubject = CurrentValueSubject(roomProperties)
|
||||
addressValidationSubject = CurrentValueSubject(.none("#"))
|
||||
defaultAddress = ""
|
||||
|
||||
readRoomState()
|
||||
}
|
||||
@@ -121,15 +121,15 @@ class SpaceSettingsService: SpaceSettingsServiceProtocol {
|
||||
|
||||
private func readRoomState() {
|
||||
isLoadingSubject.send(true)
|
||||
self.room?.state { [weak self] roomState in
|
||||
room?.state { [weak self] roomState in
|
||||
self?.roomState = roomState
|
||||
self?.isLoadingSubject.send(false)
|
||||
}
|
||||
|
||||
roomEventListener = self.room?.listen(toEvents: { [weak self] event, direction, state in
|
||||
self?.room?.state({ [weak self] roomState in
|
||||
roomEventListener = room?.listen(toEvents: { [weak self] _, _, _ in
|
||||
self?.room?.state { [weak self] roomState in
|
||||
self?.roomState = roomState
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ class SpaceSettingsService: SpaceSettingsServiceProtocol {
|
||||
return false
|
||||
}
|
||||
|
||||
let userPowerLevel = powerLevels.powerLevelOfUser(withUserID: self.session.myUserId)
|
||||
let userPowerLevel = powerLevels.powerLevelOfUser(withUserID: session.myUserId)
|
||||
return userPowerLevel >= powerLevels.minimumPowerLevel(forNotifications: notification, defaultPower: powerLevels.stateDefault)
|
||||
}
|
||||
|
||||
@@ -172,10 +172,10 @@ class SpaceSettingsService: SpaceSettingsServiceProtocol {
|
||||
addressValidationOperation?.cancel()
|
||||
addressValidationOperation = nil
|
||||
|
||||
guard let userDefinedAddress = self.userDefinedAddress, !userDefinedAddress.isEmpty else {
|
||||
guard let userDefinedAddress = userDefinedAddress, !userDefinedAddress.isEmpty else {
|
||||
let fullAddress = MXTools.fullLocalAlias(from: defaultAddress, with: session)
|
||||
|
||||
if let publicAddress = self.publicAddress, !publicAddress.isEmpty {
|
||||
if let publicAddress = publicAddress, !publicAddress.isEmpty {
|
||||
addressValidationSubject.send(.current(fullAddress))
|
||||
} else if defaultAddress.isEmpty {
|
||||
addressValidationSubject.send(.none(fullAddress))
|
||||
@@ -191,8 +191,8 @@ class SpaceSettingsService: SpaceSettingsServiceProtocol {
|
||||
private func validate(_ aliasLocalPart: String) {
|
||||
let fullAddress = MXTools.fullLocalAlias(from: aliasLocalPart, with: session)
|
||||
|
||||
if let publicAddress = self.publicAddress, publicAddress == aliasLocalPart {
|
||||
self.addressValidationSubject.send(.current(fullAddress))
|
||||
if let publicAddress = publicAddress, publicAddress == aliasLocalPart {
|
||||
addressValidationSubject.send(.current(fullAddress))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -221,17 +221,17 @@ class SpaceSettingsService: SpaceSettingsServiceProtocol {
|
||||
|
||||
if let canonicalAlias = roomState.canonicalAlias {
|
||||
let localAliasPart = MXTools.extractLocalAliasPart(from: canonicalAlias)
|
||||
self.publicAddress = localAliasPart
|
||||
self.defaultAddress = localAliasPart
|
||||
publicAddress = localAliasPart
|
||||
defaultAddress = localAliasPart
|
||||
} else {
|
||||
self.publicAddress = nil
|
||||
self.defaultAddress = MXTools.validAliasLocalPart(from: roomState.name)
|
||||
publicAddress = nil
|
||||
defaultAddress = MXTools.validAliasLocalPart(from: roomState.name)
|
||||
}
|
||||
|
||||
self.roomProperties = SpaceSettingsRoomProperties(
|
||||
roomProperties = SpaceSettingsRoomProperties(
|
||||
name: roomState.name,
|
||||
topic: roomState.topic,
|
||||
address: self.defaultAddress,
|
||||
address: defaultAddress,
|
||||
avatarUrl: roomState.avatar,
|
||||
visibility: visibility(with: roomState),
|
||||
allowedParentIds: allowedParentIds(with: roomState),
|
||||
@@ -239,12 +239,13 @@ class SpaceSettingsService: SpaceSettingsServiceProtocol {
|
||||
isNameEditable: isField(ofType: kMXEventTypeStringRoomName, editableWith: roomState.powerLevels),
|
||||
isTopicEditable: isField(ofType: kMXEventTypeStringRoomTopic, editableWith: roomState.powerLevels),
|
||||
isAddressEditable: isField(ofType: kMXEventTypeStringRoomAliases, editableWith: roomState.powerLevels),
|
||||
isAccessEditable: isField(ofType: kMXEventTypeStringRoomJoinRules, editableWith: roomState.powerLevels))
|
||||
isAccessEditable: isField(ofType: kMXEventTypeStringRoomJoinRules, editableWith: roomState.powerLevels)
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: - Post process
|
||||
|
||||
private var currentTaskIndex: Int = 0
|
||||
private var currentTaskIndex = 0
|
||||
private var tasks: [PostProcessTask] = []
|
||||
private var lastError: Error?
|
||||
private var completion: ((_ result: SpaceSettingsServiceCompletionResult) -> Void)?
|
||||
@@ -267,18 +268,18 @@ class SpaceSettingsService: SpaceSettingsServiceProtocol {
|
||||
let type: PostProcessTaskType
|
||||
var state: PostProcessTaskState = .none
|
||||
var isFinished: Bool {
|
||||
return state == .failure || state == .success
|
||||
state == .failure || state == .success
|
||||
}
|
||||
|
||||
static func == (lhs: PostProcessTask, rhs: PostProcessTask) -> Bool {
|
||||
return lhs.type == rhs.type && lhs.state == rhs.state
|
||||
lhs.type == rhs.type && lhs.state == rhs.state
|
||||
}
|
||||
}
|
||||
|
||||
func update(roomName: String, topic: String, address: String, avatar: UIImage?,
|
||||
completion: ((_ result: SpaceSettingsServiceCompletionResult) -> Void)?) {
|
||||
// First attempt
|
||||
if self.tasks.isEmpty {
|
||||
if tasks.isEmpty {
|
||||
var tasks: [PostProcessTask] = []
|
||||
if roomProperties?.name ?? "" != roomName {
|
||||
tasks.append(PostProcessTask(type: .updateName(roomName)))
|
||||
@@ -295,17 +296,17 @@ class SpaceSettingsService: SpaceSettingsServiceProtocol {
|
||||
self.tasks = tasks
|
||||
} else {
|
||||
// Retry -> restart failed tasks
|
||||
self.tasks = tasks.map({ task in
|
||||
tasks = tasks.map { task in
|
||||
if task.state == .failure {
|
||||
return PostProcessTask(type: task.type, state: .none)
|
||||
}
|
||||
return task
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
self.isLoadingSubject.send(true)
|
||||
isLoadingSubject.send(true)
|
||||
self.completion = completion
|
||||
self.lastError = nil
|
||||
lastError = nil
|
||||
currentTaskIndex = -1
|
||||
runNextTask()
|
||||
}
|
||||
@@ -313,7 +314,7 @@ class SpaceSettingsService: SpaceSettingsServiceProtocol {
|
||||
private func runNextTask() {
|
||||
currentTaskIndex += 1
|
||||
guard currentTaskIndex < tasks.count else {
|
||||
self.isLoadingSubject.send(false)
|
||||
isLoadingSubject.send(false)
|
||||
if let error = lastError {
|
||||
showPostProcessAlert.send(true)
|
||||
completion?(.failure(error))
|
||||
@@ -395,7 +396,7 @@ class SpaceSettingsService: SpaceSettingsServiceProtocol {
|
||||
switch response {
|
||||
case .success:
|
||||
if let publicAddress = self.publicAddress {
|
||||
self.currentOperation = self.room?.removeAlias(MXTools.fullLocalAlias(from: publicAddress, with: self.session), completion: { [weak self] response in
|
||||
self.currentOperation = self.room?.removeAlias(MXTools.fullLocalAlias(from: publicAddress, with: self.session), completion: { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.setup(canonicalAlias: canonicalAlias)
|
||||
@@ -433,33 +434,33 @@ class SpaceSettingsService: SpaceSettingsServiceProtocol {
|
||||
let avatarUp = MXKTools.forceImageOrientationUp(avatar)
|
||||
|
||||
mediaUploader.uploadData(avatarUp?.jpegData(compressionQuality: 0.5), filename: nil, mimeType: "image/jpeg",
|
||||
success: { [weak self] (urlString) in
|
||||
guard let self = self else { return }
|
||||
success: { [weak self] urlString in
|
||||
guard let self = self else { return }
|
||||
|
||||
guard let urlString = urlString else {
|
||||
self.updateCurrentTaskState(with: .failure)
|
||||
self.runNextTask()
|
||||
return
|
||||
}
|
||||
guard let url = URL(string: urlString) else {
|
||||
self.updateCurrentTaskState(with: .failure)
|
||||
self.runNextTask()
|
||||
return
|
||||
}
|
||||
guard let urlString = urlString else {
|
||||
self.updateCurrentTaskState(with: .failure)
|
||||
self.runNextTask()
|
||||
return
|
||||
}
|
||||
guard let url = URL(string: urlString) else {
|
||||
self.updateCurrentTaskState(with: .failure)
|
||||
self.runNextTask()
|
||||
return
|
||||
}
|
||||
|
||||
self.setAvatar(withURL: url)
|
||||
self.setAvatar(withURL: url)
|
||||
},
|
||||
failure: { [weak self] (error) in
|
||||
guard let self = self else { return }
|
||||
failure: { [weak self] error in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.lastError = error
|
||||
self.updateCurrentTaskState(with: .failure)
|
||||
self.runNextTask()
|
||||
self.lastError = error
|
||||
self.updateCurrentTaskState(with: .failure)
|
||||
self.runNextTask()
|
||||
})
|
||||
}
|
||||
|
||||
private func setAvatar(withURL url: URL) {
|
||||
currentOperation = room?.setAvatar(url: url) { [weak self] (response) in
|
||||
currentOperation = room?.setAvatar(url: url) { [weak self] response in
|
||||
guard let self = self else { return }
|
||||
|
||||
switch response {
|
||||
@@ -473,5 +474,4 @@ class SpaceSettingsService: SpaceSettingsServiceProtocol {
|
||||
self.runNextTask()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+9
-15
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -14,11 +14,10 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
import Foundation
|
||||
|
||||
class MockSpaceSettingsService: SpaceSettingsServiceProtocol {
|
||||
|
||||
var spaceId: String
|
||||
var roomProperties: SpaceSettingsRoomProperties?
|
||||
private(set) var displayName: String?
|
||||
@@ -36,24 +35,19 @@ class MockSpaceSettingsService: SpaceSettingsServiceProtocol {
|
||||
self.spaceId = spaceId
|
||||
self.roomProperties = roomProperties
|
||||
self.displayName = displayName
|
||||
self.isLoadingSubject = CurrentValueSubject(isLoading)
|
||||
isLoadingSubject = CurrentValueSubject(isLoading)
|
||||
self.showPostProcessAlert = CurrentValueSubject(showPostProcessAlert)
|
||||
self.roomPropertiesSubject = CurrentValueSubject(roomProperties)
|
||||
self.addressValidationSubject = CurrentValueSubject(.none(spaceId))
|
||||
roomPropertiesSubject = CurrentValueSubject(roomProperties)
|
||||
addressValidationSubject = CurrentValueSubject(.none(spaceId))
|
||||
}
|
||||
|
||||
func update(roomName: String, topic: String, address: String, avatar: UIImage?, completion: ((SpaceSettingsServiceCompletionResult) -> Void)?) {
|
||||
}
|
||||
func update(roomName: String, topic: String, address: String, avatar: UIImage?, completion: ((SpaceSettingsServiceCompletionResult) -> Void)?) { }
|
||||
|
||||
func addressDidChange(_ newValue: String) {
|
||||
|
||||
}
|
||||
func addressDidChange(_ newValue: String) { }
|
||||
|
||||
func simulateUpdate(addressValidationStatus: SpaceCreationSettingsAddressValidationStatus) {
|
||||
self.addressValidationSubject.value = addressValidationStatus
|
||||
addressValidationSubject.value = addressValidationStatus
|
||||
}
|
||||
|
||||
func trackSpace() {
|
||||
|
||||
}
|
||||
func trackSpace() { }
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -14,8 +14,8 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
import Foundation
|
||||
|
||||
enum SpaceSettingsServiceCompletionResult {
|
||||
case success
|
||||
@@ -42,6 +42,7 @@ extension SpaceSettingsServiceProtocol {
|
||||
var mxContentUri: String? {
|
||||
roomProperties?.avatarUrl
|
||||
}
|
||||
|
||||
var matrixItemId: String {
|
||||
spaceId
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -81,15 +81,19 @@ struct SpaceSettingsViewState: BindableState {
|
||||
var isModified: Bool {
|
||||
userSelectedAvatar != nil || isRoomNameModified || isTopicModified || isAddressModified
|
||||
}
|
||||
|
||||
var isRoomNameModified: Bool {
|
||||
(roomProperties?.name ?? "") != bindings.name
|
||||
}
|
||||
|
||||
var isTopicModified: Bool {
|
||||
(roomProperties?.topic ?? "") != bindings.topic
|
||||
}
|
||||
|
||||
var isAddressModified: Bool {
|
||||
(roomProperties?.address ?? "") != bindings.address
|
||||
}
|
||||
|
||||
var bindings: SpaceSettingsViewModelBindings
|
||||
}
|
||||
|
||||
|
||||
@@ -14,14 +14,13 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Combine
|
||||
import SwiftUI
|
||||
|
||||
typealias SpaceSettingsViewModelType = StateStoreViewModel<SpaceSettingsViewState,
|
||||
Never,
|
||||
SpaceSettingsViewAction>
|
||||
Never,
|
||||
SpaceSettingsViewAction>
|
||||
class SpaceSettingsViewModel: SpaceSettingsViewModelType, SpaceSettingsViewModelProtocol {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
private static let options: [SpaceSettingsOption] = [
|
||||
@@ -40,7 +39,7 @@ class SpaceSettingsViewModel: SpaceSettingsViewModelType, SpaceSettingsViewModel
|
||||
// MARK: - Setup
|
||||
|
||||
static func makeSpaceSettingsViewModel(service: SpaceSettingsServiceProtocol) -> SpaceSettingsViewModelProtocol {
|
||||
return SpaceSettingsViewModel(service: service)
|
||||
SpaceSettingsViewModel(service: service)
|
||||
}
|
||||
|
||||
private init(service: SpaceSettingsServiceProtocol) {
|
||||
@@ -54,7 +53,8 @@ class SpaceSettingsViewModel: SpaceSettingsViewModelType, SpaceSettingsViewModel
|
||||
name: service.roomProperties?.name ?? "",
|
||||
topic: service.roomProperties?.topic ?? "",
|
||||
address: service.roomProperties?.address ?? "",
|
||||
showPostProcessAlert: service.showPostProcessAlert.value)
|
||||
showPostProcessAlert: service.showPostProcessAlert.value
|
||||
)
|
||||
|
||||
return SpaceSettingsViewState(
|
||||
defaultAddress: service.roomProperties?.address ?? "",
|
||||
@@ -68,12 +68,13 @@ class SpaceSettingsViewModel: SpaceSettingsViewModelType, SpaceSettingsViewModel
|
||||
isLoading: service.isLoadingSubject.value,
|
||||
visibilityString: (service.roomProperties?.visibility ?? .private).stringValue,
|
||||
options: options,
|
||||
bindings: bindings)
|
||||
bindings: bindings
|
||||
)
|
||||
}
|
||||
|
||||
private func setupObservers() {
|
||||
service.isLoadingSubject.sink { [weak self] isLoading in
|
||||
self?.state.isLoading = isLoading
|
||||
self?.state.isLoading = isLoading
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
|
||||
+1
-2
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -17,7 +17,6 @@
|
||||
import Foundation
|
||||
|
||||
protocol SpaceSettingsViewModelProtocol {
|
||||
|
||||
var completion: ((SpaceSettingsViewModelResult) -> Void)? { get set }
|
||||
static func makeSpaceSettingsViewModel(service: SpaceSettingsServiceProtocol) -> SpaceSettingsViewModelProtocol
|
||||
var context: SpaceSettingsViewModelType.Context { get }
|
||||
|
||||
+1
-1
@@ -14,8 +14,8 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
import RiotSwiftUI
|
||||
import XCTest
|
||||
|
||||
class SpaceSettingsUITests: MockScreenTestCase {
|
||||
// Tests to be implemented.
|
||||
|
||||
+4
-3
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -14,8 +14,8 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
import Combine
|
||||
import XCTest
|
||||
|
||||
@testable import RiotSwiftUI
|
||||
|
||||
@@ -38,7 +38,8 @@ class SpaceSettingsViewModelTests: XCTestCase {
|
||||
isNameEditable: true,
|
||||
isTopicEditable: true,
|
||||
isAddressEditable: true,
|
||||
isAccessEditable: true)
|
||||
isAccessEditable: true
|
||||
)
|
||||
|
||||
service = MockSpaceSettingsService(roomProperties: roomProperties, displayName: roomProperties.name, isLoading: false, showPostProcessAlert: false)
|
||||
viewModel = SpaceSettingsViewModel.makeSpaceSettingsViewModel(service: service)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -17,7 +17,6 @@
|
||||
import SwiftUI
|
||||
|
||||
struct SpaceSettings: View {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
@@ -32,7 +31,7 @@ struct SpaceSettings: View {
|
||||
ScrollView {
|
||||
VStack {
|
||||
avatarView
|
||||
Spacer().frame(height:32)
|
||||
Spacer().frame(height: 32)
|
||||
formView
|
||||
roomAccess
|
||||
options
|
||||
@@ -63,7 +62,7 @@ struct SpaceSettings: View {
|
||||
Alert(title: Text(VectorL10n.settingsTitle),
|
||||
message: Text(VectorL10n.spaceSettingsUpdateFailedMessage),
|
||||
primaryButton: .default(Text(VectorL10n.retry), action: {
|
||||
updateSpace()
|
||||
updateSpace()
|
||||
}),
|
||||
secondaryButton: .cancel())
|
||||
})
|
||||
@@ -80,7 +79,7 @@ struct SpaceSettings: View {
|
||||
GeometryReader { reader in
|
||||
ZStack {
|
||||
SpaceAvatarImage(mxContentUri: viewModel.viewState.avatar.mxContentUri, matrixItemId: viewModel.viewState.avatar.matrixItemId, displayName: viewModel.viewState.avatar.displayName, size: .xxLarge)
|
||||
.padding(6)
|
||||
.padding(6)
|
||||
if let image = viewModel.viewState.userSelectedAvatar {
|
||||
Image(uiImage: image)
|
||||
.resizable()
|
||||
@@ -89,13 +88,13 @@ struct SpaceSettings: View {
|
||||
.clipShape(RoundedRectangle(cornerRadius: 8))
|
||||
}
|
||||
}.padding(10)
|
||||
.onTapGesture {
|
||||
guard viewModel.viewState.roomProperties?.isAvatarEditable == true else {
|
||||
return
|
||||
.onTapGesture {
|
||||
guard viewModel.viewState.roomProperties?.isAvatarEditable == true else {
|
||||
return
|
||||
}
|
||||
ResponderManager.resignFirstResponder()
|
||||
viewModel.send(viewAction: .pickImage(reader.frame(in: .global)))
|
||||
}
|
||||
ResponderManager.resignFirstResponder()
|
||||
viewModel.send(viewAction: .pickImage(reader.frame(in: .global)))
|
||||
}
|
||||
}
|
||||
if viewModel.viewState.roomProperties?.isAvatarEditable == true {
|
||||
Image(uiImage: Asset.Images.spaceCreationCamera.image)
|
||||
@@ -110,26 +109,28 @@ struct SpaceSettings: View {
|
||||
|
||||
@ViewBuilder
|
||||
private var formView: some View {
|
||||
VStack{
|
||||
VStack {
|
||||
RoundedBorderTextField(
|
||||
title: VectorL10n.createRoomPlaceholderName,
|
||||
placeHolder: "",
|
||||
text: $viewModel.name,
|
||||
footerText: viewModel.viewState.roomNameError,
|
||||
isError: true,
|
||||
configuration: UIKitTextInputConfiguration( returnKeyType: .next))
|
||||
.padding(.horizontal, 2)
|
||||
.padding(.bottom, 20)
|
||||
.disabled(viewModel.viewState.roomProperties?.isNameEditable != true)
|
||||
configuration: UIKitTextInputConfiguration(returnKeyType: .next)
|
||||
)
|
||||
.padding(.horizontal, 2)
|
||||
.padding(.bottom, 20)
|
||||
.disabled(viewModel.viewState.roomProperties?.isNameEditable != true)
|
||||
RoundedBorderTextEditor(
|
||||
title: VectorL10n.spaceTopic,
|
||||
placeHolder: VectorL10n.spaceTopic,
|
||||
text: $viewModel.topic,
|
||||
textMaxHeight: 72,
|
||||
error: nil)
|
||||
.padding(.horizontal, 2)
|
||||
.padding(.bottom, viewModel.viewState.showRoomAddress ? 20 : 3)
|
||||
.disabled(viewModel.viewState.roomProperties?.isTopicEditable != true)
|
||||
error: nil
|
||||
)
|
||||
.padding(.horizontal, 2)
|
||||
.padding(.bottom, viewModel.viewState.showRoomAddress ? 20 : 3)
|
||||
.disabled(viewModel.viewState.roomProperties?.isTopicEditable != true)
|
||||
if viewModel.viewState.showRoomAddress {
|
||||
RoundedBorderTextField(
|
||||
title: VectorL10n.spacesCreationAddress,
|
||||
@@ -137,14 +138,15 @@ struct SpaceSettings: View {
|
||||
text: $viewModel.address,
|
||||
footerText: viewModel.viewState.addressMessage,
|
||||
isError: !viewModel.viewState.isAddressValid,
|
||||
configuration: UIKitTextInputConfiguration(keyboardType: .URL, returnKeyType: .done, autocapitalizationType: .none), onTextChanged: {
|
||||
configuration: UIKitTextInputConfiguration(keyboardType: .URL, returnKeyType: .done, autocapitalizationType: .none), onTextChanged: {
|
||||
newText in
|
||||
viewModel.send(viewAction: .addressChanged(newText))
|
||||
})
|
||||
.disabled(viewModel.viewState.roomProperties?.isAddressEditable != true)
|
||||
.padding(.horizontal, 2)
|
||||
.padding(.bottom, 3)
|
||||
.accessibility(identifier: "addressTextField")
|
||||
}
|
||||
)
|
||||
.disabled(viewModel.viewState.roomProperties?.isAddressEditable != true)
|
||||
.padding(.horizontal, 2)
|
||||
.padding(.bottom, 3)
|
||||
.accessibility(identifier: "addressTextField")
|
||||
}
|
||||
}
|
||||
.padding(.horizontal)
|
||||
@@ -153,7 +155,7 @@ struct SpaceSettings: View {
|
||||
@ViewBuilder
|
||||
private var roomAccess: some View {
|
||||
VStack(alignment: .leading) {
|
||||
Spacer().frame(height:24)
|
||||
Spacer().frame(height: 24)
|
||||
Text(VectorL10n.spaceSettingsAccessSection)
|
||||
.font(theme.fonts.footnote)
|
||||
.foregroundColor(theme.colors.secondaryContent)
|
||||
@@ -161,11 +163,12 @@ struct SpaceSettings: View {
|
||||
.padding(.bottom, 4)
|
||||
SpaceSettingsOptionListItem(
|
||||
title: VectorL10n.roomDetailsAccessRowTitle,
|
||||
value: viewModel.viewState.visibilityString) {
|
||||
value: viewModel.viewState.visibilityString
|
||||
) {
|
||||
ResponderManager.resignFirstResponder()
|
||||
viewModel.send(viewAction: .optionSelected(.visibility))
|
||||
}
|
||||
.disabled(viewModel.viewState.roomProperties?.isAccessEditable != true)
|
||||
.disabled(viewModel.viewState.roomProperties?.isAccessEditable != true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,11 +185,12 @@ struct SpaceSettings: View {
|
||||
SpaceSettingsOptionListItem(
|
||||
icon: option.icon,
|
||||
title: option.title,
|
||||
value: option.value) {
|
||||
value: option.value
|
||||
) {
|
||||
ResponderManager.resignFirstResponder()
|
||||
viewModel.send(viewAction: .optionSelected(option.id))
|
||||
}
|
||||
.disabled(!option.isEnabled)
|
||||
.disabled(!option.isEnabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-4
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// Copyright 2021 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -17,7 +17,6 @@
|
||||
import SwiftUI
|
||||
|
||||
struct SpaceSettingsOptionListItem: View {
|
||||
|
||||
// MARK: Private
|
||||
|
||||
@Environment(\.theme) private var theme: ThemeSwiftUI
|
||||
@@ -85,7 +84,6 @@ struct SpaceSettingsOptionListItem: View {
|
||||
// MARK: - Previews
|
||||
|
||||
struct SpaceSettingsOptionListItem_Previews: PreviewProvider {
|
||||
|
||||
static var previews: some View {
|
||||
sampleView.theme(.light).preferredColorScheme(.light)
|
||||
sampleView.theme(.dark).preferredColorScheme(.dark)
|
||||
@@ -100,5 +98,4 @@ struct SpaceSettingsOptionListItem_Previews: PreviewProvider {
|
||||
.disabled(true)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user