MESSENGER-3671 Merge FOSS 1.9.8

Conflicts:
 - CommonConfiguration.swift
 - BuildSettings.swift
 - Generated/images.Swift
 - RoomMemberDetailsViewController.m
 - LiveLocationSharingViewModell
-  PinCodeEnterViewController.m
This commit is contained in:
Frank Rotermund
2022-10-05 15:47:27 +02:00
744 changed files with 6999 additions and 3819 deletions
@@ -17,11 +17,10 @@
*/
import Foundation
import UIKit
import SwiftUI
import UIKit
final class SpaceCreationSettingsCoordinator: Coordinator, Presentable {
// MARK: - Properties
// MARK: Private
@@ -72,13 +71,12 @@ final class SpaceCreationSettingsCoordinator: Coordinator, Presentable {
self.callback?(.back)
case .pickImage(let sourceRect):
self.pickImage(from: sourceRect)
break
}
}
}
func toPresentable() -> UIViewController {
return self.spaceCreationSettingsHostingController
spaceCreationSettingsHostingController
}
// MARK: - Private
@@ -91,6 +89,7 @@ final class SpaceCreationSettingsCoordinator: Coordinator, Presentable {
}
// MARK: - SingleImagePickerPresenterDelegate
extension SpaceCreationSettingsCoordinator: SingleImagePickerPresenterDelegate {
func singleImagePickerPresenter(_ presenter: SingleImagePickerPresenter, didSelectImageData imageData: Data, withUTI uti: MXKUTI?) {
spaceCreationSettingsViewModel.updateAvatarImage(with: UIImage(data: imageData))
@@ -1,6 +1,6 @@
// 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");
@@ -1,4 +1,4 @@
//
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,4 @@
//
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,29 +0,0 @@
// 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 Foundation
import UIKit
/// Actions to be performed on the `ViewModel` State
enum SpaceCreationSettingsStateAction {
case updateRoomNameError(String?)
case updateRoomDefaultAddress(String)
case updateAddressValidationStatus(SpaceCreationSettingsAddressValidationStatus)
case updateAvatar(AvatarInputProtocol)
case updateAvatarImage(UIImage?)
}
@@ -1,6 +1,6 @@
// 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");
@@ -1,6 +1,6 @@
// 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");
@@ -1,6 +1,6 @@
// 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");
@@ -1,6 +1,6 @@
// 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");
@@ -31,4 +31,3 @@ struct SpaceCreationSettingsViewState: BindableState {
var avatarImage: UIImage?
var bindings: SpaceCreationSettingsViewModelBindings
}
@@ -1,6 +1,6 @@
// 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");
@@ -16,12 +16,11 @@
// limitations under the License.
//
import Foundation
import Combine
import Foundation
import MatrixSDK
class SpaceCreationSettingsService: SpaceCreationSettingsServiceProtocol {
// MARK: - Properties
var roomName: String {
@@ -30,6 +29,7 @@ class SpaceCreationSettingsService: SpaceCreationSettingsServiceProtocol {
updateAvatar()
}
}
var userDefinedAddress: String? {
didSet {
validateAddress()
@@ -45,10 +45,12 @@ class SpaceCreationSettingsService: SpaceCreationSettingsServiceProtocol {
validateAddress()
}
}
private var lastValidatedAddress: String = ""
private var lastValidatedAddress = ""
private var currentAddress: String? {
return self.userDefinedAddress?.count ?? 0 > 0 ? self.userDefinedAddress : defaultAddress
userDefinedAddress?.count ?? 0 > 0 ? userDefinedAddress : defaultAddress
}
private var currentOperation: MXHTTPOperation?
// MARK: Public
@@ -69,14 +71,14 @@ class SpaceCreationSettingsService: SpaceCreationSettingsServiceProtocol {
init(roomName: String, userDefinedAddress: String?, session: MXSession) {
self.session = session
self.defaultAddress = ""
self.defaultAddressSubject = CurrentValueSubject(defaultAddress)
defaultAddress = ""
defaultAddressSubject = CurrentValueSubject(defaultAddress)
self.roomName = roomName
self.addressValidationSubject = CurrentValueSubject(.none("#"))
self.avatarViewDataSubject = CurrentValueSubject(AvatarInput(mxContentUri: userDefinedAddress, matrixItemId: "", displayName: roomName))
addressValidationSubject = CurrentValueSubject(.none("#"))
avatarViewDataSubject = CurrentValueSubject(AvatarInput(mxContentUri: userDefinedAddress, matrixItemId: "", displayName: roomName))
self.updateDefaultAddress()
self.validateAddress()
updateDefaultAddress()
validateAddress()
}
deinit {
@@ -89,7 +91,7 @@ class SpaceCreationSettingsService: SpaceCreationSettingsServiceProtocol {
// MARK: Private
private func updateAvatar() {
self.avatarViewDataSubject.send(AvatarInput(mxContentUri: currentAddress, matrixItemId: "", displayName: roomName))
avatarViewDataSubject.send(AvatarInput(mxContentUri: currentAddress, matrixItemId: "", displayName: roomName))
}
private func updateDefaultAddress() {
@@ -100,7 +102,7 @@ class SpaceCreationSettingsService: SpaceCreationSettingsServiceProtocol {
currentOperation?.cancel()
currentOperation = 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 defaultAddress.isEmpty {
@@ -1,6 +1,6 @@
// 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");
@@ -19,7 +19,6 @@
import Foundation
import SwiftUI
/// Using an enum for the screen allows you define the different state cases with
/// the relevant associated data for each case.
enum MockSpaceCreationSettingsScreenState: MockScreenState, CaseIterable {
@@ -40,7 +39,7 @@ enum MockSpaceCreationSettingsScreenState: MockScreenState, CaseIterable {
let creationParameters = SpaceCreationParameters()
creationParameters.name = "Fake"
let service: MockSpaceCreationSettingsService = MockSpaceCreationSettingsService()
let service = MockSpaceCreationSettingsService()
switch self {
case .privateSpace:
creationParameters.isPublic = false
@@ -60,7 +59,7 @@ enum MockSpaceCreationSettingsScreenState: MockScreenState, CaseIterable {
return (
[service, viewModel],
AnyView(SpaceCreationSettings(viewModel: viewModel.context)
.addDependency(MockAvatarService.example))
.addDependency(MockAvatarService.example))
)
}
}
@@ -1,6 +1,6 @@
// 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");
@@ -16,19 +16,17 @@
// limitations under the License.
//
import Foundation
import Combine
import Foundation
class MockSpaceCreationSettingsService: SpaceCreationSettingsServiceProtocol {
var addressValidationSubject: CurrentValueSubject<SpaceCreationSettingsAddressValidationStatus, Never>
var avatarViewDataSubject: CurrentValueSubject<AvatarInputProtocol, Never>
var defaultAddressSubject: CurrentValueSubject<String, Never>
var spaceAddress: String?
var roomName: String
var userDefinedAddress: String?
var isAddressValid: Bool = true
var isAddressValid = true
init() {
roomName = "Fake"
@@ -38,7 +36,7 @@ class MockSpaceCreationSettingsService: SpaceCreationSettingsServiceProtocol {
}
func simulateUpdate(addressValidationStatus: SpaceCreationSettingsAddressValidationStatus) {
self.addressValidationSubject.value = addressValidationStatus
addressValidationSubject.value = addressValidationStatus
}
// func simulateUpdate()
@@ -1,6 +1,6 @@
// 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");
@@ -16,8 +16,8 @@
// limitations under the License.
//
import Foundation
import Combine
import Foundation
protocol SpaceCreationSettingsServiceProtocol: AnyObject {
var defaultAddressSubject: CurrentValueSubject<String, Never> { get }
@@ -1,6 +1,6 @@
// 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");
@@ -16,8 +16,8 @@
// limitations under the License.
//
import XCTest
import RiotSwiftUI
import XCTest
class SpaceCreationSettingsUITests: MockScreenTestCase {
func testPrivateSpace() {
@@ -1,6 +1,6 @@
// 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");
@@ -16,20 +16,18 @@
// limitations under the License.
//
import XCTest
import Combine
import XCTest
@testable import RiotSwiftUI
class SpaceCreationSettingsViewModelTests: XCTestCase {
let creationParameters = SpaceCreationParameters()
var service: MockSpaceCreationSettingsService!
var viewModel: SpaceCreationSettingsViewModel!
var context: SpaceCreationSettingsViewModel.Context!
var cancellables = Set<AnyCancellable>()
override func setUpWithError() throws {
creationParameters.name = "Fake"
creationParameters.isPublic = true
@@ -16,11 +16,10 @@
// limitations under the License.
//
import SwiftUI
import Combine
import SwiftUI
struct SpaceCreationSettings: View {
// MARK: - Properties
@ObservedObject var viewModel: SpaceCreationSettingsViewModel.Context
@@ -69,8 +68,8 @@ struct SpaceCreationSettings: View {
ZStack(alignment: .bottomTrailing) {
GeometryReader { reader in
ZStack {
SpaceAvatarImage(mxContentUri: viewModel.viewState.avatar.mxContentUri, matrixItemId: viewModel.viewState.avatar.matrixItemId, displayName: viewModel.viewState.avatar.displayName, size: .xxLarge)
.padding(6)
SpaceAvatarImage(mxContentUri: viewModel.viewState.avatar.mxContentUri, matrixItemId: viewModel.viewState.avatar.matrixItemId, displayName: viewModel.viewState.avatar.displayName, size: .xxLarge)
.padding(6)
if let image = viewModel.viewState.avatarImage {
Image(uiImage: image)
.resizable()
@@ -79,10 +78,10 @@ struct SpaceCreationSettings: View {
.clipShape(RoundedRectangle(cornerRadius: 8))
}
}.padding(10)
.gesture(TapGesture().onEnded { _ in
ResponderManager.resignFirstResponder()
viewModel.send(viewAction: .pickImage(reader.frame(in: .global)))
})
.gesture(TapGesture().onEnded { _ in
ResponderManager.resignFirstResponder()
viewModel.send(viewAction: .pickImage(reader.frame(in: .global)))
})
}
Image(uiImage: Asset.Images.spaceCreationCamera.image)
.renderingMode(.template)
@@ -95,21 +94,21 @@ struct SpaceCreationSettings: View {
@ViewBuilder
private var formView: some View {
GeometryReader { geometryReader in
GeometryReader { _ in
ScrollView {
ScrollViewReader { scrollViewReader in
VStack {
headerView
Spacer()
avatarView
Spacer().frame(height:40)
RoundedBorderTextField(title: VectorL10n.createRoomPlaceholderName, placeHolder: "", text: $viewModel.roomName, footerText: viewModel.viewState.roomNameError, isError: true, isFirstResponder: false, configuration: UIKitTextInputConfiguration( returnKeyType: .next), onTextChanged: { newText in
Spacer().frame(height: 40)
RoundedBorderTextField(title: VectorL10n.createRoomPlaceholderName, placeHolder: "", text: $viewModel.roomName, footerText: viewModel.viewState.roomNameError, isError: true, isFirstResponder: false, configuration: UIKitTextInputConfiguration(returnKeyType: .next), onTextChanged: { newText in
viewModel.send(viewAction: .nameChanged(newText))
})
.id("nameTextField")
.padding(.horizontal, 2)
.padding(.bottom, 20)
RoundedBorderTextEditor(title: nil, placeHolder: VectorL10n.spaceTopic, text: $viewModel.topic, textMaxHeight: 72, error: nil, onTextChanged: {
RoundedBorderTextEditor(title: nil, placeHolder: VectorL10n.spaceTopic, text: $viewModel.topic, textMaxHeight: 72, error: nil, onTextChanged: {
newText in
viewModel.send(viewAction: .topicChanged(newText))
}, onEditingChanged: { editing in
@@ -121,7 +120,7 @@ struct SpaceCreationSettings: View {
.padding(.horizontal, 2)
.padding(.bottom, viewModel.viewState.showRoomAddress ? 20 : 3)
if viewModel.viewState.showRoomAddress {
RoundedBorderTextField(title: VectorL10n.spacesCreationAddress, placeHolder: "# \(viewModel.viewState.defaultAddress)", text: $viewModel.address, footerText: viewModel.viewState.addressMessage, isError: !viewModel.viewState.isAddressValid, configuration: UIKitTextInputConfiguration(keyboardType: .URL, returnKeyType: .done, autocapitalizationType: .none), onTextChanged: {
RoundedBorderTextField(title: VectorL10n.spacesCreationAddress, placeHolder: "# \(viewModel.viewState.defaultAddress)", text: $viewModel.address, footerText: viewModel.viewState.addressMessage, isError: !viewModel.viewState.isAddressValid, configuration: UIKitTextInputConfiguration(keyboardType: .URL, returnKeyType: .done, autocapitalizationType: .none), onTextChanged: {
newText in
viewModel.send(viewAction: .addressChanged(newText))
})
@@ -16,15 +16,12 @@
// limitations under the License.
//
import SwiftUI
import Combine
import SwiftUI
typealias SpaceCreationSettingsViewModelType = StateStoreViewModel<SpaceCreationSettingsViewState,
SpaceCreationSettingsStateAction,
SpaceCreationSettingsViewAction>
typealias SpaceCreationSettingsViewModelType = StateStoreViewModel<SpaceCreationSettingsViewState, SpaceCreationSettingsViewAction>
class SpaceCreationSettingsViewModel: SpaceCreationSettingsViewModelType, SpaceCreationSettingsViewModelProtocol {
// MARK: - Properties
// MARK: Private
@@ -47,27 +44,35 @@ class SpaceCreationSettingsViewModel: SpaceCreationSettingsViewModelType, SpaceC
}
private func setupServiceObserving() {
let defaultAddressUpdatePublisher = spaceCreationSettingsService.defaultAddressSubject
.map(SpaceCreationSettingsStateAction.updateRoomDefaultAddress)
.eraseToAnyPublisher()
dispatch(actionPublisher: defaultAddressUpdatePublisher)
spaceCreationSettingsService
.defaultAddressSubject
.sink(receiveValue: { [weak self] address in
self?.state.defaultAddress = address
})
.store(in: &cancellables)
let addressValidationUpdatePublisher = spaceCreationSettingsService.addressValidationSubject
.map(SpaceCreationSettingsStateAction.updateAddressValidationStatus)
.eraseToAnyPublisher()
dispatch(actionPublisher: addressValidationUpdatePublisher)
spaceCreationSettingsService
.addressValidationSubject
.sink(receiveValue: { [weak self] status in
self?.state.addressMessage = status.message
self?.state.isAddressValid = status.isValid
})
.store(in: &cancellables)
let avatarUpdatePublisher = spaceCreationSettingsService.avatarViewDataSubject
.map(SpaceCreationSettingsStateAction.updateAvatar)
.eraseToAnyPublisher()
dispatch(actionPublisher: avatarUpdatePublisher)
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 ?? "")
address: creationParameters.userDefinedAddress ?? ""
)
return SpaceCreationSettingsViewState(
title: creationParameters.isPublic ? VectorL10n.spacesCreationPublicSpaceTitle : VectorL10n.spacesCreationPrivateSpaceTitle,
@@ -78,14 +83,15 @@ class SpaceCreationSettingsViewModel: SpaceCreationSettingsViewModelType, SpaceC
isAddressValid: validationStatus.isValid,
avatar: AvatarInput(mxContentUri: nil, matrixItemId: "", displayName: nil),
avatarImage: creationParameters.userSelectedAvatar,
bindings: bindings)
bindings: bindings
)
}
// MARK: - Public
func updateAvatarImage(with image: UIImage?) {
creationParameters.userSelectedAvatar = image
dispatch(action: .updateAvatarImage(image))
state.avatarImage = image
}
override func process(viewAction: SpaceCreationSettingsViewAction) {
@@ -102,7 +108,7 @@ class SpaceCreationSettingsViewModel: SpaceCreationSettingsViewModelType, SpaceC
spaceCreationSettingsService.roomName = newValue
creationParameters.address = spaceCreationSettingsService.defaultAddressSubject.value
creationParameters.name = newValue
dispatch(action: .updateRoomNameError(newValue.isEmpty ? VectorL10n.spacesCreationEmptyRoomNameError : nil))
state.roomNameError = newValue.isEmpty ? VectorL10n.spacesCreationEmptyRoomNameError : nil
case .addressChanged(let newValue):
spaceCreationSettingsService.userDefinedAddress = newValue
creationParameters.userDefinedAddress = newValue
@@ -110,28 +116,12 @@ class SpaceCreationSettingsViewModel: SpaceCreationSettingsViewModelType, SpaceC
creationParameters.topic = newValue
}
}
override class func reducer(state: inout SpaceCreationSettingsViewState, action: SpaceCreationSettingsStateAction) {
switch action {
case .updateRoomNameError(let error):
state.roomNameError = error
case .updateRoomDefaultAddress(let defaultAddress):
state.defaultAddress = defaultAddress
case .updateAddressValidationStatus(let validationStatus):
state.addressMessage = validationStatus.message
state.isAddressValid = validationStatus.isValid
case .updateAvatar(let avatar):
state.avatar = avatar
case .updateAvatarImage(let image):
state.avatarImage = image
}
}
// MARK: - Private
private func done() {
guard !context.roomName.isEmpty else {
dispatch(action: .updateRoomNameError(VectorL10n.spacesCreationEmptyRoomNameError))
state.roomNameError = VectorL10n.spacesCreationEmptyRoomNameError
return
}
@@ -144,7 +134,7 @@ class SpaceCreationSettingsViewModel: SpaceCreationSettingsViewModelType, SpaceC
creationParameters.userDefinedAddress = context.address
creationParameters.address = spaceCreationSettingsService.defaultAddressSubject.value
dispatch(action: .updateRoomNameError(nil))
state.roomNameError = nil
callback?(.done)
}
@@ -1,6 +1,6 @@
// 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");