diff --git a/.swiftformat b/.swiftformat new file mode 100644 index 000000000..024e43468 --- /dev/null +++ b/.swiftformat @@ -0,0 +1,15 @@ +--swiftversion 5.6 + +--exclude CommonKit, Config, DesignKit, Riot, RiotNSE, RiotShareExtension, RiotTests, SiriIntents, Tools, Variants, vendor + +--disable wrapMultiLineStatementBraces +--disable hoistPatternLet + +--commas inline +--ifdef no-indent +--nospaceoperators ...,..< +--stripunusedargs closure-only +--trimwhitespace nonblank-lines +--wrapparameters after-first +--redundanttype inferred +--emptybraces spaced \ No newline at end of file diff --git a/RiotSwiftUI/Modules/AnalyticsPrompt/AnalyticsPromptModels.swift b/RiotSwiftUI/Modules/AnalyticsPrompt/AnalyticsPromptModels.swift index 6e4e34f30..39f339e87 100644 --- a/RiotSwiftUI/Modules/AnalyticsPrompt/AnalyticsPromptModels.swift +++ b/RiotSwiftUI/Modules/AnalyticsPrompt/AnalyticsPromptModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/AnalyticsPrompt/AnalyticsPromptViewModel.swift b/RiotSwiftUI/Modules/AnalyticsPrompt/AnalyticsPromptViewModel.swift index 3fa94d351..a0ce70a99 100644 --- a/RiotSwiftUI/Modules/AnalyticsPrompt/AnalyticsPromptViewModel.swift +++ b/RiotSwiftUI/Modules/AnalyticsPrompt/AnalyticsPromptViewModel.swift @@ -14,14 +14,13 @@ // limitations under the License. // -import SwiftUI import Combine +import SwiftUI typealias AnalyticsPromptViewModelType = StateStoreViewModel + Never, + AnalyticsPromptViewAction> class AnalyticsPromptViewModel: AnalyticsPromptViewModelType { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/AnalyticsPrompt/Coordinator/AnalyticsPromptCoordinator.swift b/RiotSwiftUI/Modules/AnalyticsPrompt/Coordinator/AnalyticsPromptCoordinator.swift index c41749369..fb79b8df8 100644 --- a/RiotSwiftUI/Modules/AnalyticsPrompt/Coordinator/AnalyticsPromptCoordinator.swift +++ b/RiotSwiftUI/Modules/AnalyticsPrompt/Coordinator/AnalyticsPromptCoordinator.swift @@ -22,17 +22,16 @@ struct AnalyticsPromptCoordinatorParameters { } final class AnalyticsPromptCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private private let parameters: AnalyticsPromptCoordinatorParameters private let analyticsPromptHostingController: UIViewController - private var _analyticsPromptViewModel: Any? = nil + private var _analyticsPromptViewModel: Any? fileprivate var analyticsPromptViewModel: AnalyticsPromptViewModel { - return _analyticsPromptViewModel as! AnalyticsPromptViewModel + _analyticsPromptViewModel as! AnalyticsPromptViewModel } // MARK: Public @@ -84,6 +83,6 @@ final class AnalyticsPromptCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.analyticsPromptHostingController + analyticsPromptHostingController } } diff --git a/RiotSwiftUI/Modules/AnalyticsPrompt/Coordinator/AnalyticsPromptStrings.swift b/RiotSwiftUI/Modules/AnalyticsPrompt/Coordinator/AnalyticsPromptStrings.swift index 9ada08435..0d5d844c8 100644 --- a/RiotSwiftUI/Modules/AnalyticsPrompt/Coordinator/AnalyticsPromptStrings.swift +++ b/RiotSwiftUI/Modules/AnalyticsPrompt/Coordinator/AnalyticsPromptStrings.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,4 +25,3 @@ struct AnalyticsPromptStrings: AnalyticsPromptStringsProtocol { withAllowedTags: ["b", "p"], font: UIFont.systemFont(ofSize: UIFont.systemFontSize)) } - diff --git a/RiotSwiftUI/Modules/AnalyticsPrompt/MockAnalyticsPromptScreenState.swift b/RiotSwiftUI/Modules/AnalyticsPrompt/MockAnalyticsPromptScreenState.swift index 290a88836..7d222aa31 100644 --- a/RiotSwiftUI/Modules/AnalyticsPrompt/MockAnalyticsPromptScreenState.swift +++ b/RiotSwiftUI/Modules/AnalyticsPrompt/MockAnalyticsPromptScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/AnalyticsPrompt/MockAnalyticsPromptStrings.swift b/RiotSwiftUI/Modules/AnalyticsPrompt/MockAnalyticsPromptStrings.swift index 37a38e32d..2fd7c0018 100644 --- a/RiotSwiftUI/Modules/AnalyticsPrompt/MockAnalyticsPromptStrings.swift +++ b/RiotSwiftUI/Modules/AnalyticsPrompt/MockAnalyticsPromptStrings.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/AnalyticsPrompt/Test/UI/AnalyticsPromptUITests.swift b/RiotSwiftUI/Modules/AnalyticsPrompt/Test/UI/AnalyticsPromptUITests.swift index 2013f0866..46eed139c 100644 --- a/RiotSwiftUI/Modules/AnalyticsPrompt/Test/UI/AnalyticsPromptUITests.swift +++ b/RiotSwiftUI/Modules/AnalyticsPrompt/Test/UI/AnalyticsPromptUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class AnalyticsPromptUITests: MockScreenTestCase { /// Verify that the prompt is displayed correctly for new users. diff --git a/RiotSwiftUI/Modules/AnalyticsPrompt/View/AnalyticsPrompt.swift b/RiotSwiftUI/Modules/AnalyticsPrompt/View/AnalyticsPrompt.swift index 16cbeb989..a400af7aa 100644 --- a/RiotSwiftUI/Modules/AnalyticsPrompt/View/AnalyticsPrompt.swift +++ b/RiotSwiftUI/Modules/AnalyticsPrompt/View/AnalyticsPrompt.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import SwiftUI /// A prompt that asks the user whether they would like to enable Analytics or not. struct AnalyticsPrompt: View { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/AnalyticsPrompt/View/AnalyticsPromptCheckmarkItem.swift b/RiotSwiftUI/Modules/AnalyticsPrompt/View/AnalyticsPromptCheckmarkItem.swift index cec25f2d7..1ec120069 100644 --- a/RiotSwiftUI/Modules/AnalyticsPrompt/View/AnalyticsPromptCheckmarkItem.swift +++ b/RiotSwiftUI/Modules/AnalyticsPrompt/View/AnalyticsPromptCheckmarkItem.swift @@ -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 AnalyticsPromptCheckmarkItem: View { - // MARK: - Properties // MARK: Private @@ -40,7 +39,7 @@ struct AnalyticsPromptCheckmarkItem: View { let range = NSRange(location: 0, length: attributedString.length) let string = attributedString.string as NSString - attributedString.enumerateAttributes(in: range, options: []) { attributes, range, stop in + attributedString.enumerateAttributes(in: range, options: []) { attributes, range, _ in var isBold = false if let font = attributes[.font] as? UIFont { @@ -54,7 +53,7 @@ struct AnalyticsPromptCheckmarkItem: View { } init(string: String) { - self.components = [StringComponent(string: string, isBold: false)] + components = [StringComponent(string: string, isBold: false)] } // MARK: - Views @@ -75,11 +74,10 @@ struct AnalyticsPromptCheckmarkItem: View { // MARK: - Previews struct AnalyticsPromptCheckmarkItem_Previews: PreviewProvider { - static let strings = MockAnalyticsPromptStrings() static var previews: some View { - VStack(alignment:.leading) { + VStack(alignment: .leading) { AnalyticsPromptCheckmarkItem(attributedString: strings.point1) AnalyticsPromptCheckmarkItem(attributedString: strings.point2) AnalyticsPromptCheckmarkItem(attributedString: strings.longString) diff --git a/RiotSwiftUI/Modules/Authentication/ChoosePassword/AuthenticationChoosePasswordModels.swift b/RiotSwiftUI/Modules/Authentication/ChoosePassword/AuthenticationChoosePasswordModels.swift index 6c8230b18..838767317 100644 --- a/RiotSwiftUI/Modules/Authentication/ChoosePassword/AuthenticationChoosePasswordModels.swift +++ b/RiotSwiftUI/Modules/Authentication/ChoosePassword/AuthenticationChoosePasswordModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Authentication/ChoosePassword/AuthenticationChoosePasswordViewModel.swift b/RiotSwiftUI/Modules/Authentication/ChoosePassword/AuthenticationChoosePasswordViewModel.swift index 89f418a07..fb6fc88e2 100644 --- a/RiotSwiftUI/Modules/Authentication/ChoosePassword/AuthenticationChoosePasswordViewModel.swift +++ b/RiotSwiftUI/Modules/Authentication/ChoosePassword/AuthenticationChoosePasswordViewModel.swift @@ -17,10 +17,9 @@ import SwiftUI typealias AuthenticationChoosePasswordViewModelType = StateStoreViewModel + Never, + AuthenticationChoosePasswordViewAction> class AuthenticationChoosePasswordViewModel: AuthenticationChoosePasswordViewModelType, AuthenticationChoosePasswordViewModelProtocol { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Authentication/ChoosePassword/AuthenticationChoosePasswordViewModelProtocol.swift b/RiotSwiftUI/Modules/Authentication/ChoosePassword/AuthenticationChoosePasswordViewModelProtocol.swift index 47c57304e..46a148ec4 100644 --- a/RiotSwiftUI/Modules/Authentication/ChoosePassword/AuthenticationChoosePasswordViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Authentication/ChoosePassword/AuthenticationChoosePasswordViewModelProtocol.swift @@ -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 AuthenticationChoosePasswordViewModelProtocol { - var callback: (@MainActor (AuthenticationChoosePasswordViewModelResult) -> Void)? { get set } var context: AuthenticationChoosePasswordViewModelType.Context { get } diff --git a/RiotSwiftUI/Modules/Authentication/ChoosePassword/Coordinator/AuthenticationChoosePasswordCoordinator.swift b/RiotSwiftUI/Modules/Authentication/ChoosePassword/Coordinator/AuthenticationChoosePasswordCoordinator.swift index 9d02e4000..df3f7d793 100644 --- a/RiotSwiftUI/Modules/Authentication/ChoosePassword/Coordinator/AuthenticationChoosePasswordCoordinator.swift +++ b/RiotSwiftUI/Modules/Authentication/ChoosePassword/Coordinator/AuthenticationChoosePasswordCoordinator.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import SwiftUI import CommonKit +import SwiftUI struct AuthenticationChoosePasswordCoordinatorParameters { let loginWizard: LoginWizard @@ -29,7 +29,6 @@ enum AuthenticationChoosePasswordCoordinatorResult { } final class AuthenticationChoosePasswordCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -79,7 +78,7 @@ final class AuthenticationChoosePasswordCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.authenticationChoosePasswordHostingController + authenticationChoosePasswordHostingController } // MARK: - Private diff --git a/RiotSwiftUI/Modules/Authentication/ChoosePassword/MockAuthenticationChoosePasswordScreenState.swift b/RiotSwiftUI/Modules/Authentication/ChoosePassword/MockAuthenticationChoosePasswordScreenState.swift index c18b1398a..afe021fbc 100644 --- a/RiotSwiftUI/Modules/Authentication/ChoosePassword/MockAuthenticationChoosePasswordScreenState.swift +++ b/RiotSwiftUI/Modules/Authentication/ChoosePassword/MockAuthenticationChoosePasswordScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,7 +34,7 @@ enum MockAuthenticationChoosePasswordScreenState: MockScreenState, CaseIterable } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let viewModel: AuthenticationChoosePasswordViewModel switch self { case .emptyPassword: diff --git a/RiotSwiftUI/Modules/Authentication/ChoosePassword/Test/UI/AuthenticationChoosePasswordUITests.swift b/RiotSwiftUI/Modules/Authentication/ChoosePassword/Test/UI/AuthenticationChoosePasswordUITests.swift index d1fffa0fb..2d6539e1f 100644 --- a/RiotSwiftUI/Modules/Authentication/ChoosePassword/Test/UI/AuthenticationChoosePasswordUITests.swift +++ b/RiotSwiftUI/Modules/Authentication/ChoosePassword/Test/UI/AuthenticationChoosePasswordUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class AuthenticationChoosePasswordUITests: MockScreenTestCase { func testEmptyPassword() { @@ -93,7 +93,6 @@ class AuthenticationChoosePasswordUITests: MockScreenTestCase { XCTAssertTrue(signoutAllDevicesToggle.exists, "Sign out all devices toggle should exist") XCTAssertTrue(signoutAllDevicesToggle.isOn, "Sign out all devices should be checked") } - } extension XCUIElement { diff --git a/RiotSwiftUI/Modules/Authentication/ChoosePassword/Test/Unit/AuthenticationChoosePasswordViewModelTests.swift b/RiotSwiftUI/Modules/Authentication/ChoosePassword/Test/Unit/AuthenticationChoosePasswordViewModelTests.swift index ac9219ea1..34d236e09 100644 --- a/RiotSwiftUI/Modules/Authentication/ChoosePassword/Test/Unit/AuthenticationChoosePasswordViewModelTests.swift +++ b/RiotSwiftUI/Modules/Authentication/ChoosePassword/Test/Unit/AuthenticationChoosePasswordViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ import XCTest @testable import RiotSwiftUI class AuthenticationChoosePasswordViewModelTests: XCTestCase { - @MainActor func testInitialState() async { let viewModel = AuthenticationChoosePasswordViewModel() let context = viewModel.context @@ -29,5 +28,4 @@ class AuthenticationChoosePasswordViewModelTests: XCTestCase { XCTAssert(context.viewState.hasInvalidPassword, "The view model should start with an invalid password.") XCTAssertFalse(context.signoutAllDevices, "The view model should start with sign out of all devices unchecked.") } - } diff --git a/RiotSwiftUI/Modules/Authentication/ChoosePassword/View/AuthenticationChoosePasswordScreen.swift b/RiotSwiftUI/Modules/Authentication/ChoosePassword/View/AuthenticationChoosePasswordScreen.swift index ff76409d6..704ca6a36 100644 --- a/RiotSwiftUI/Modules/Authentication/ChoosePassword/View/AuthenticationChoosePasswordScreen.swift +++ b/RiotSwiftUI/Modules/Authentication/ChoosePassword/View/AuthenticationChoosePasswordScreen.swift @@ -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 AuthenticationChoosePasswordScreen: View { - // MARK: - Properties // MARK: Private @@ -100,7 +99,7 @@ struct AuthenticationChoosePasswordScreen: View { configuration: UIKitTextInputConfiguration(returnKeyType: .done, isSecureTextEntry: true), onCommit: submit) - .accessibilityIdentifier("passwordTextField") + .accessibilityIdentifier("passwordTextField") } /// Sends the `send` view action so long as a valid email address has been input. diff --git a/RiotSwiftUI/Modules/Authentication/Common/AuthenticationHomeserverViewData.swift b/RiotSwiftUI/Modules/Authentication/Common/AuthenticationHomeserverViewData.swift index c5fdf1bb4..7952e7db3 100644 --- a/RiotSwiftUI/Modules/Authentication/Common/AuthenticationHomeserverViewData.swift +++ b/RiotSwiftUI/Modules/Authentication/Common/AuthenticationHomeserverViewData.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,11 +37,11 @@ extension AuthenticationHomeserverViewData { showLoginForm: true, showRegistrationForm: true, ssoIdentityProviders: [ - SSOIdentityProvider(id: "1", name: "Apple", brand: "apple", iconURL: nil), - SSOIdentityProvider(id: "2", name: "Facebook", brand: "facebook", iconURL: nil), - SSOIdentityProvider(id: "3", name: "GitHub", brand: "github", iconURL: nil), - SSOIdentityProvider(id: "4", name: "GitLab", brand: "gitlab", iconURL: nil), - SSOIdentityProvider(id: "5", name: "Google", brand: "google", iconURL: nil) + SSOIdentityProvider(id: "1", name: "Apple", brand: "apple", iconURL: nil), + SSOIdentityProvider(id: "2", name: "Facebook", brand: "facebook", iconURL: nil), + SSOIdentityProvider(id: "3", name: "GitHub", brand: "github", iconURL: nil), + SSOIdentityProvider(id: "4", name: "GitLab", brand: "gitlab", iconURL: nil), + SSOIdentityProvider(id: "5", name: "Google", brand: "google", iconURL: nil) ]) } @@ -68,5 +68,4 @@ extension AuthenticationHomeserverViewData { showRegistrationForm: false, ssoIdentityProviders: []) } - } diff --git a/RiotSwiftUI/Modules/Authentication/Common/AuthenticationModels.swift b/RiotSwiftUI/Modules/Authentication/Common/AuthenticationModels.swift index 1e78da544..e59aa0189 100644 --- a/RiotSwiftUI/Modules/Authentication/Common/AuthenticationModels.swift +++ b/RiotSwiftUI/Modules/Authentication/Common/AuthenticationModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -78,7 +78,7 @@ enum LoginError: String, Error { case resetPasswordNotStarted } -@objcMembers +@objcMembers class HomeserverAddress: NSObject { /// Sanitizes a user entered homeserver address with the following rules /// - Trim any whitespace. diff --git a/RiotSwiftUI/Modules/Authentication/Common/AuthenticationSSOButton.swift b/RiotSwiftUI/Modules/Authentication/Common/AuthenticationSSOButton.swift index 767ed7d18..6f440d943 100644 --- a/RiotSwiftUI/Modules/Authentication/Common/AuthenticationSSOButton.swift +++ b/RiotSwiftUI/Modules/Authentication/Common/AuthenticationSSOButton.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import SwiftUI /// A button that displays the icon and name of an SSO provider. struct AuthenticationSSOButton: View { - // MARK: - Constants enum Brand: String { diff --git a/RiotSwiftUI/Modules/Authentication/Common/AuthenticationServerInfoSection.swift b/RiotSwiftUI/Modules/Authentication/Common/AuthenticationServerInfoSection.swift index edfc703c4..ea62c52c6 100644 --- a/RiotSwiftUI/Modules/Authentication/Common/AuthenticationServerInfoSection.swift +++ b/RiotSwiftUI/Modules/Authentication/Common/AuthenticationServerInfoSection.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ import SwiftUI /// A view that shows information about the chosen homeserver, /// along with an edit button to pick a different one. struct AuthenticationServerInfoSection: View { - // MARK: - Private @Environment(\.theme) private var theme diff --git a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/AuthenticationPendingData.swift b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/AuthenticationPendingData.swift index 2aa4bc499..6f637d5b9 100644 --- a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/AuthenticationPendingData.swift +++ b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/AuthenticationPendingData.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/AuthenticationRestClient.swift b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/AuthenticationRestClient.swift index 058ac3d18..33d20f17b 100644 --- a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/AuthenticationRestClient.swift +++ b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/AuthenticationRestClient.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +18,7 @@ import Foundation protocol AuthenticationRestClient: AnyObject { // MARK: Configuration + var homeserver: String! { get } var identityServer: String! { get set } var credentials: MXCredentials! { get } @@ -26,24 +27,27 @@ protocol AuthenticationRestClient: AnyObject { init(homeServer: URL, unrecognizedCertificateHandler handler: MXHTTPClientOnUnrecognizedCertificate?) // MARK: Login + var loginFallbackURL: URL { get } func wellKnown() async throws -> MXWellKnown func getLoginSession() async throws -> MXAuthenticationSession func login(parameters: LoginParameters) async throws -> MXCredentials - func login(parameters: [String : Any]) async throws -> MXCredentials + func login(parameters: [String: Any]) async throws -> MXCredentials // MARK: Registration + var registerFallbackURL: URL { get } func getRegisterSession() async throws -> MXAuthenticationSession func isUsernameAvailable(_ username: String) async throws -> Bool func register(parameters: RegistrationParameters) async throws -> MXLoginResponse - func register(parameters: [String : Any]) async throws -> MXLoginResponse + func register(parameters: [String: Any]) async throws -> MXLoginResponse func requestTokenDuringRegistration(for threePID: RegisterThreePID, clientSecret: String, sendAttempt: UInt) async throws -> RegistrationThreePIDTokenResponse // MARK: Forgot Password + func forgetPassword(for email: String, clientSecret: String, sendAttempt: UInt) async throws -> String func resetPassword(parameters: CheckResetPasswordParameters) async throws - func resetPassword(parameters: [String : Any]) async throws + func resetPassword(parameters: [String: Any]) async throws } extension MXRestClient: AuthenticationRestClient { } diff --git a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/AuthenticationService.swift b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/AuthenticationService.swift index eff30724c..492d39834 100644 --- a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/AuthenticationService.swift +++ b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/AuthenticationService.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,7 +39,6 @@ protocol AuthenticationServiceDelegate: AnyObject { @objcMembers class AuthenticationService: NSObject { - /// The shared service object. static let shared = AuthenticationService() @@ -97,7 +96,7 @@ class AuthenticationService: NSObject { let hsUrl = universalLink.homeserverUrl let isUrl = universalLink.identityServerUrl - if hsUrl == nil && isUrl == nil { + if hsUrl == nil, isUrl == nil { MXLog.debug("[AuthenticationService] handleServerProvisioningLink: no hsUrl or isUrl") return false } @@ -166,7 +165,7 @@ class AuthenticationService: NSObject { // The state and client are set after trying the registration flow to // ensure the existing state isn't wiped out when an error occurs. - self.state = AuthenticationState(flow: flow, homeserver: homeserver) + state = AuthenticationState(flow: flow, homeserver: homeserver) self.client = client } @@ -200,9 +199,9 @@ class AuthenticationService: NSObject { // completeness revert to the default homeserver if requested anyway. let address = useDefaultServer ? BuildSettings.serverConfigDefaultHomeserverUrlString : state.homeserver.addressFromUser ?? state.homeserver.address let identityServer = state.identityServer - self.state = AuthenticationState(flow: .login, - homeserverAddress: address, - identityServer: identityServer) + state = AuthenticationState(flow: .login, + homeserverAddress: address, + identityServer: identityServer) } /// Continues an SSO flow when completion comes via a deep link. @@ -289,7 +288,7 @@ class AuthenticationService: NSObject { let identityProviders = loginFlowResponse.flows?.compactMap { $0 as? MXLoginSSOFlow }.first?.identityProviders ?? [] return LoginFlowResult(supportedLoginTypes: loginFlowResponse.flows?.compactMap { $0 } ?? [], - ssoIdentityProviders: identityProviders.sorted { $0.name < $1.name }.map { $0.ssoIdentityProvider }, + ssoIdentityProviders: identityProviders.sorted { $0.name < $1.name }.map(\.ssoIdentityProvider), homeserverAddress: client.homeserver) } diff --git a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/AuthenticationState.swift b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/AuthenticationState.swift index cac59552f..e2a48e315 100644 --- a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/AuthenticationState.swift +++ b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/AuthenticationState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,7 +29,7 @@ struct AuthenticationState { init(flow: AuthenticationFlow, homeserverAddress: String, identityServer: String? = nil) { self.flow = flow - self.homeserver = Homeserver(address: homeserverAddress) + homeserver = Homeserver(address: homeserverAddress) self.identityServer = identityServer } @@ -72,7 +72,7 @@ struct AuthenticationState { /// Needs authentication fallback for login var needsLoginFallback: Bool { - return preferredLoginMode.isUnsupported + preferredLoginMode.isUnsupported } /// Needs authentication fallback for registration diff --git a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/LoginModels.swift b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/LoginModels.swift index c3332146c..90c12f503 100644 --- a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/LoginModels.swift +++ b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/LoginModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -93,4 +93,3 @@ enum LoginMode { struct ResetPasswordData { let addThreePIDSessionID: String } - diff --git a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/LoginParameters.swift b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/LoginParameters.swift index 4e4bacb15..6146b3999 100644 --- a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/LoginParameters.swift +++ b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/LoginParameters.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -110,7 +110,7 @@ struct CheckResetPasswordParameters: DictionaryEncodable { } init(clientSecret: String, sessionID: String, newPassword: String, signoutAllDevices: Bool) { - self.auth = AuthenticationParameters.resetPasswordParameters(clientSecret: clientSecret, sessionID: sessionID) + auth = AuthenticationParameters.resetPasswordParameters(clientSecret: clientSecret, sessionID: sessionID) self.newPassword = newPassword self.signoutAllDevices = signoutAllDevices } diff --git a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/LoginWizard.swift b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/LoginWizard.swift index ae759b058..f31902506 100644 --- a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/LoginWizard.swift +++ b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/LoginWizard.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -40,7 +40,7 @@ class LoginWizard { self.client = client self.sessionCreator = sessionCreator - self.state = State() + state = State() } /// Login to the homeserver. diff --git a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/RegistrationModels.swift b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/RegistrationModels.swift index af3ffbf78..590941353 100644 --- a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/RegistrationModels.swift +++ b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/RegistrationModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -114,7 +114,7 @@ struct FlowResult { } /// Whether fallback registration should be used due to unsupported stages. - var needsFallback : Bool { + var needsFallback: Bool { missingStages.filter(\.isMandatory).contains { stage in if case .other = stage { return true } else { return false } } diff --git a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/RegistrationParameters.swift b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/RegistrationParameters.swift index d4a1416e9..cdc336e30 100644 --- a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/RegistrationParameters.swift +++ b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/RegistrationParameters.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/RegistrationWizard.swift b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/RegistrationWizard.swift index 2a2a0989b..76b470ef9 100644 --- a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/RegistrationWizard.swift +++ b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/RegistrationWizard.swift @@ -63,7 +63,7 @@ class RegistrationWizard { self.client = client self.sessionCreator = sessionCreator - self.state = State() + state = State() } /// Call this method to get the possible registration flow of the current homeserver. @@ -164,7 +164,7 @@ class RegistrationWizard { /// Send the code received by SMS to validate a msisdn. /// If the code is correct, the registration request will be executed to validate the msisdn. func handleValidateThreePID(code: String) async throws -> RegistrationResult { - return try await validateThreePid(code: code) + try await validateThreePid(code: code) } /// Useful to poll the homeserver when waiting for the email to be validated by the user. @@ -197,7 +197,6 @@ class RegistrationWizard { throw RegistrationError.missingThreePIDURL } - let validationBody = ThreePIDValidationCodeBody(clientSecret: state.clientSecret, sessionID: threePIDData.registrationResponse.sessionID, code: code) @@ -278,7 +277,7 @@ class RegistrationWizard { /// Checks for a dummy stage and handles it automatically when possible. private func handleDummyStage(flowResult: FlowResult) async throws -> RegistrationResult { // If the dummy stage is mandatory, do the dummy stage now - guard flowResult.missingStages.contains(where: { $0.isDummy }) else { return .flowResponse(flowResult) } + guard flowResult.missingStages.contains(where: \.isDummy) else { return .flowResponse(flowResult) } return try await dummy() } diff --git a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/SessionCreator.swift b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/SessionCreator.swift index 955f13fed..78d183924 100644 --- a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/SessionCreator.swift +++ b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/SessionCreator.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,7 +29,6 @@ protocol SessionCreatorProtocol { /// A struct that provides common functionality to create a new session. struct SessionCreator: SessionCreatorProtocol { - private let accountManager: MXKAccountManager init(withAccountManager accountManager: MXKAccountManager = .shared()) { @@ -44,7 +43,7 @@ struct SessionCreator: SessionCreatorProtocol { } if removeOtherAccounts { - let otherAccounts = accountManager.accounts.filter({ $0.mxCredentials.userId != credentials.userId }) + let otherAccounts = accountManager.accounts.filter { $0.mxCredentials.userId != credentials.userId } for account in otherAccounts { accountManager.removeAccount(account, completion: nil) } diff --git a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/ThreePIDModels.swift b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/ThreePIDModels.swift index 478cbf9f2..852f6a60a 100644 --- a/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/ThreePIDModels.swift +++ b/RiotSwiftUI/Modules/Authentication/Common/Service/MatrixSDK/ThreePIDModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -53,13 +53,13 @@ struct RegistrationThreePIDTokenResponse { /// /// If this field is not present, the client can assume that verification will happen without the client's involvement provided /// the homeserver advertises this specification version in the /versions response (ie: r0.5.0). - var submitURL: String? = nil + var submitURL: String? // MARK: - Additional data that may be needed - var msisdn: String? = nil - var formattedMSISDN: String? = nil - var success: Bool? = nil + var msisdn: String? + var formattedMSISDN: String? + var success: Bool? enum CodingKeys: String, CodingKey { case sessionID = "sid" diff --git a/RiotSwiftUI/Modules/Authentication/ForgotPassword/AuthenticationForgotPasswordModels.swift b/RiotSwiftUI/Modules/Authentication/ForgotPassword/AuthenticationForgotPasswordModels.swift index 788a33552..6d5f60a30 100644 --- a/RiotSwiftUI/Modules/Authentication/ForgotPassword/AuthenticationForgotPasswordModels.swift +++ b/RiotSwiftUI/Modules/Authentication/ForgotPassword/AuthenticationForgotPasswordModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Authentication/ForgotPassword/AuthenticationForgotPasswordViewModel.swift b/RiotSwiftUI/Modules/Authentication/ForgotPassword/AuthenticationForgotPasswordViewModel.swift index 461e064a6..fdc17d6c7 100644 --- a/RiotSwiftUI/Modules/Authentication/ForgotPassword/AuthenticationForgotPasswordViewModel.swift +++ b/RiotSwiftUI/Modules/Authentication/ForgotPassword/AuthenticationForgotPasswordViewModel.swift @@ -17,10 +17,9 @@ import SwiftUI typealias AuthenticationForgotPasswordViewModelType = StateStoreViewModel + Never, + AuthenticationForgotPasswordViewAction> class AuthenticationForgotPasswordViewModel: AuthenticationForgotPasswordViewModelType, AuthenticationForgotPasswordViewModelProtocol { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Authentication/ForgotPassword/AuthenticationForgotPasswordViewModelProtocol.swift b/RiotSwiftUI/Modules/Authentication/ForgotPassword/AuthenticationForgotPasswordViewModelProtocol.swift index 673138290..baffd45d1 100644 --- a/RiotSwiftUI/Modules/Authentication/ForgotPassword/AuthenticationForgotPasswordViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Authentication/ForgotPassword/AuthenticationForgotPasswordViewModelProtocol.swift @@ -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 AuthenticationForgotPasswordViewModelProtocol { - var callback: (@MainActor (AuthenticationForgotPasswordViewModelResult) -> Void)? { get set } var context: AuthenticationForgotPasswordViewModelType.Context { get } diff --git a/RiotSwiftUI/Modules/Authentication/ForgotPassword/Coordinator/AuthenticationForgotPasswordCoordinator.swift b/RiotSwiftUI/Modules/Authentication/ForgotPassword/Coordinator/AuthenticationForgotPasswordCoordinator.swift index 3f19180cf..deea1e803 100644 --- a/RiotSwiftUI/Modules/Authentication/ForgotPassword/Coordinator/AuthenticationForgotPasswordCoordinator.swift +++ b/RiotSwiftUI/Modules/Authentication/ForgotPassword/Coordinator/AuthenticationForgotPasswordCoordinator.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import SwiftUI import CommonKit +import SwiftUI struct AuthenticationForgotPasswordCoordinatorParameters { let navigationRouter: NavigationRouterType @@ -32,7 +32,6 @@ enum AuthenticationForgotPasswordCoordinatorResult { } final class AuthenticationForgotPasswordCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -83,7 +82,7 @@ final class AuthenticationForgotPasswordCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.authenticationForgotPasswordHostingController + authenticationForgotPasswordHostingController } // MARK: - Private diff --git a/RiotSwiftUI/Modules/Authentication/ForgotPassword/MockAuthenticationForgotPasswordScreenState.swift b/RiotSwiftUI/Modules/Authentication/ForgotPassword/MockAuthenticationForgotPasswordScreenState.swift index 1d126e998..e69cbee41 100644 --- a/RiotSwiftUI/Modules/Authentication/ForgotPassword/MockAuthenticationForgotPasswordScreenState.swift +++ b/RiotSwiftUI/Modules/Authentication/ForgotPassword/MockAuthenticationForgotPasswordScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,7 +33,7 @@ enum MockAuthenticationForgotPasswordScreenState: MockScreenState, CaseIterable } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let viewModel: AuthenticationForgotPasswordViewModel switch self { case .emptyAddress: diff --git a/RiotSwiftUI/Modules/Authentication/ForgotPassword/Test/UI/AuthenticationForgotPasswordUITests.swift b/RiotSwiftUI/Modules/Authentication/ForgotPassword/Test/UI/AuthenticationForgotPasswordUITests.swift index 06478ce2a..f633349a2 100644 --- a/RiotSwiftUI/Modules/Authentication/ForgotPassword/Test/UI/AuthenticationForgotPasswordUITests.swift +++ b/RiotSwiftUI/Modules/Authentication/ForgotPassword/Test/UI/AuthenticationForgotPasswordUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class AuthenticationForgotPasswordUITests: MockScreenTestCase { func testEmptyAddress() { @@ -98,5 +98,4 @@ class AuthenticationForgotPasswordUITests: MockScreenTestCase { XCTAssertTrue(backButton.exists, "Back button should be shown.") XCTAssertEqual(backButton.label, "Back") } - } diff --git a/RiotSwiftUI/Modules/Authentication/ForgotPassword/Test/Unit/AuthenticationForgotPasswordViewModelTests.swift b/RiotSwiftUI/Modules/Authentication/ForgotPassword/Test/Unit/AuthenticationForgotPasswordViewModelTests.swift index c05dfccaa..925370625 100644 --- a/RiotSwiftUI/Modules/Authentication/ForgotPassword/Test/Unit/AuthenticationForgotPasswordViewModelTests.swift +++ b/RiotSwiftUI/Modules/Authentication/ForgotPassword/Test/Unit/AuthenticationForgotPasswordViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ import XCTest @testable import RiotSwiftUI class AuthenticationForgotPasswordViewModelTests: XCTestCase { - var viewModel: AuthenticationForgotPasswordViewModelProtocol! var context: AuthenticationForgotPasswordViewModelType.Context! diff --git a/RiotSwiftUI/Modules/Authentication/ForgotPassword/View/AuthenticationForgotPasswordForm.swift b/RiotSwiftUI/Modules/Authentication/ForgotPassword/View/AuthenticationForgotPasswordForm.swift index 9c19f94fb..815831159 100644 --- a/RiotSwiftUI/Modules/Authentication/ForgotPassword/View/AuthenticationForgotPasswordForm.swift +++ b/RiotSwiftUI/Modules/Authentication/ForgotPassword/View/AuthenticationForgotPasswordForm.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import SwiftUI /// The form shown to enter an email address. struct AuthenticationForgotPasswordForm: View { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Authentication/ForgotPassword/View/AuthenticationForgotPasswordScreen.swift b/RiotSwiftUI/Modules/Authentication/ForgotPassword/View/AuthenticationForgotPasswordScreen.swift index a2a6619e1..423f4d8b6 100644 --- a/RiotSwiftUI/Modules/Authentication/ForgotPassword/View/AuthenticationForgotPasswordScreen.swift +++ b/RiotSwiftUI/Modules/Authentication/ForgotPassword/View/AuthenticationForgotPasswordScreen.swift @@ -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 AuthenticationForgotPasswordScreen: View { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Authentication/Login/AuthenticationLoginModels.swift b/RiotSwiftUI/Modules/Authentication/Login/AuthenticationLoginModels.swift index 823a56499..e273d0d16 100644 --- a/RiotSwiftUI/Modules/Authentication/Login/AuthenticationLoginModels.swift +++ b/RiotSwiftUI/Modules/Authentication/Login/AuthenticationLoginModels.swift @@ -57,7 +57,7 @@ struct AuthenticationLoginViewState: BindableState { /// Data about the selected homeserver. var homeserver: AuthenticationHomeserverViewData /// Whether a new homeserver is currently being loaded. - var isLoading: Bool = false + var isLoading = false /// View state that can be bound to from SwiftUI. var bindings: AuthenticationLoginBindings diff --git a/RiotSwiftUI/Modules/Authentication/Login/AuthenticationLoginViewModel.swift b/RiotSwiftUI/Modules/Authentication/Login/AuthenticationLoginViewModel.swift index aa73f0586..d7d528a10 100644 --- a/RiotSwiftUI/Modules/Authentication/Login/AuthenticationLoginViewModel.swift +++ b/RiotSwiftUI/Modules/Authentication/Login/AuthenticationLoginViewModel.swift @@ -17,11 +17,10 @@ import SwiftUI typealias AuthenticationLoginViewModelType = StateStoreViewModel + Never, + AuthenticationLoginViewAction> class AuthenticationLoginViewModel: AuthenticationLoginViewModelType, AuthenticationLoginViewModelProtocol { - // MARK: - Properties // MARK: Public @@ -52,7 +51,7 @@ class AuthenticationLoginViewModel: AuthenticationLoginViewModelType, Authentica case .fallback: Task { await callback?(.fallback) } case .continueWithSSO(let provider): - Task { await callback?(.continueWithSSO(provider))} + Task { await callback?(.continueWithSSO(provider)) } } } diff --git a/RiotSwiftUI/Modules/Authentication/Login/AuthenticationLoginViewModelProtocol.swift b/RiotSwiftUI/Modules/Authentication/Login/AuthenticationLoginViewModelProtocol.swift index afe9d3a92..87ef46fce 100644 --- a/RiotSwiftUI/Modules/Authentication/Login/AuthenticationLoginViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Authentication/Login/AuthenticationLoginViewModelProtocol.swift @@ -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 AuthenticationLoginViewModelProtocol { - var callback: (@MainActor (AuthenticationLoginViewModelResult) -> Void)? { get set } var context: AuthenticationLoginViewModelType.Context { get } diff --git a/RiotSwiftUI/Modules/Authentication/Login/Coordinator/AuthenticationLoginCoordinator.swift b/RiotSwiftUI/Modules/Authentication/Login/Coordinator/AuthenticationLoginCoordinator.swift index 080917097..596e1cad7 100644 --- a/RiotSwiftUI/Modules/Authentication/Login/Coordinator/AuthenticationLoginCoordinator.swift +++ b/RiotSwiftUI/Modules/Authentication/Login/Coordinator/AuthenticationLoginCoordinator.swift @@ -14,9 +14,9 @@ // limitations under the License. // -import SwiftUI import CommonKit import MatrixSDK +import SwiftUI struct AuthenticationLoginCoordinatorParameters { let navigationRouter: NavigationRouterType @@ -47,7 +47,6 @@ enum AuthenticationLoginCoordinatorResult: CustomStringConvertible { } final class AuthenticationLoginCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -96,6 +95,7 @@ final class AuthenticationLoginCoordinator: Coordinator, Presentable { } // MARK: - Public + func start() { MXLog.debug("[AuthenticationLoginCoordinator] did start.") Task { await setupViewModel() } diff --git a/RiotSwiftUI/Modules/Authentication/Login/MockAuthenticationLoginScreenState.swift b/RiotSwiftUI/Modules/Authentication/Login/MockAuthenticationLoginScreenState.swift index 1e242c7e1..09ffa9ce6 100644 --- a/RiotSwiftUI/Modules/Authentication/Login/MockAuthenticationLoginScreenState.swift +++ b/RiotSwiftUI/Modules/Authentication/Login/MockAuthenticationLoginScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,7 +35,7 @@ enum MockAuthenticationLoginScreenState: MockScreenState, CaseIterable { } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let viewModel: AuthenticationLoginViewModel switch self { case .matrixDotOrg: @@ -52,7 +52,6 @@ enum MockAuthenticationLoginScreenState: MockScreenState, CaseIterable { viewModel = AuthenticationLoginViewModel(homeserver: .mockFallback) } - // can simulate service and viewModel actions here if needs be. return ( diff --git a/RiotSwiftUI/Modules/Authentication/Login/Test/UI/AuthenticationLoginUITests.swift b/RiotSwiftUI/Modules/Authentication/Login/Test/UI/AuthenticationLoginUITests.swift index 8dcf6eb63..8075ccc9f 100644 --- a/RiotSwiftUI/Modules/Authentication/Login/Test/UI/AuthenticationLoginUITests.swift +++ b/RiotSwiftUI/Modules/Authentication/Login/Test/UI/AuthenticationLoginUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class AuthenticationLoginUITests: MockScreenTestCase { func testMatrixDotOrg() { @@ -120,5 +120,4 @@ class AuthenticationLoginUITests: MockScreenTestCase { XCTAssertTrue(fallbackButton.exists, "The fallback button should be shown for \(state).") XCTAssertTrue(fallbackButton.isEnabled, "The fallback button should be enabled for \(state).") } - } diff --git a/RiotSwiftUI/Modules/Authentication/Login/Test/Unit/AuthenticationLoginViewModelTests.swift b/RiotSwiftUI/Modules/Authentication/Login/Test/Unit/AuthenticationLoginViewModelTests.swift index dde66c2fb..ae9b3b7ec 100644 --- a/RiotSwiftUI/Modules/Authentication/Login/Test/Unit/AuthenticationLoginViewModelTests.swift +++ b/RiotSwiftUI/Modules/Authentication/Login/Test/Unit/AuthenticationLoginViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Authentication/Login/View/AuthenticationLoginScreen.swift b/RiotSwiftUI/Modules/Authentication/Login/View/AuthenticationLoginScreen.swift index 8e4a5776f..3ff67aaf2 100644 --- a/RiotSwiftUI/Modules/Authentication/Login/View/AuthenticationLoginScreen.swift +++ b/RiotSwiftUI/Modules/Authentication/Login/View/AuthenticationLoginScreen.swift @@ -17,7 +17,6 @@ import SwiftUI struct AuthenticationLoginScreen: View { - // MARK: - Properties // MARK: Private @@ -52,7 +51,7 @@ struct AuthenticationLoginScreen: View { loginForm } - if viewModel.viewState.homeserver.showLoginForm && viewModel.viewState.showSSOButtons { + if viewModel.viewState.homeserver.showLoginForm, viewModel.viewState.showSSOButtons { Text(VectorL10n.or) .foregroundColor(theme.colors.secondaryContent) .padding(.top, 16) @@ -63,10 +62,9 @@ struct AuthenticationLoginScreen: View { .padding(.top, 16) } - if !viewModel.viewState.homeserver.showLoginForm && !viewModel.viewState.showSSOButtons { + if !viewModel.viewState.homeserver.showLoginForm, !viewModel.viewState.showSSOButtons { fallbackButton } - } .readableFrame() .padding(.horizontal, 16) @@ -104,8 +102,8 @@ struct AuthenticationLoginScreen: View { autocorrectionType: .no), onEditingChanged: usernameEditingChanged, onCommit: { isPasswordFocused = true }) - .accessibilityIdentifier("usernameTextField") - .padding(.bottom, 7) + .accessibilityIdentifier("usernameTextField") + .padding(.bottom, 7) RoundedBorderTextField(placeHolder: VectorL10n.authPasswordPlaceholder, text: $viewModel.password, @@ -114,7 +112,7 @@ struct AuthenticationLoginScreen: View { isSecureTextEntry: true), onEditingChanged: passwordEditingChanged, onCommit: submit) - .accessibilityIdentifier("passwordTextField") + .accessibilityIdentifier("passwordTextField") Button { viewModel.send(viewAction: .forgotPassword) } label: { Text(VectorL10n.authenticationLoginForgotPassword) diff --git a/RiotSwiftUI/Modules/Authentication/ReCaptcha/AuthenticationReCaptchaModels.swift b/RiotSwiftUI/Modules/Authentication/ReCaptcha/AuthenticationReCaptchaModels.swift index 27b95d713..7c0f90bc5 100644 --- a/RiotSwiftUI/Modules/Authentication/ReCaptcha/AuthenticationReCaptchaModels.swift +++ b/RiotSwiftUI/Modules/Authentication/ReCaptcha/AuthenticationReCaptchaModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Authentication/ReCaptcha/AuthenticationReCaptchaViewModel.swift b/RiotSwiftUI/Modules/Authentication/ReCaptcha/AuthenticationReCaptchaViewModel.swift index 08a733d93..873f278ba 100644 --- a/RiotSwiftUI/Modules/Authentication/ReCaptcha/AuthenticationReCaptchaViewModel.swift +++ b/RiotSwiftUI/Modules/Authentication/ReCaptcha/AuthenticationReCaptchaViewModel.swift @@ -17,11 +17,10 @@ import SwiftUI typealias AuthenticationReCaptchaViewModelType = StateStoreViewModel + Never, + AuthenticationReCaptchaViewAction> class AuthenticationReCaptchaViewModel: AuthenticationReCaptchaViewModelType, AuthenticationReCaptchaViewModelProtocol { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Authentication/ReCaptcha/AuthenticationReCaptchaViewModelProtocol.swift b/RiotSwiftUI/Modules/Authentication/ReCaptcha/AuthenticationReCaptchaViewModelProtocol.swift index d29a25f13..097af6e9c 100644 --- a/RiotSwiftUI/Modules/Authentication/ReCaptcha/AuthenticationReCaptchaViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Authentication/ReCaptcha/AuthenticationReCaptchaViewModelProtocol.swift @@ -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 AuthenticationReCaptchaViewModelProtocol { - var callback: (@MainActor (AuthenticationReCaptchaViewModelResult) -> Void)? { get set } var context: AuthenticationReCaptchaViewModelType.Context { get } diff --git a/RiotSwiftUI/Modules/Authentication/ReCaptcha/Coordinator/AuthenticationReCaptchaCoordinator.swift b/RiotSwiftUI/Modules/Authentication/ReCaptcha/Coordinator/AuthenticationReCaptchaCoordinator.swift index 356beb6cb..efeafb184 100644 --- a/RiotSwiftUI/Modules/Authentication/ReCaptcha/Coordinator/AuthenticationReCaptchaCoordinator.swift +++ b/RiotSwiftUI/Modules/Authentication/ReCaptcha/Coordinator/AuthenticationReCaptchaCoordinator.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import SwiftUI import CommonKit +import SwiftUI struct AuthenticationReCaptchaCoordinatorParameters { let registrationWizard: RegistrationWizard @@ -26,7 +26,6 @@ struct AuthenticationReCaptchaCoordinatorParameters { } final class AuthenticationReCaptchaCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -76,7 +75,7 @@ final class AuthenticationReCaptchaCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.authenticationReCaptchaHostingController + authenticationReCaptchaHostingController } // MARK: - Private diff --git a/RiotSwiftUI/Modules/Authentication/ReCaptcha/MockAuthenticationReCaptchaScreenState.swift b/RiotSwiftUI/Modules/Authentication/ReCaptcha/MockAuthenticationReCaptchaScreenState.swift index 057ce257f..d96456d0f 100644 --- a/RiotSwiftUI/Modules/Authentication/ReCaptcha/MockAuthenticationReCaptchaScreenState.swift +++ b/RiotSwiftUI/Modules/Authentication/ReCaptcha/MockAuthenticationReCaptchaScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,7 +31,7 @@ enum MockAuthenticationReCaptchaScreenState: MockScreenState, CaseIterable { } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let viewModel: AuthenticationReCaptchaViewModel switch self { case .standard: diff --git a/RiotSwiftUI/Modules/Authentication/ReCaptcha/Test/UI/AuthenticationReCaptchaUITests.swift b/RiotSwiftUI/Modules/Authentication/ReCaptcha/Test/UI/AuthenticationReCaptchaUITests.swift index ac8ff628c..450d5bfe1 100644 --- a/RiotSwiftUI/Modules/Authentication/ReCaptcha/Test/UI/AuthenticationReCaptchaUITests.swift +++ b/RiotSwiftUI/Modules/Authentication/ReCaptcha/Test/UI/AuthenticationReCaptchaUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class AuthenticationReCaptchaUITests: MockScreenTestCase { // Nothing to test as the view only has a single state. diff --git a/RiotSwiftUI/Modules/Authentication/ReCaptcha/Test/Unit/AuthenticationReCaptchaViewModelTests.swift b/RiotSwiftUI/Modules/Authentication/ReCaptcha/Test/Unit/AuthenticationReCaptchaViewModelTests.swift index 1d8d15b37..37d76e135 100644 --- a/RiotSwiftUI/Modules/Authentication/ReCaptcha/Test/Unit/AuthenticationReCaptchaViewModelTests.swift +++ b/RiotSwiftUI/Modules/Authentication/ReCaptcha/Test/Unit/AuthenticationReCaptchaViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Authentication/ReCaptcha/View/AuthenticationReCaptchaScreen.swift b/RiotSwiftUI/Modules/Authentication/ReCaptcha/View/AuthenticationReCaptchaScreen.swift index 41dd2d896..16dc70bf9 100644 --- a/RiotSwiftUI/Modules/Authentication/ReCaptcha/View/AuthenticationReCaptchaScreen.swift +++ b/RiotSwiftUI/Modules/Authentication/ReCaptcha/View/AuthenticationReCaptchaScreen.swift @@ -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 AuthenticationReCaptchaScreen: View { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Authentication/ReCaptcha/View/AuthenticationReCaptchaWebView.swift b/RiotSwiftUI/Modules/Authentication/ReCaptcha/View/AuthenticationReCaptchaWebView.swift index fbd000cb5..06e7ff784 100644 --- a/RiotSwiftUI/Modules/Authentication/ReCaptcha/View/AuthenticationReCaptchaWebView.swift +++ b/RiotSwiftUI/Modules/Authentication/ReCaptcha/View/AuthenticationReCaptchaWebView.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import SwiftUI import WebKit struct AuthenticationRecaptchaWebView: UIViewRepresentable { - // MARK: - Properties // MARK: Public @@ -84,7 +83,7 @@ struct AuthenticationRecaptchaWebView: UIViewRepresentable { var completion: ((String) -> Void)? init(isLoading: Binding) { - self._isLoading = isLoading + _isLoading = isLoading } /// Generates the HTML page to show for the given `siteKey` and `theme`. @@ -134,4 +133,3 @@ struct AuthenticationRecaptchaWebView: UIViewRepresentable { } } } - diff --git a/RiotSwiftUI/Modules/Authentication/Registration/AuthenticationRegistrationModels.swift b/RiotSwiftUI/Modules/Authentication/Registration/AuthenticationRegistrationModels.swift index 1652a3978..830edf3fc 100644 --- a/RiotSwiftUI/Modules/Authentication/Registration/AuthenticationRegistrationModels.swift +++ b/RiotSwiftUI/Modules/Authentication/Registration/AuthenticationRegistrationModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -62,7 +62,7 @@ struct AuthenticationRegistrationViewState: BindableState { /// Data about the selected homeserver. var homeserver: AuthenticationHomeserverViewData /// Whether a new homeserver is currently being loaded. - var isLoading: Bool = false + var isLoading = false /// View state that can be bound to from SwiftUI. var bindings: AuthenticationRegistrationBindings /// Whether or not the username field has been edited yet. diff --git a/RiotSwiftUI/Modules/Authentication/Registration/AuthenticationRegistrationViewModel.swift b/RiotSwiftUI/Modules/Authentication/Registration/AuthenticationRegistrationViewModel.swift index 9b2e1d699..f792adb12 100644 --- a/RiotSwiftUI/Modules/Authentication/Registration/AuthenticationRegistrationViewModel.swift +++ b/RiotSwiftUI/Modules/Authentication/Registration/AuthenticationRegistrationViewModel.swift @@ -14,15 +14,14 @@ // limitations under the License. // -import SwiftUI import Combine +import SwiftUI typealias AuthenticationRegistrationViewModelType = StateStoreViewModel + Never, + AuthenticationRegistrationViewAction> class AuthenticationRegistrationViewModel: AuthenticationRegistrationViewModelType, AuthenticationRegistrationViewModelProtocol { - // MARK: - Properties // MARK: Public diff --git a/RiotSwiftUI/Modules/Authentication/Registration/AuthenticationRegistrationViewModelProtocol.swift b/RiotSwiftUI/Modules/Authentication/Registration/AuthenticationRegistrationViewModelProtocol.swift index 036f720e7..96468ba56 100644 --- a/RiotSwiftUI/Modules/Authentication/Registration/AuthenticationRegistrationViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Authentication/Registration/AuthenticationRegistrationViewModelProtocol.swift @@ -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 AuthenticationRegistrationViewModelProtocol { - var callback: (@MainActor (AuthenticationRegistrationViewModelResult) -> Void)? { get set } var context: AuthenticationRegistrationViewModelType.Context { get } diff --git a/RiotSwiftUI/Modules/Authentication/Registration/Coordinator/AuthenticationRegistrationCoordinator.swift b/RiotSwiftUI/Modules/Authentication/Registration/Coordinator/AuthenticationRegistrationCoordinator.swift index f749aa32b..72fa8f441 100644 --- a/RiotSwiftUI/Modules/Authentication/Registration/Coordinator/AuthenticationRegistrationCoordinator.swift +++ b/RiotSwiftUI/Modules/Authentication/Registration/Coordinator/AuthenticationRegistrationCoordinator.swift @@ -14,9 +14,9 @@ // limitations under the License. // -import SwiftUI import CommonKit import MatrixSDK +import SwiftUI struct AuthenticationRegistrationCoordinatorParameters { let navigationRouter: NavigationRouterType @@ -49,7 +49,6 @@ enum AuthenticationRegistrationCoordinatorResult: CustomStringConvertible { } final class AuthenticationRegistrationCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -97,13 +96,14 @@ final class AuthenticationRegistrationCoordinator: Coordinator, Presentable { } // MARK: - Public + func start() { MXLog.debug("[AuthenticationRegistrationCoordinator] did start.") Task { await setupViewModel() } } func toPresentable() -> UIViewController { - return self.authenticationRegistrationHostingController + authenticationRegistrationHostingController } // MARK: - Private @@ -117,7 +117,7 @@ final class AuthenticationRegistrationCoordinator: Coordinator, Presentable { switch result { case .selectServer: self.presentServerSelectionScreen() - case.validateUsername(let username): + case .validateUsername(let username): self.validateUsername(username) case .createAccount(let username, let password): self.createAccount(username: username, password: password) diff --git a/RiotSwiftUI/Modules/Authentication/Registration/MockAuthenticationRegistrationScreenState.swift b/RiotSwiftUI/Modules/Authentication/Registration/MockAuthenticationRegistrationScreenState.swift index a85021a17..d3086def6 100644 --- a/RiotSwiftUI/Modules/Authentication/Registration/MockAuthenticationRegistrationScreenState.swift +++ b/RiotSwiftUI/Modules/Authentication/Registration/MockAuthenticationRegistrationScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,7 +36,7 @@ enum MockAuthenticationRegistrationScreenState: MockScreenState, CaseIterable { } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let viewModel: AuthenticationRegistrationViewModel switch self { case .matrixDotOrg: @@ -58,7 +58,6 @@ enum MockAuthenticationRegistrationScreenState: MockScreenState, CaseIterable { viewModel = AuthenticationRegistrationViewModel(homeserver: .mockFallback) } - // can simulate service and viewModel actions here if needs be. return ( diff --git a/RiotSwiftUI/Modules/Authentication/Registration/Test/UI/AuthenticationRegistrationUITests.swift b/RiotSwiftUI/Modules/Authentication/Registration/Test/UI/AuthenticationRegistrationUITests.swift index 223d20c40..d49ecd580 100644 --- a/RiotSwiftUI/Modules/Authentication/Registration/Test/UI/AuthenticationRegistrationUITests.swift +++ b/RiotSwiftUI/Modules/Authentication/Registration/Test/UI/AuthenticationRegistrationUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class AuthenticationRegistrationUITests: MockScreenTestCase { func testMatrixDotOrg() { @@ -88,7 +88,6 @@ class AuthenticationRegistrationUITests: MockScreenTestCase { validateFallbackButtonIsShown(for: state) } - /// Checks that the username and password text fields are shown along with the next button. func validateRegistrationFormIsVisible(for state: String) { let usernameTextField = app.textFields.element diff --git a/RiotSwiftUI/Modules/Authentication/Registration/Test/Unit/AuthenticationRegistrationViewModelTests.swift b/RiotSwiftUI/Modules/Authentication/Registration/Test/Unit/AuthenticationRegistrationViewModelTests.swift index 2d5f3830f..734c174f9 100644 --- a/RiotSwiftUI/Modules/Authentication/Registration/Test/Unit/AuthenticationRegistrationViewModelTests.swift +++ b/RiotSwiftUI/Modules/Authentication/Registration/Test/Unit/AuthenticationRegistrationViewModelTests.swift @@ -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 @@ -110,7 +110,7 @@ import Combine XCTAssertEqual(context.viewState.usernameFooterMessage, VectorL10n.authenticationRegistrationUsernameFooterAvailable("@bob:matrix.org"), "The footer message should display that the username is available.") XCTAssertFalse(context.viewState.isUsernameInvalid, - "The username should continue to be valid when it is available.") + "The username should continue to be valid when it is available.") // When clearing the error. context.send(viewAction: .resetUsernameAvailability) @@ -190,7 +190,7 @@ import Combine // Then the username should be valid but the credentials should still be invalid. XCTAssertTrue(context.viewState.isPasswordInvalid, "An empty password should be invalid.") - XCTAssertFalse(context.viewState.isUsernameInvalid, "The username should be valid when unverified.") + XCTAssertFalse(context.viewState.isUsernameInvalid, "The username should be valid when unverified.") XCTAssertFalse(context.viewState.hasValidCredentials, "The credentials should be invalid.") } diff --git a/RiotSwiftUI/Modules/Authentication/Registration/View/AuthenticationRegistrationScreen.swift b/RiotSwiftUI/Modules/Authentication/Registration/View/AuthenticationRegistrationScreen.swift index 4f62560b3..c333f047a 100644 --- a/RiotSwiftUI/Modules/Authentication/Registration/View/AuthenticationRegistrationScreen.swift +++ b/RiotSwiftUI/Modules/Authentication/Registration/View/AuthenticationRegistrationScreen.swift @@ -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 AuthenticationRegistrationScreen: View { - // MARK: - Properties // MARK: Private @@ -50,7 +49,7 @@ struct AuthenticationRegistrationScreen: View { registrationForm } - if viewModel.viewState.homeserver.showRegistrationForm && viewModel.viewState.showSSOButtons { + if viewModel.viewState.homeserver.showRegistrationForm, viewModel.viewState.showSSOButtons { Text(VectorL10n.or) .foregroundColor(theme.colors.secondaryContent) .padding(.top, 16) @@ -61,10 +60,9 @@ struct AuthenticationRegistrationScreen: View { .padding(.top, 16) } - if !viewModel.viewState.homeserver.showRegistrationForm && !viewModel.viewState.showSSOButtons { + if !viewModel.viewState.homeserver.showRegistrationForm, !viewModel.viewState.showSSOButtons { fallbackButton } - } .readableFrame() .padding(.horizontal, 16) @@ -110,8 +108,8 @@ struct AuthenticationRegistrationScreen: View { autocorrectionType: .no), onEditingChanged: usernameEditingChanged, onCommit: { isPasswordFocused = true }) - .onChange(of: viewModel.username) { _ in viewModel.send(viewAction: .resetUsernameAvailability) } - .accessibilityIdentifier("usernameTextField") + .onChange(of: viewModel.username) { _ in viewModel.send(viewAction: .resetUsernameAvailability) } + .accessibilityIdentifier("usernameTextField") RoundedBorderTextField(title: nil, placeHolder: VectorL10n.authPasswordPlaceholder, @@ -123,7 +121,7 @@ struct AuthenticationRegistrationScreen: View { isSecureTextEntry: true), onEditingChanged: passwordEditingChanged, onCommit: submit) - .accessibilityIdentifier("passwordTextField") + .accessibilityIdentifier("passwordTextField") Button(action: submit) { Text(VectorL10n.next) diff --git a/RiotSwiftUI/Modules/Authentication/ServerSelection/AuthenticationServerSelectionModels.swift b/RiotSwiftUI/Modules/Authentication/ServerSelection/AuthenticationServerSelectionModels.swift index 8f4a07f62..c94df50ca 100644 --- a/RiotSwiftUI/Modules/Authentication/ServerSelection/AuthenticationServerSelectionModels.swift +++ b/RiotSwiftUI/Modules/Authentication/ServerSelection/AuthenticationServerSelectionModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Authentication/ServerSelection/AuthenticationServerSelectionViewModel.swift b/RiotSwiftUI/Modules/Authentication/ServerSelection/AuthenticationServerSelectionViewModel.swift index 8a5326593..fdcc726b5 100644 --- a/RiotSwiftUI/Modules/Authentication/ServerSelection/AuthenticationServerSelectionViewModel.swift +++ b/RiotSwiftUI/Modules/Authentication/ServerSelection/AuthenticationServerSelectionViewModel.swift @@ -17,11 +17,10 @@ import SwiftUI typealias AuthenticationServerSelectionViewModelType = StateStoreViewModel + Never, + AuthenticationServerSelectionViewAction> class AuthenticationServerSelectionViewModel: AuthenticationServerSelectionViewModelType, AuthenticationServerSelectionViewModelProtocol { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Authentication/ServerSelection/AuthenticationServerSelectionViewModelProtocol.swift b/RiotSwiftUI/Modules/Authentication/ServerSelection/AuthenticationServerSelectionViewModelProtocol.swift index e57a2d86e..a4e8abe4a 100644 --- a/RiotSwiftUI/Modules/Authentication/ServerSelection/AuthenticationServerSelectionViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Authentication/ServerSelection/AuthenticationServerSelectionViewModelProtocol.swift @@ -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 AuthenticationServerSelectionViewModelProtocol { - var callback: (@MainActor (AuthenticationServerSelectionViewModelResult) -> Void)? { get set } var context: AuthenticationServerSelectionViewModelType.Context { get } diff --git a/RiotSwiftUI/Modules/Authentication/ServerSelection/Coordinator/AuthenticationServerSelectionCoordinator.swift b/RiotSwiftUI/Modules/Authentication/ServerSelection/Coordinator/AuthenticationServerSelectionCoordinator.swift index 0f3888146..c5d521701 100644 --- a/RiotSwiftUI/Modules/Authentication/ServerSelection/Coordinator/AuthenticationServerSelectionCoordinator.swift +++ b/RiotSwiftUI/Modules/Authentication/ServerSelection/Coordinator/AuthenticationServerSelectionCoordinator.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import SwiftUI import CommonKit +import SwiftUI struct AuthenticationServerSelectionCoordinatorParameters { let authenticationService: AuthenticationService @@ -31,7 +31,6 @@ enum AuthenticationServerSelectionCoordinatorResult { } final class AuthenticationServerSelectionCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -78,7 +77,7 @@ final class AuthenticationServerSelectionCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.authenticationServerSelectionHostingController + authenticationServerSelectionHostingController } // MARK: - Private diff --git a/RiotSwiftUI/Modules/Authentication/ServerSelection/MockAuthenticationServerSelectionScreenState.swift b/RiotSwiftUI/Modules/Authentication/ServerSelection/MockAuthenticationServerSelectionScreenState.swift index c7e2f12c7..baf8faf53 100644 --- a/RiotSwiftUI/Modules/Authentication/ServerSelection/MockAuthenticationServerSelectionScreenState.swift +++ b/RiotSwiftUI/Modules/Authentication/ServerSelection/MockAuthenticationServerSelectionScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,7 +35,7 @@ enum MockAuthenticationServerSelectionScreenState: MockScreenState, CaseIterable } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let viewModel: AuthenticationServerSelectionViewModel switch self { case .matrix: diff --git a/RiotSwiftUI/Modules/Authentication/ServerSelection/Test/UI/AuthenticationServerSelectionUITests.swift b/RiotSwiftUI/Modules/Authentication/ServerSelection/Test/UI/AuthenticationServerSelectionUITests.swift index e72e00ec4..1bdcd6698 100644 --- a/RiotSwiftUI/Modules/Authentication/ServerSelection/Test/UI/AuthenticationServerSelectionUITests.swift +++ b/RiotSwiftUI/Modules/Authentication/ServerSelection/Test/UI/AuthenticationServerSelectionUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class AuthenticationServerSelectionUITests: MockScreenTestCase { func testRegisterState() { @@ -41,7 +41,6 @@ class AuthenticationServerSelectionUITests: MockScreenTestCase { XCTAssertTrue(dismissButton.exists, "The dismiss button should be shown during modal presentation.") } - func testLoginState() { app.goToScreenWithIdentifier(MockAuthenticationServerSelectionScreenState.login.title) diff --git a/RiotSwiftUI/Modules/Authentication/ServerSelection/Test/Unit/AuthenticationServerSelectionViewModelTests.swift b/RiotSwiftUI/Modules/Authentication/ServerSelection/Test/Unit/AuthenticationServerSelectionViewModelTests.swift index ed75e67aa..ab62bf4aa 100644 --- a/RiotSwiftUI/Modules/Authentication/ServerSelection/Test/Unit/AuthenticationServerSelectionViewModelTests.swift +++ b/RiotSwiftUI/Modules/Authentication/ServerSelection/Test/Unit/AuthenticationServerSelectionViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Authentication/ServerSelection/View/AuthenticationServerSelectionScreen.swift b/RiotSwiftUI/Modules/Authentication/ServerSelection/View/AuthenticationServerSelectionScreen.swift index 687d6ec92..54144006b 100644 --- a/RiotSwiftUI/Modules/Authentication/ServerSelection/View/AuthenticationServerSelectionScreen.swift +++ b/RiotSwiftUI/Modules/Authentication/ServerSelection/View/AuthenticationServerSelectionScreen.swift @@ -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 AuthenticationServerSelectionScreen: View { - // MARK: - Properties // MARK: Private @@ -37,7 +36,7 @@ struct AuthenticationServerSelectionScreen: View { // MARK: Views var body: some View { - GeometryReader { geometry in + GeometryReader { _ in ScrollView { VStack(spacing: 0) { header diff --git a/RiotSwiftUI/Modules/Authentication/SoftLogout/AuthenticationSoftLogoutModels.swift b/RiotSwiftUI/Modules/Authentication/SoftLogout/AuthenticationSoftLogoutModels.swift index 7222af762..c6bb92d12 100644 --- a/RiotSwiftUI/Modules/Authentication/SoftLogout/AuthenticationSoftLogoutModels.swift +++ b/RiotSwiftUI/Modules/Authentication/SoftLogout/AuthenticationSoftLogoutModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,6 +17,7 @@ import SwiftUI // MARK: Data + struct SoftLogoutCredentials { let userId: String let homeserverName: String diff --git a/RiotSwiftUI/Modules/Authentication/SoftLogout/AuthenticationSoftLogoutViewModel.swift b/RiotSwiftUI/Modules/Authentication/SoftLogout/AuthenticationSoftLogoutViewModel.swift index bd9fcee28..a984ac375 100644 --- a/RiotSwiftUI/Modules/Authentication/SoftLogout/AuthenticationSoftLogoutViewModel.swift +++ b/RiotSwiftUI/Modules/Authentication/SoftLogout/AuthenticationSoftLogoutViewModel.swift @@ -17,10 +17,9 @@ import SwiftUI typealias AuthenticationSoftLogoutViewModelType = StateStoreViewModel + Never, + AuthenticationSoftLogoutViewAction> class AuthenticationSoftLogoutViewModel: AuthenticationSoftLogoutViewModelType, AuthenticationSoftLogoutViewModelProtocol { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Authentication/SoftLogout/AuthenticationSoftLogoutViewModelProtocol.swift b/RiotSwiftUI/Modules/Authentication/SoftLogout/AuthenticationSoftLogoutViewModelProtocol.swift index f4e948f5b..45f700d41 100644 --- a/RiotSwiftUI/Modules/Authentication/SoftLogout/AuthenticationSoftLogoutViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Authentication/SoftLogout/AuthenticationSoftLogoutViewModelProtocol.swift @@ -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 AuthenticationSoftLogoutViewModelProtocol { - var callback: (@MainActor (AuthenticationSoftLogoutViewModelResult) -> Void)? { get set } var context: AuthenticationSoftLogoutViewModelType.Context { get } diff --git a/RiotSwiftUI/Modules/Authentication/SoftLogout/Coordinator/AuthenticationSoftLogoutCoordinator.swift b/RiotSwiftUI/Modules/Authentication/SoftLogout/Coordinator/AuthenticationSoftLogoutCoordinator.swift index 5b2fba433..a76ce9a0b 100644 --- a/RiotSwiftUI/Modules/Authentication/SoftLogout/Coordinator/AuthenticationSoftLogoutCoordinator.swift +++ b/RiotSwiftUI/Modules/Authentication/SoftLogout/Coordinator/AuthenticationSoftLogoutCoordinator.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import SwiftUI import CommonKit +import SwiftUI struct AuthenticationSoftLogoutCoordinatorParameters { let navigationRouter: NavigationRouterType @@ -50,7 +50,6 @@ enum AuthenticationSoftLogoutCoordinatorResult: CustomStringConvertible { } final class AuthenticationSoftLogoutCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -107,7 +106,7 @@ final class AuthenticationSoftLogoutCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.authenticationSoftLogoutHostingController + authenticationSoftLogoutHostingController } // MARK: - Private diff --git a/RiotSwiftUI/Modules/Authentication/SoftLogout/MockAuthenticationSoftLogoutScreenState.swift b/RiotSwiftUI/Modules/Authentication/SoftLogout/MockAuthenticationSoftLogoutScreenState.swift index 8efa80d67..8127665d5 100644 --- a/RiotSwiftUI/Modules/Authentication/SoftLogout/MockAuthenticationSoftLogoutScreenState.swift +++ b/RiotSwiftUI/Modules/Authentication/SoftLogout/MockAuthenticationSoftLogoutScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,7 +36,7 @@ enum MockAuthenticationSoftLogoutScreenState: MockScreenState, CaseIterable { } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let viewModel: AuthenticationSoftLogoutViewModel let credentials = SoftLogoutCredentials(userId: "@mock:matrix.org", homeserverName: "matrix.org", diff --git a/RiotSwiftUI/Modules/Authentication/SoftLogout/Test/UI/AuthenticationSoftLogoutUITests.swift b/RiotSwiftUI/Modules/Authentication/SoftLogout/Test/UI/AuthenticationSoftLogoutUITests.swift index 52268610a..4487fee04 100644 --- a/RiotSwiftUI/Modules/Authentication/SoftLogout/Test/UI/AuthenticationSoftLogoutUITests.swift +++ b/RiotSwiftUI/Modules/Authentication/SoftLogout/Test/UI/AuthenticationSoftLogoutUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class AuthenticationSoftLogoutUITests: MockScreenTestCase { func testEmptyPassword() { @@ -185,5 +185,4 @@ class AuthenticationSoftLogoutUITests: MockScreenTestCase { XCTAssertFalse(app.staticTexts["messageLabel2"].exists, "The message 2 should not be shown.") } - } diff --git a/RiotSwiftUI/Modules/Authentication/SoftLogout/Test/Unit/AuthenticationSoftLogoutViewModelTests.swift b/RiotSwiftUI/Modules/Authentication/SoftLogout/Test/Unit/AuthenticationSoftLogoutViewModelTests.swift index 4d9c8142c..bacaf8638 100644 --- a/RiotSwiftUI/Modules/Authentication/SoftLogout/Test/Unit/AuthenticationSoftLogoutViewModelTests.swift +++ b/RiotSwiftUI/Modules/Authentication/SoftLogout/Test/Unit/AuthenticationSoftLogoutViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ import XCTest @testable import RiotSwiftUI class AuthenticationSoftLogoutViewModelTests: XCTestCase { - @MainActor func testInitialStateForMatrixOrg() async { let credentials = SoftLogoutCredentials(userId: "mock_user_id", homeserverName: "https://matrix.org", @@ -55,5 +54,4 @@ class AuthenticationSoftLogoutViewModelTests: XCTestCase { XCTAssert(context.viewState.showLoginForm, "The view model should show login form for the given homeserver.") XCTAssertFalse(context.viewState.showRecoverEncryptionKeysMessage, "The view model should not show recover encryption keys message.") } - } diff --git a/RiotSwiftUI/Modules/Authentication/SoftLogout/View/AuthenticationSoftLogoutScreen.swift b/RiotSwiftUI/Modules/Authentication/SoftLogout/View/AuthenticationSoftLogoutScreen.swift index b7d20d88b..ced206e1c 100644 --- a/RiotSwiftUI/Modules/Authentication/SoftLogout/View/AuthenticationSoftLogoutScreen.swift +++ b/RiotSwiftUI/Modules/Authentication/SoftLogout/View/AuthenticationSoftLogoutScreen.swift @@ -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 AuthenticationSoftLogoutScreen: View { - // MARK: - Properties // MARK: Private @@ -153,7 +152,7 @@ struct AuthenticationSoftLogoutScreen: View { configuration: UIKitTextInputConfiguration(returnKeyType: .done, isSecureTextEntry: true), onCommit: login) - .accessibilityIdentifier("passwordTextField") + .accessibilityIdentifier("passwordTextField") } /// A list of SSO buttons that can be used for login. @@ -188,7 +187,6 @@ struct AuthenticationSoftLogoutScreen: View { func clearData() { viewModel.send(viewAction: .clearAllData) } - } // MARK: - Previews diff --git a/RiotSwiftUI/Modules/Authentication/Terms/AuthenticationTermsModels.swift b/RiotSwiftUI/Modules/Authentication/Terms/AuthenticationTermsModels.swift index 8ff128be2..88301c6cb 100644 --- a/RiotSwiftUI/Modules/Authentication/Terms/AuthenticationTermsModels.swift +++ b/RiotSwiftUI/Modules/Authentication/Terms/AuthenticationTermsModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,7 +27,7 @@ struct AuthenticationTermsPolicy: Identifiable, Equatable { /// The policy's subtitle. let subtitle: String /// Whether or not the policy has been accepted. - var accepted: Bool = false + var accepted = false } // MARK: View model diff --git a/RiotSwiftUI/Modules/Authentication/Terms/AuthenticationTermsViewModel.swift b/RiotSwiftUI/Modules/Authentication/Terms/AuthenticationTermsViewModel.swift index e35366899..c868d8f4a 100644 --- a/RiotSwiftUI/Modules/Authentication/Terms/AuthenticationTermsViewModel.swift +++ b/RiotSwiftUI/Modules/Authentication/Terms/AuthenticationTermsViewModel.swift @@ -16,13 +16,11 @@ import SwiftUI - typealias AuthenticationTermsViewModelType = StateStoreViewModel + Never, + AuthenticationTermsViewAction> class AuthenticationTermsViewModel: AuthenticationTermsViewModelType, AuthenticationTermsViewModelProtocol { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Authentication/Terms/AuthenticationTermsViewModelProtocol.swift b/RiotSwiftUI/Modules/Authentication/Terms/AuthenticationTermsViewModelProtocol.swift index bd924d7cb..4a5bb4773 100644 --- a/RiotSwiftUI/Modules/Authentication/Terms/AuthenticationTermsViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Authentication/Terms/AuthenticationTermsViewModelProtocol.swift @@ -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 AuthenticationTermsViewModelProtocol { - var callback: (@MainActor (AuthenticationTermsViewModelResult) -> Void)? { get set } var context: AuthenticationTermsViewModelType.Context { get } diff --git a/RiotSwiftUI/Modules/Authentication/Terms/Coordinator/AuthenticationTermsCoordinator.swift b/RiotSwiftUI/Modules/Authentication/Terms/Coordinator/AuthenticationTermsCoordinator.swift index d05e3a5aa..5baeb2d3f 100644 --- a/RiotSwiftUI/Modules/Authentication/Terms/Coordinator/AuthenticationTermsCoordinator.swift +++ b/RiotSwiftUI/Modules/Authentication/Terms/Coordinator/AuthenticationTermsCoordinator.swift @@ -14,9 +14,9 @@ // limitations under the License. // -import SwiftUI import CommonKit import SafariServices +import SwiftUI struct AuthenticationTermsCoordinatorParameters { let registrationWizard: RegistrationWizard @@ -27,7 +27,6 @@ struct AuthenticationTermsCoordinatorParameters { } final class AuthenticationTermsCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -80,7 +79,7 @@ final class AuthenticationTermsCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.authenticationTermsHostingController + authenticationTermsHostingController } // MARK: - Private diff --git a/RiotSwiftUI/Modules/Authentication/Terms/MockAuthenticationTermsScreenState.swift b/RiotSwiftUI/Modules/Authentication/Terms/MockAuthenticationTermsScreenState.swift index 0bb977c46..7624872e9 100644 --- a/RiotSwiftUI/Modules/Authentication/Terms/MockAuthenticationTermsScreenState.swift +++ b/RiotSwiftUI/Modules/Authentication/Terms/MockAuthenticationTermsScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,7 +33,7 @@ enum MockAuthenticationTermsScreenState: MockScreenState, CaseIterable { } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let viewModel: AuthenticationTermsViewModel switch self { case .matrixDotOrg: diff --git a/RiotSwiftUI/Modules/Authentication/Terms/Test/UI/AuthenticationTermsUITests.swift b/RiotSwiftUI/Modules/Authentication/Terms/Test/UI/AuthenticationTermsUITests.swift index 3cb31c36a..c9f92a96c 100644 --- a/RiotSwiftUI/Modules/Authentication/Terms/Test/UI/AuthenticationTermsUITests.swift +++ b/RiotSwiftUI/Modules/Authentication/Terms/Test/UI/AuthenticationTermsUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class AuthenticationTermsUITests: MockScreenTestCase { func testMatrixDotOrg() { @@ -38,5 +38,4 @@ class AuthenticationTermsUITests: MockScreenTestCase { XCTAssertTrue(nextButton.exists, "The next button should always exist.") XCTAssertEqual(nextButton.isEnabled, accepted, "The next button should be enabled when the terms are accepted") } - } diff --git a/RiotSwiftUI/Modules/Authentication/Terms/Test/Unit/AuthenticationTermsViewModelTests.swift b/RiotSwiftUI/Modules/Authentication/Terms/Test/Unit/AuthenticationTermsViewModelTests.swift index 70166d010..ccbc50721 100644 --- a/RiotSwiftUI/Modules/Authentication/Terms/Test/Unit/AuthenticationTermsViewModelTests.swift +++ b/RiotSwiftUI/Modules/Authentication/Terms/Test/Unit/AuthenticationTermsViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Authentication/Terms/View/AuthenticationTermsListItem.swift b/RiotSwiftUI/Modules/Authentication/Terms/View/AuthenticationTermsListItem.swift index d8d8456b3..9cdb3d1d9 100644 --- a/RiotSwiftUI/Modules/Authentication/Terms/View/AuthenticationTermsListItem.swift +++ b/RiotSwiftUI/Modules/Authentication/Terms/View/AuthenticationTermsListItem.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ import SwiftUI struct AuthenticationTermsListItem: View { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Authentication/Terms/View/AuthenticationTermsScreen.swift b/RiotSwiftUI/Modules/Authentication/Terms/View/AuthenticationTermsScreen.swift index d8241ef62..ff2aa02cf 100644 --- a/RiotSwiftUI/Modules/Authentication/Terms/View/AuthenticationTermsScreen.swift +++ b/RiotSwiftUI/Modules/Authentication/Terms/View/AuthenticationTermsScreen.swift @@ -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 AuthenticationTermsScreen: View { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Authentication/Terms/View/AuthenticationTermsToggleStyle.swift b/RiotSwiftUI/Modules/Authentication/Terms/View/AuthenticationTermsToggleStyle.swift index b8bdec32f..f5e94ce84 100644 --- a/RiotSwiftUI/Modules/Authentication/Terms/View/AuthenticationTermsToggleStyle.swift +++ b/RiotSwiftUI/Modules/Authentication/Terms/View/AuthenticationTermsToggleStyle.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Authentication/VerifyEmail/AuthenticationVerifyEmailModels.swift b/RiotSwiftUI/Modules/Authentication/VerifyEmail/AuthenticationVerifyEmailModels.swift index dfe29221b..c3fce72fe 100644 --- a/RiotSwiftUI/Modules/Authentication/VerifyEmail/AuthenticationVerifyEmailModels.swift +++ b/RiotSwiftUI/Modules/Authentication/VerifyEmail/AuthenticationVerifyEmailModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Authentication/VerifyEmail/AuthenticationVerifyEmailViewModel.swift b/RiotSwiftUI/Modules/Authentication/VerifyEmail/AuthenticationVerifyEmailViewModel.swift index fca58b047..269c5e0a1 100644 --- a/RiotSwiftUI/Modules/Authentication/VerifyEmail/AuthenticationVerifyEmailViewModel.swift +++ b/RiotSwiftUI/Modules/Authentication/VerifyEmail/AuthenticationVerifyEmailViewModel.swift @@ -17,10 +17,9 @@ import SwiftUI typealias AuthenticationVerifyEmailViewModelType = StateStoreViewModel + Never, + AuthenticationVerifyEmailViewAction> class AuthenticationVerifyEmailViewModel: AuthenticationVerifyEmailViewModelType, AuthenticationVerifyEmailViewModelProtocol { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Authentication/VerifyEmail/AuthenticationVerifyEmailViewModelProtocol.swift b/RiotSwiftUI/Modules/Authentication/VerifyEmail/AuthenticationVerifyEmailViewModelProtocol.swift index 1c72824e5..6700cd157 100644 --- a/RiotSwiftUI/Modules/Authentication/VerifyEmail/AuthenticationVerifyEmailViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Authentication/VerifyEmail/AuthenticationVerifyEmailViewModelProtocol.swift @@ -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 AuthenticationVerifyEmailViewModelProtocol { - var callback: (@MainActor (AuthenticationVerifyEmailViewModelResult) -> Void)? { get set } var context: AuthenticationVerifyEmailViewModelType.Context { get } diff --git a/RiotSwiftUI/Modules/Authentication/VerifyEmail/Coordinator/AuthenticationVerifyEmailCoordinator.swift b/RiotSwiftUI/Modules/Authentication/VerifyEmail/Coordinator/AuthenticationVerifyEmailCoordinator.swift index bd68b0e44..920884048 100644 --- a/RiotSwiftUI/Modules/Authentication/VerifyEmail/Coordinator/AuthenticationVerifyEmailCoordinator.swift +++ b/RiotSwiftUI/Modules/Authentication/VerifyEmail/Coordinator/AuthenticationVerifyEmailCoordinator.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import SwiftUI import CommonKit +import SwiftUI struct AuthenticationVerifyEmailCoordinatorParameters { let registrationWizard: RegistrationWizard @@ -24,7 +24,6 @@ struct AuthenticationVerifyEmailCoordinatorParameters { } final class AuthenticationVerifyEmailCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -74,7 +73,7 @@ final class AuthenticationVerifyEmailCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.authenticationVerifyEmailHostingController + authenticationVerifyEmailHostingController } // MARK: - Private diff --git a/RiotSwiftUI/Modules/Authentication/VerifyEmail/MockAuthenticationVerifyEmailScreenState.swift b/RiotSwiftUI/Modules/Authentication/VerifyEmail/MockAuthenticationVerifyEmailScreenState.swift index 3226f2f00..2474d00cc 100644 --- a/RiotSwiftUI/Modules/Authentication/VerifyEmail/MockAuthenticationVerifyEmailScreenState.swift +++ b/RiotSwiftUI/Modules/Authentication/VerifyEmail/MockAuthenticationVerifyEmailScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,7 +33,7 @@ enum MockAuthenticationVerifyEmailScreenState: MockScreenState, CaseIterable { } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let viewModel: AuthenticationVerifyEmailViewModel switch self { case .emptyAddress: diff --git a/RiotSwiftUI/Modules/Authentication/VerifyEmail/Test/UI/AuthenticationVerifyEmailUITests.swift b/RiotSwiftUI/Modules/Authentication/VerifyEmail/Test/UI/AuthenticationVerifyEmailUITests.swift index 73706abcd..52dad31a0 100644 --- a/RiotSwiftUI/Modules/Authentication/VerifyEmail/Test/UI/AuthenticationVerifyEmailUITests.swift +++ b/RiotSwiftUI/Modules/Authentication/VerifyEmail/Test/UI/AuthenticationVerifyEmailUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class AuthenticationVerifyEmailUITests: MockScreenTestCase { func testEmptyAddress() { @@ -78,5 +78,4 @@ class AuthenticationVerifyEmailUITests: MockScreenTestCase { XCTAssertTrue(backButton.exists, "Back button should be shown.") XCTAssertEqual(backButton.label, "Back") } - } diff --git a/RiotSwiftUI/Modules/Authentication/VerifyEmail/Test/Unit/AuthenticationVerifyEmailViewModelTests.swift b/RiotSwiftUI/Modules/Authentication/VerifyEmail/Test/Unit/AuthenticationVerifyEmailViewModelTests.swift index 3b340a9bf..553858d25 100644 --- a/RiotSwiftUI/Modules/Authentication/VerifyEmail/Test/Unit/AuthenticationVerifyEmailViewModelTests.swift +++ b/RiotSwiftUI/Modules/Authentication/VerifyEmail/Test/Unit/AuthenticationVerifyEmailViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ import XCTest @testable import RiotSwiftUI class AuthenticationVerifyEmailViewModelTests: XCTestCase { - var viewModel: AuthenticationVerifyEmailViewModelProtocol! var context: AuthenticationVerifyEmailViewModelType.Context! diff --git a/RiotSwiftUI/Modules/Authentication/VerifyEmail/View/AuthenticationVerifyEmailForm.swift b/RiotSwiftUI/Modules/Authentication/VerifyEmail/View/AuthenticationVerifyEmailForm.swift index 274a0a942..79ca40c12 100644 --- a/RiotSwiftUI/Modules/Authentication/VerifyEmail/View/AuthenticationVerifyEmailForm.swift +++ b/RiotSwiftUI/Modules/Authentication/VerifyEmail/View/AuthenticationVerifyEmailForm.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import SwiftUI /// The form shown to enter an email address. struct AuthenticationVerifyEmailForm: View { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Authentication/VerifyEmail/View/AuthenticationVerifyEmailScreen.swift b/RiotSwiftUI/Modules/Authentication/VerifyEmail/View/AuthenticationVerifyEmailScreen.swift index 97283a9f9..2081f58d9 100644 --- a/RiotSwiftUI/Modules/Authentication/VerifyEmail/View/AuthenticationVerifyEmailScreen.swift +++ b/RiotSwiftUI/Modules/Authentication/VerifyEmail/View/AuthenticationVerifyEmailScreen.swift @@ -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 AuthenticationVerifyEmailScreen: View { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/AuthenticationVerifyMsisdnModels.swift b/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/AuthenticationVerifyMsisdnModels.swift index c9d9aec6e..a89016fda 100644 --- a/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/AuthenticationVerifyMsisdnModels.swift +++ b/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/AuthenticationVerifyMsisdnModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/AuthenticationVerifyMsisdnViewModel.swift b/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/AuthenticationVerifyMsisdnViewModel.swift index de688374a..651a4935a 100644 --- a/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/AuthenticationVerifyMsisdnViewModel.swift +++ b/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/AuthenticationVerifyMsisdnViewModel.swift @@ -17,10 +17,9 @@ import SwiftUI typealias AuthenticationVerifyMsisdnViewModelType = StateStoreViewModel + Never, + AuthenticationVerifyMsisdnViewAction> class AuthenticationVerifyMsisdnViewModel: AuthenticationVerifyMsisdnViewModelType, AuthenticationVerifyMsisdnViewModelProtocol { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/AuthenticationVerifyMsisdnViewModelProtocol.swift b/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/AuthenticationVerifyMsisdnViewModelProtocol.swift index 56c565398..b9412cd46 100644 --- a/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/AuthenticationVerifyMsisdnViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/AuthenticationVerifyMsisdnViewModelProtocol.swift @@ -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 AuthenticationVerifyMsisdnViewModelProtocol { - var callback: (@MainActor (AuthenticationVerifyMsisdnViewModelResult) -> Void)? { get set } var context: AuthenticationVerifyMsisdnViewModelType.Context { get } diff --git a/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/Coordinator/AuthenticationVerifyMsisdnCoordinator.swift b/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/Coordinator/AuthenticationVerifyMsisdnCoordinator.swift index 1962efe56..0d7b42dc4 100644 --- a/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/Coordinator/AuthenticationVerifyMsisdnCoordinator.swift +++ b/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/Coordinator/AuthenticationVerifyMsisdnCoordinator.swift @@ -14,9 +14,9 @@ // limitations under the License. // -import SwiftUI import CommonKit import libPhoneNumber_iOS +import SwiftUI struct AuthenticationVerifyMsisdnCoordinatorParameters { let registrationWizard: RegistrationWizard @@ -25,7 +25,6 @@ struct AuthenticationVerifyMsisdnCoordinatorParameters { } final class AuthenticationVerifyMsisdnCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -75,7 +74,7 @@ final class AuthenticationVerifyMsisdnCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.authenticationVerifyMsisdnHostingController + authenticationVerifyMsisdnHostingController } // MARK: - Private @@ -174,7 +173,6 @@ final class AuthenticationVerifyMsisdnCoordinator: Coordinator, Presentable { self?.stopLoading() self?.handleError(error) } - } } diff --git a/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/MockAuthenticationVerifyMsisdnScreenState.swift b/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/MockAuthenticationVerifyMsisdnScreenState.swift index 63242fa42..622176a74 100644 --- a/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/MockAuthenticationVerifyMsisdnScreenState.swift +++ b/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/MockAuthenticationVerifyMsisdnScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,7 +34,7 @@ enum MockAuthenticationVerifyMsisdnScreenState: MockScreenState, CaseIterable { } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let viewModel: AuthenticationVerifyMsisdnViewModel switch self { case .emptyPhoneNumber: diff --git a/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/Test/UI/AuthenticationVerifyMsisdnUITests.swift b/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/Test/UI/AuthenticationVerifyMsisdnUITests.swift index f5528acfa..535565860 100644 --- a/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/Test/UI/AuthenticationVerifyMsisdnUITests.swift +++ b/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/Test/UI/AuthenticationVerifyMsisdnUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class AuthenticationVerifyMsisdnUITests: MockScreenTestCase { func testEmptyPhoneNumber() { @@ -127,5 +127,4 @@ class AuthenticationVerifyMsisdnUITests: MockScreenTestCase { XCTAssertTrue(backButton.exists, "Back button should be shown.") XCTAssertEqual(backButton.label, "Back") } - } diff --git a/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/Test/Unit/AuthenticationVerifyMsisdnViewModelTests.swift b/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/Test/Unit/AuthenticationVerifyMsisdnViewModelTests.swift index 77a117d37..fb4c1965c 100644 --- a/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/Test/Unit/AuthenticationVerifyMsisdnViewModelTests.swift +++ b/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/Test/Unit/AuthenticationVerifyMsisdnViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ import XCTest @testable import RiotSwiftUI class AuthenticationVerifyMsisdnViewModelTests: XCTestCase { - var viewModel: AuthenticationVerifyMsisdnViewModelProtocol! var context: AuthenticationVerifyMsisdnViewModelType.Context! diff --git a/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/View/AuthenticationVerifyMsisdnForm.swift b/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/View/AuthenticationVerifyMsisdnForm.swift index 9701a680d..97a7b6f20 100644 --- a/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/View/AuthenticationVerifyMsisdnForm.swift +++ b/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/View/AuthenticationVerifyMsisdnForm.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import SwiftUI /// The form shown to enter an email address. struct AuthenticationVerifyMsisdnForm: View { - // MARK: - Properties // MARK: Private @@ -65,7 +64,7 @@ struct AuthenticationVerifyMsisdnForm: View { /// The text field and submit button where the user enters a phone number. var mainContent: some View { - return VStack(alignment: .leading, spacing: 12) { + VStack(alignment: .leading, spacing: 12) { if #available(iOS 15.0, *) { textField .onSubmit(sendSMS) diff --git a/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/View/AuthenticationVerifyMsisdnOTPForm.swift b/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/View/AuthenticationVerifyMsisdnOTPForm.swift index e56badab4..926892791 100644 --- a/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/View/AuthenticationVerifyMsisdnOTPForm.swift +++ b/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/View/AuthenticationVerifyMsisdnOTPForm.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import SwiftUI /// The form shown to enter an OTP for phone number vaildation struct AuthenticationVerifyMsisdnOTPForm: View { - // MARK: - Properties // MARK: Private @@ -65,7 +64,7 @@ struct AuthenticationVerifyMsisdnOTPForm: View { /// The text field and submit button where the user enters an OTP. var mainContent: some View { - return VStack(alignment: .leading, spacing: 12) { + VStack(alignment: .leading, spacing: 12) { if #available(iOS 15.0, *) { textField .onSubmit(submitOTP) @@ -93,7 +92,7 @@ struct AuthenticationVerifyMsisdnOTPForm: View { /// The text field, extracted for iOS 15 modifiers to be applied. var textField: some View { - return TextField(VectorL10n.authenticationVerifyMsisdnOtpTextFieldPlaceholder, text: $viewModel.otp) { + TextField(VectorL10n.authenticationVerifyMsisdnOtpTextFieldPlaceholder, text: $viewModel.otp) { isEditingTextField = $0 } .textFieldStyle(BorderedInputFieldStyle(isEditing: isEditingTextField, isError: false)) @@ -104,7 +103,7 @@ struct AuthenticationVerifyMsisdnOTPForm: View { /// Sends the `submitOTP` view action so long as a valid OTP has been input. func submitOTP() { - guard viewModel.viewState.hasSentSMS && !viewModel.viewState.hasInvalidOTP else { return } + guard viewModel.viewState.hasSentSMS, !viewModel.viewState.hasInvalidOTP else { return } viewModel.send(viewAction: .submitOTP) } } diff --git a/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/View/AuthenticationVerifyMsisdnScreen.swift b/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/View/AuthenticationVerifyMsisdnScreen.swift index 867e58224..c6bd7943d 100644 --- a/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/View/AuthenticationVerifyMsisdnScreen.swift +++ b/RiotSwiftUI/Modules/Authentication/VerifyMsisdn/View/AuthenticationVerifyMsisdnScreen.swift @@ -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 AuthenticationVerifyMsisdnScreen: View { - // MARK: - Properties // MARK: Private @@ -31,7 +30,7 @@ struct AuthenticationVerifyMsisdnScreen: View { // MARK: Views var body: some View { - GeometryReader { geometry in + GeometryReader { _ in VStack { ScrollView { if viewModel.viewState.hasSentSMS { diff --git a/RiotSwiftUI/Modules/Common/ActivityIndicator/ActivityIndicator.swift b/RiotSwiftUI/Modules/Common/ActivityIndicator/ActivityIndicator.swift index 51c4ecdd8..32b48c821 100644 --- a/RiotSwiftUI/Modules/Common/ActivityIndicator/ActivityIndicator.swift +++ b/RiotSwiftUI/Modules/Common/ActivityIndicator/ActivityIndicator.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import SwiftUI /// A visual cue to user that something is in progress. struct ActivityIndicator: View { - private enum Constants { static let backgroundColor = Color(UIColor(white: 0.8, alpha: 0.9)) } @@ -29,7 +28,6 @@ struct ActivityIndicator: View { .padding() .background(Constants.backgroundColor) .cornerRadius(5) - } } diff --git a/RiotSwiftUI/Modules/Common/ActivityIndicator/ActivityIndicatorModifier.swift b/RiotSwiftUI/Modules/Common/ActivityIndicator/ActivityIndicatorModifier.swift index cd4bb859f..3d935ea67 100644 --- a/RiotSwiftUI/Modules/Common/ActivityIndicator/ActivityIndicatorModifier.swift +++ b/RiotSwiftUI/Modules/Common/ActivityIndicator/ActivityIndicatorModifier.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,6 +37,6 @@ struct ActivityIndicatorModifier: ViewModifier { extension View { func activityIndicator(show: Bool) -> some View { - self.modifier(ActivityIndicatorModifier(show: show)) + modifier(ActivityIndicatorModifier(show: show)) } } diff --git a/RiotSwiftUI/Modules/Common/Avatar/Model/AvatarInputProtocol.swift b/RiotSwiftUI/Modules/Common/Avatar/Model/AvatarInputProtocol.swift index 2b36660a0..fe53976f1 100644 --- a/RiotSwiftUI/Modules/Common/Avatar/Model/AvatarInputProtocol.swift +++ b/RiotSwiftUI/Modules/Common/Avatar/Model/AvatarInputProtocol.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Common/Avatar/Model/AvatarProtocol.swift b/RiotSwiftUI/Modules/Common/Avatar/Model/AvatarProtocol.swift index 7963c333a..b3342b8b3 100644 --- a/RiotSwiftUI/Modules/Common/Avatar/Model/AvatarProtocol.swift +++ b/RiotSwiftUI/Modules/Common/Avatar/Model/AvatarProtocol.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Common/Avatar/Model/Avatarable.swift b/RiotSwiftUI/Modules/Common/Avatar/Model/Avatarable.swift index 4e5062b5f..ce8e4ee40 100644 --- a/RiotSwiftUI/Modules/Common/Avatar/Model/Avatarable.swift +++ b/RiotSwiftUI/Modules/Common/Avatar/Model/Avatarable.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,7 @@ import Foundation /// A protocol that any class or struct can conform to /// so that it can easily produce avatar data. -/// +/// /// E.g. MXRoom, MxUser can conform to this making it /// easy to grab the avatar data for display. protocol Avatarable: AvatarInputProtocol { } diff --git a/RiotSwiftUI/Modules/Common/Avatar/Model/Mock/MockAvatarInput.swift b/RiotSwiftUI/Modules/Common/Avatar/Model/Mock/MockAvatarInput.swift index 4e62c0b50..773c6d439 100644 --- a/RiotSwiftUI/Modules/Common/Avatar/Model/Mock/MockAvatarInput.swift +++ b/RiotSwiftUI/Modules/Common/Avatar/Model/Mock/MockAvatarInput.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Common/Avatar/Service/MatrixSDK/AvatarService.swift b/RiotSwiftUI/Modules/Common/Avatar/Service/MatrixSDK/AvatarService.swift index 2e6ca5a94..02369980c 100644 --- a/RiotSwiftUI/Modules/Common/Avatar/Service/MatrixSDK/AvatarService.swift +++ b/RiotSwiftUI/Modules/Common/Avatar/Service/MatrixSDK/AvatarService.swift @@ -14,10 +14,10 @@ // limitations under the License. // -import Foundation -import MatrixSDK import Combine import DesignKit +import Foundation +import MatrixSDK enum AvatarServiceError: Error { case pathNotfound @@ -25,7 +25,6 @@ enum AvatarServiceError: Error { } class AvatarService: AvatarServiceProtocol { - private enum Constants { static let mimeType = "image/jpeg" static let thumbnailMethod = MXThumbnailingMethodCrop @@ -34,7 +33,7 @@ class AvatarService: AvatarServiceProtocol { private let mediaManager: MXMediaManager static func instantiate(mediaManager: MXMediaManager) -> AvatarServiceProtocol { - return AvatarService(mediaManager: mediaManager) + AvatarService(mediaManager: mediaManager) } init(mediaManager: MXMediaManager) { @@ -49,13 +48,13 @@ class AvatarService: AvatarServiceProtocol { /// - avatarSize: The size of avatar to retrieve as defined in the DesignKit spec. /// - Returns: A Future of UIImage that returns an error if it fails to fetch the image. func avatarImage(mxContentUri: String, avatarSize: AvatarSize) -> Future { - let cachePath = MXMediaManager.thumbnailCachePath( forMatrixContentURI: mxContentUri, andType: Constants.mimeType, - inFolder: nil, + inFolder: nil, toFitViewSize: avatarSize.size, - with: Constants.thumbnailMethod) + with: Constants.thumbnailMethod + ) return Future { promise in if let image = MXMediaManager.loadThroughCache(withFilePath: cachePath), @@ -69,7 +68,8 @@ class AvatarService: AvatarServiceProtocol { withType: Constants.mimeType, inFolder: nil, toFitViewSize: avatarSize.size, - with: Constants.thumbnailMethod) { path in + with: Constants.thumbnailMethod + ) { path in guard let path = path else { promise(.failure(AvatarServiceError.pathNotfound)) return diff --git a/RiotSwiftUI/Modules/Common/Avatar/Service/Mock/MockAvatarService.swift b/RiotSwiftUI/Modules/Common/Avatar/Service/Mock/MockAvatarService.swift index 94ea01c55..eff0be3f4 100644 --- a/RiotSwiftUI/Modules/Common/Avatar/Service/Mock/MockAvatarService.swift +++ b/RiotSwiftUI/Modules/Common/Avatar/Service/Mock/MockAvatarService.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,9 +14,9 @@ // limitations under the License. // -import Foundation import Combine import DesignKit +import Foundation import UIKit class MockAvatarService: AvatarServiceProtocol { diff --git a/RiotSwiftUI/Modules/Common/Avatar/View/AvatarImage.swift b/RiotSwiftUI/Modules/Common/Avatar/View/AvatarImage.swift index 2b7fa9e60..4f51f574a 100644 --- a/RiotSwiftUI/Modules/Common/Avatar/View/AvatarImage.swift +++ b/RiotSwiftUI/Modules/Common/Avatar/View/AvatarImage.swift @@ -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 SwiftUI import DesignKit +import SwiftUI struct AvatarImage: View { - @Environment(\.theme) var theme: ThemeSwiftUI @Environment(\.dependencies) var dependencies: DependencyContainer @StateObject var viewModel = AvatarViewModel() @@ -75,7 +74,7 @@ extension AvatarImage { /// Use display name color as border color by default func border() -> some View { let borderColor = theme.userColor(for: matrixItemId) - return self.border(color: borderColor) + return border(color: borderColor) } } diff --git a/RiotSwiftUI/Modules/Common/Avatar/View/PlaceholderAvatarImage.swift b/RiotSwiftUI/Modules/Common/Avatar/View/PlaceholderAvatarImage.swift index f119a7e14..55a1b6854 100644 --- a/RiotSwiftUI/Modules/Common/Avatar/View/PlaceholderAvatarImage.swift +++ b/RiotSwiftUI/Modules/Common/Avatar/View/PlaceholderAvatarImage.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,7 +22,6 @@ import SwiftUI /// This view has a forced 1:1 aspect ratio but will appear very large until a `.frame` /// modifier is applied. struct PlaceholderAvatarImage: View { - // MARK: - Private @Environment(\.theme) private var theme diff --git a/RiotSwiftUI/Modules/Common/Avatar/View/SpaceAvatarImage.swift b/RiotSwiftUI/Modules/Common/Avatar/View/SpaceAvatarImage.swift index d82e2107f..8e967fe18 100644 --- a/RiotSwiftUI/Modules/Common/Avatar/View/SpaceAvatarImage.swift +++ b/RiotSwiftUI/Modules/Common/Avatar/View/SpaceAvatarImage.swift @@ -14,11 +14,10 @@ // limitations under the License. // -import SwiftUI import DesignKit +import SwiftUI struct SpaceAvatarImage: View { - @Environment(\.theme) var theme: ThemeSwiftUI @Environment(\.dependencies) var dependencies: DependencyContainer @StateObject var viewModel = AvatarViewModel() diff --git a/RiotSwiftUI/Modules/Common/Avatar/ViewModel/AvatarServiceProtocol.swift b/RiotSwiftUI/Modules/Common/Avatar/ViewModel/AvatarServiceProtocol.swift index 1f505a7db..578c34834 100644 --- a/RiotSwiftUI/Modules/Common/Avatar/ViewModel/AvatarServiceProtocol.swift +++ b/RiotSwiftUI/Modules/Common/Avatar/ViewModel/AvatarServiceProtocol.swift @@ -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 DesignKit import Combine +import DesignKit +import Foundation import UIKit - /// Provides a simple api to retrieve and cache avatar images protocol AvatarServiceProtocol { func avatarImage(mxContentUri: String, avatarSize: AvatarSize) -> Future diff --git a/RiotSwiftUI/Modules/Common/Avatar/ViewModel/AvatarViewModel.swift b/RiotSwiftUI/Modules/Common/Avatar/ViewModel/AvatarViewModel.swift index 90f736da6..433fb9cba 100644 --- a/RiotSwiftUI/Modules/Common/Avatar/ViewModel/AvatarViewModel.swift +++ b/RiotSwiftUI/Modules/Common/Avatar/ViewModel/AvatarViewModel.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,13 +14,12 @@ // limitations under the License. // -import Foundation import Combine import DesignKit +import Foundation /// Simple ViewModel that supports loading an avatar image class AvatarViewModel: InjectableObject, ObservableObject { - @Inject var avatarService: AvatarServiceProtocol @Published private(set) var viewState = AvatarViewState.empty @@ -34,24 +33,22 @@ class AvatarViewModel: InjectableObject, ObservableObject { /// - displayName: Display name of the avatar. /// - colorCount: The count of total avatar colors used to generate the stable color index. /// - avatarSize: The size of the avatar to fetch (as defined within DesignKit). - func loadAvatar( - mxContentUri: String?, - matrixItemId: String, - displayName: String?, - colorCount: Int, - avatarSize: AvatarSize) { - + func loadAvatar(mxContentUri: String?, + matrixItemId: String, + displayName: String?, + colorCount: Int, + avatarSize: AvatarSize) { let placeholderViewModel = PlaceholderAvatarViewModel(displayName: displayName, matrixItemId: matrixItemId, colorCount: colorCount) - self.viewState = .placeholder(placeholderViewModel.firstCharacterCapitalized, placeholderViewModel.stableColorIndex) + viewState = .placeholder(placeholderViewModel.firstCharacterCapitalized, placeholderViewModel.stableColorIndex) guard let mxContentUri = mxContentUri, mxContentUri.count > 0 else { return } - avatarService.avatarImage(mxContentUri: mxContentUri, avatarSize: avatarSize) + avatarService.avatarImage(mxContentUri: mxContentUri, avatarSize: avatarSize) .sink { completion in guard case let .failure(error) = completion else { return } UILog.error("[AvatarService] Failed to retrieve avatar", context: error) diff --git a/RiotSwiftUI/Modules/Common/Avatar/ViewModel/AvatarViewState.swift b/RiotSwiftUI/Modules/Common/Avatar/ViewModel/AvatarViewState.swift index cac2a70d4..97b09ea41 100644 --- a/RiotSwiftUI/Modules/Common/Avatar/ViewModel/AvatarViewState.swift +++ b/RiotSwiftUI/Modules/Common/Avatar/ViewModel/AvatarViewState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Common/Avatar/ViewModel/PlaceholderAvatarViewModel.swift b/RiotSwiftUI/Modules/Common/Avatar/ViewModel/PlaceholderAvatarViewModel.swift index d5c131b39..618d6f284 100644 --- a/RiotSwiftUI/Modules/Common/Avatar/ViewModel/PlaceholderAvatarViewModel.swift +++ b/RiotSwiftUI/Modules/Common/Avatar/ViewModel/PlaceholderAvatarViewModel.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,7 +27,7 @@ struct PlaceholderAvatarViewModel { /// Get the first character of the display name capitalized or else a space character. var firstCharacterCapitalized: Character { - return displayName?.capitalized.first ?? " " + displayName?.capitalized.first ?? " " } /// Provides the same color each time for a specified matrixId @@ -39,7 +39,7 @@ struct PlaceholderAvatarViewModel { var stableColorIndex: Int { // Sum all characters let sum = matrixItemId.utf8 - .map({ UInt($0) }) + .map { UInt($0) } .reduce(0, +) // modulo the color count return Int(sum) % colorCount diff --git a/RiotSwiftUI/Modules/Common/Bridging/VectorContentView.swift b/RiotSwiftUI/Modules/Common/Bridging/VectorContentView.swift index 4783fd01c..dfdd5e8b3 100644 --- a/RiotSwiftUI/Modules/Common/Bridging/VectorContentView.swift +++ b/RiotSwiftUI/Modules/Common/Bridging/VectorContentView.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,7 +20,6 @@ import SwiftUI /// /// Provides any app level configuration the SwiftUI hierarchy might need (E.g. to monitor theme changes). struct VectorContentModifier: ViewModifier { - @ObservedObject private var themePublisher = ThemePublisher.shared @Environment(\.layoutDirection) private var defaultLayoutDirection @@ -39,6 +38,6 @@ struct VectorContentModifier: ViewModifier { extension View { func vectorContent() -> some View { - self.modifier(VectorContentModifier()) + modifier(VectorContentModifier()) } } diff --git a/RiotSwiftUI/Modules/Common/DependencyInjection/DependencyContainer.swift b/RiotSwiftUI/Modules/Common/DependencyInjection/DependencyContainer.swift index c3c0169fd..d09fa87f4 100644 --- a/RiotSwiftUI/Modules/Common/DependencyInjection/DependencyContainer.swift +++ b/RiotSwiftUI/Modules/Common/DependencyInjection/DependencyContainer.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import Foundation /// Used for storing and resolving dependencies at runtime. struct DependencyContainer { - // Stores the dependencies with type information removed. private var dependencyStore: [String: Any] = [:] @@ -26,7 +25,7 @@ struct DependencyContainer { /// /// Given a particular `Type` (Inferred from return type), /// generate a key and retrieve from storage. - /// + /// /// - Returns: The resolved dependency. func resolve() -> T { let key = String(describing: T.self) diff --git a/RiotSwiftUI/Modules/Common/DependencyInjection/DependencyContainerKey.swift b/RiotSwiftUI/Modules/Common/DependencyInjection/DependencyContainerKey.swift index b788b362d..4bde8956e 100644 --- a/RiotSwiftUI/Modules/Common/DependencyInjection/DependencyContainerKey.swift +++ b/RiotSwiftUI/Modules/Common/DependencyInjection/DependencyContainerKey.swift @@ -33,7 +33,6 @@ extension EnvironmentValues { } extension View { - /// A modifier for adding a dependency to the SwiftUI view hierarchy's dependency container. /// /// Important: When adding a dependency to cast it to the type in which it will be injected. diff --git a/RiotSwiftUI/Modules/Common/DependencyInjection/Inject.swift b/RiotSwiftUI/Modules/Common/DependencyInjection/Inject.swift index e81457678..d45907eeb 100644 --- a/RiotSwiftUI/Modules/Common/DependencyInjection/Inject.swift +++ b/RiotSwiftUI/Modules/Common/DependencyInjection/Inject.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,12 +22,9 @@ import Foundation /// @Inject var someClass: SomeClass /// ``` @propertyWrapper struct Inject { - - static subscript( - _enclosingInstance instance: T, - wrapped wrappedKeyPath: ReferenceWritableKeyPath, - storage storageKeyPath: ReferenceWritableKeyPath - ) -> Value { + static subscript(_enclosingInstance instance: T, + wrapped wrappedKeyPath: ReferenceWritableKeyPath, + storage storageKeyPath: ReferenceWritableKeyPath) -> Value { get { // Resolve dependencies from enclosing instance's `dependencies` property let v: Value = instance.dependencies.resolve() @@ -38,9 +35,9 @@ import Foundation } } - @available(*, unavailable, message: "This property wrapper can only be applied to classes") + @available(*, unavailable, message: "This property wrapper can only be applied to classes") var wrappedValue: Value { get { fatalError("wrappedValue get not used") } - set { fatalError("wrappedValue set not used. \(newValue)" ) } + set { fatalError("wrappedValue set not used. \(newValue)") } } } diff --git a/RiotSwiftUI/Modules/Common/DependencyInjection/Injectable.swift b/RiotSwiftUI/Modules/Common/DependencyInjection/Injectable.swift index 96e5eef64..b05b966e4 100644 --- a/RiotSwiftUI/Modules/Common/DependencyInjection/Injectable.swift +++ b/RiotSwiftUI/Modules/Common/DependencyInjection/Injectable.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,9 +21,7 @@ protocol Injectable: AnyObject { var dependencies: DependencyContainer! { get set } } - extension Injectable { - /// Used to inject the dependency container into an Injectable. /// - Parameter dependencies: The `DependencyContainer` to inject. func inject(dependencies: DependencyContainer) { diff --git a/RiotSwiftUI/Modules/Common/DependencyInjection/InjectableObject.swift b/RiotSwiftUI/Modules/Common/DependencyInjection/InjectableObject.swift index bf38a0707..eab3cdcdf 100644 --- a/RiotSwiftUI/Modules/Common/DependencyInjection/InjectableObject.swift +++ b/RiotSwiftUI/Modules/Common/DependencyInjection/InjectableObject.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Common/EffectsScene/EffectsScene.swift b/RiotSwiftUI/Modules/Common/EffectsScene/EffectsScene.swift index 38eb5db11..6224c7185 100644 --- a/RiotSwiftUI/Modules/Common/EffectsScene/EffectsScene.swift +++ b/RiotSwiftUI/Modules/Common/EffectsScene/EffectsScene.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import SceneKit import SwiftUI class EffectsScene: SCNScene { - // MARK: - Constants private enum Constants { @@ -31,14 +30,14 @@ class EffectsScene: SCNScene { static func confetti(with theme: ThemeSwiftUI) -> EffectsScene? { guard let scene = EffectsScene(named: Constants.confettiSceneName) else { return nil } - let colors: [[Float]] = theme.colors.namesAndAvatars.compactMap { $0.floatComponents } + let colors: [[Float]] = theme.colors.namesAndAvatars.compactMap(\.floatComponents) if let particles = scene.rootNode.childNode(withName: Constants.particlesNodeName, recursively: false)?.particleSystems?.first { // The particles need a non-zero color variation for the handler to affect the color particles.particleColorVariation = SCNVector4(x: 0, y: 0, z: 0, w: 0.1) // Add a handler to customize the color of the particles. - particles.handle(.birth, forProperties: [.color]) { data, dataStride, indices, count in + particles.handle(.birth, forProperties: [.color]) { data, dataStride, _, count in for index in 0..: Identifiable { /// The alert's title. let title: String /// The alert's message (optional). - var message: String? = nil + var message: String? /// The alert's primary button title and action. Defaults to an Ok button with no action. var primaryButton: (title: String, action: (() -> Void)?) = (VectorL10n.ok, nil) /// The alert's secondary button title and action. - var secondaryButton: (title: String, action: (() -> Void)?)? = nil + var secondaryButton: (title: String, action: (() -> Void)?)? } extension AlertInfo { @@ -47,7 +47,7 @@ extension AlertInfo { /// - id: An ID that identifies the error. /// - error: The Error that occurred. init?(id: T, error: NSError? = nil) { - guard error?.domain != NSURLErrorDomain && error?.code != NSURLErrorCancelled else { return nil } + guard error?.domain != NSURLErrorDomain, error?.code != NSURLErrorCancelled else { return nil } self.id = id title = error?.userInfo[NSLocalizedFailureReasonErrorKey] as? String ?? VectorL10n.error diff --git a/RiotSwiftUI/Modules/Common/Extensions/CLLocationCoordinate2D.swift b/RiotSwiftUI/Modules/Common/Extensions/CLLocationCoordinate2D.swift index cdc21e100..7a5fdf63c 100644 --- a/RiotSwiftUI/Modules/Common/Extensions/CLLocationCoordinate2D.swift +++ b/RiotSwiftUI/Modules/Common/Extensions/CLLocationCoordinate2D.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,18 +14,16 @@ // limitations under the License. // -import Foundation import CoreLocation +import Foundation extension CLLocationCoordinate2D { - /// Compare two coordinates /// - parameter coordinate: another coordinate to compare /// - parameter precision:it represente how close you want the two coordinates /// - return: bool value func isEqual(to coordinate: CLLocationCoordinate2D, precision: Double) -> Bool { - - if fabs(self.latitude - coordinate.latitude) <= precision && fabs(self.longitude - coordinate.longitude) <= precision { + if fabs(latitude - coordinate.latitude) <= precision, fabs(longitude - coordinate.longitude) <= precision { return true } return false diff --git a/RiotSwiftUI/Modules/Common/Extensions/MatrixSDK/MXRoomAvatarable.swift b/RiotSwiftUI/Modules/Common/Extensions/MatrixSDK/MXRoomAvatarable.swift index e18feed41..ac7a7ebbc 100644 --- a/RiotSwiftUI/Modules/Common/Extensions/MatrixSDK/MXRoomAvatarable.swift +++ b/RiotSwiftUI/Modules/Common/Extensions/MatrixSDK/MXRoomAvatarable.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,5 +27,4 @@ extension MXRoom: Avatarable { var displayName: String? { summary.displayname } - } diff --git a/RiotSwiftUI/Modules/Common/Extensions/MatrixSDK/MXUserAvatarable.swift b/RiotSwiftUI/Modules/Common/Extensions/MatrixSDK/MXUserAvatarable.swift index 701c2f75f..f6843b063 100644 --- a/RiotSwiftUI/Modules/Common/Extensions/MatrixSDK/MXUserAvatarable.swift +++ b/RiotSwiftUI/Modules/Common/Extensions/MatrixSDK/MXUserAvatarable.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,5 +27,4 @@ extension MXUser: Avatarable { var displayName: String? { displayname } - } diff --git a/RiotSwiftUI/Modules/Common/Extensions/Publisher.swift b/RiotSwiftUI/Modules/Common/Extensions/Publisher.swift index 892608cef..c5e3622ad 100644 --- a/RiotSwiftUI/Modules/Common/Extensions/Publisher.swift +++ b/RiotSwiftUI/Modules/Common/Extensions/Publisher.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,17 +14,15 @@ // limitations under the License. // -import Foundation import Combine +import Foundation extension Publisher where Failure == Never { /// Same as `assign(to:on:)` but maintains a weak reference to object /// /// Useful in cases where you want to pass self and not cause a retain cycle. - func weakAssign( - to keyPath: ReferenceWritableKeyPath, - on object: T - ) -> AnyCancellable { + func weakAssign(to keyPath: ReferenceWritableKeyPath, + on object: T) -> AnyCancellable { sink { [weak object] value in object?[keyPath: keyPath] = value } diff --git a/RiotSwiftUI/Modules/Common/Locale/LocaleProvider.swift b/RiotSwiftUI/Modules/Common/Locale/LocaleProvider.swift index a1ba74921..11f44e8be 100644 --- a/RiotSwiftUI/Modules/Common/Locale/LocaleProvider.swift +++ b/RiotSwiftUI/Modules/Common/Locale/LocaleProvider.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +18,6 @@ import Foundation class LocaleProvider: LocaleProviderType { static var locale: Locale? { - return nil + nil } } diff --git a/RiotSwiftUI/Modules/Common/Logging/LoggerProtocol.swift b/RiotSwiftUI/Modules/Common/Logging/LoggerProtocol.swift index bedcb6a67..6f2eabbf1 100644 --- a/RiotSwiftUI/Modules/Common/Logging/LoggerProtocol.swift +++ b/RiotSwiftUI/Modules/Common/Logging/LoggerProtocol.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Common/Logging/PrintLogger.swift b/RiotSwiftUI/Modules/Common/Logging/PrintLogger.swift index 85587467f..decebbc42 100644 --- a/RiotSwiftUI/Modules/Common/Logging/PrintLogger.swift +++ b/RiotSwiftUI/Modules/Common/Logging/PrintLogger.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,15 +23,19 @@ class PrintLogger: LoggerProtocol { static func verbose(_ message: @autoclosure () -> Any, _ file: String = #file, _ function: String = #function, line: Int = #line, context: Any? = nil) { print(message()) } + static func debug(_ message: @autoclosure () -> Any, _ file: String = #file, _ function: String = #function, line: Int = #line, context: Any? = nil) { print(message()) } + static func info(_ message: @autoclosure () -> Any, _ file: String = #file, _ function: String = #function, line: Int = #line, context: Any? = nil) { print(message()) } + static func warning(_ message: @autoclosure () -> Any, _ file: String = #file, _ function: String = #function, line: Int = #line, context: Any? = nil) { print(message()) } + static func error(_ message: @autoclosure () -> StaticString, _ file: String = #file, _ function: String = #function, line: Int = #line, context: Any? = nil) { print(message()) } diff --git a/RiotSwiftUI/Modules/Common/Logging/UILog.swift b/RiotSwiftUI/Modules/Common/Logging/UILog.swift index ee0c4f22b..97fc113e4 100644 --- a/RiotSwiftUI/Modules/Common/Logging/UILog.swift +++ b/RiotSwiftUI/Modules/Common/Logging/UILog.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,54 +20,48 @@ import Foundation /// /// It can be configured at runtime with a suitable logger. class UILog: LoggerProtocol { - static var _logger: LoggerProtocol.Type? static func configure(logger: LoggerProtocol.Type) { _logger = logger } - static func verbose( - _ message: @autoclosure () -> Any, - _ file: String = #file, - _ function: String = #function, - line: Int = #line, - context: Any? = nil) { + static func verbose(_ message: @autoclosure () -> Any, + _ file: String = #file, + _ function: String = #function, + line: Int = #line, + context: Any? = nil) { _logger?.verbose(message(), file, function, line: line, context: context) } - static func debug( - _ message: @autoclosure () -> Any, - _ file: String = #file, - _ function: String = #function, - line: Int = #line, - context: Any? = nil) { + static func debug(_ message: @autoclosure () -> Any, + _ file: String = #file, + _ function: String = #function, + line: Int = #line, + context: Any? = nil) { _logger?.debug(message(), file, function, line: line, context: context) } - static func info( - _ message: @autoclosure () -> Any, - _ file: String = #file, - _ function: String = #function, - line: Int = #line, - context: Any? = nil) { + static func info(_ message: @autoclosure () -> Any, + _ file: String = #file, + _ function: String = #function, + line: Int = #line, + context: Any? = nil) { _logger?.info(message(), file, function, line: line, context: context) } - static func warning( - _ message: @autoclosure () -> Any, - _ file: String = #file, - _ function: String = #function, - line: Int = #line, - context: Any? = nil) { + static func warning(_ message: @autoclosure () -> Any, + _ file: String = #file, + _ function: String = #function, + line: Int = #line, + context: Any? = nil) { _logger?.warning(message(), file, function, line: line, context: context) } - static func error( - _ message: @autoclosure () -> StaticString, - _ file: String = #file, - _ function: String = #function, - line: Int = #line, - context: Any? = nil) { + static func error(_ message: @autoclosure () -> StaticString, + _ file: String = #file, + _ function: String = #function, + line: Int = #line, + context: Any? = nil) { _logger?.error(message(), file, function, line: line, context: context) } } diff --git a/RiotSwiftUI/Modules/Common/Mock/MockAppScreens.swift b/RiotSwiftUI/Modules/Common/Mock/MockAppScreens.swift index 8d5a62e63..05cc50234 100644 --- a/RiotSwiftUI/Modules/Common/Mock/MockAppScreens.swift +++ b/RiotSwiftUI/Modules/Common/Mock/MockAppScreens.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -63,4 +63,3 @@ enum MockAppScreens { MockSpaceSelectorScreenState.self ] } - diff --git a/RiotSwiftUI/Modules/Common/Mock/MockScreenState.swift b/RiotSwiftUI/Modules/Common/Mock/MockScreenState.swift index 073d32381..0129807cd 100644 --- a/RiotSwiftUI/Modules/Common/Mock/MockScreenState.swift +++ b/RiotSwiftUI/Modules/Common/Mock/MockScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,12 +24,11 @@ protocol MockScreenState { } extension MockScreenState { - /// Get a list of the screens for every screen state. static var stateRenderer: StateRenderer { - let depsAndViews = screenStates.map(\.screenView) - let deps = depsAndViews.map({ $0.0 }) - let views = depsAndViews.map({ $0.1 }) + let depsAndViews = screenStates.map(\.screenView) + let deps = depsAndViews.map(\.0) + let views = depsAndViews.map(\.1) let titles = screenStates.map(\.title) var states = [ScreenStateInfo]() @@ -45,7 +44,7 @@ extension MockScreenState { /// All available screen state keys static var screenNames: [String] { - screenStates.map { $0.title } + screenStates.map(\.title) } /// A title to represent the screen and it's screen state @@ -54,12 +53,12 @@ extension MockScreenState { } private func simpleTypeName(_ type: Any) -> String { - String(describing: type).components(separatedBy: .punctuationCharacters).filter { $0.count > 0}.last! + String(describing: type).components(separatedBy: .punctuationCharacters).filter { $0.count > 0 }.last! } } extension MockScreenState where Self: CaseIterable { static var screenStates: [MockScreenState] { - return Array(self.allCases) + Array(allCases) } } diff --git a/RiotSwiftUI/Modules/Common/Mock/ScreenList.swift b/RiotSwiftUI/Modules/Common/Mock/ScreenList.swift index 6f7f221b3..91cf8937f 100644 --- a/RiotSwiftUI/Modules/Common/Mock/ScreenList.swift +++ b/RiotSwiftUI/Modules/Common/Mock/ScreenList.swift @@ -13,11 +13,9 @@ // See the License for the specific language governing permissions and // limitations under the License. - import SwiftUI struct ScreenList: View { - private let allStates: [ScreenStateInfo] @State private var searchQuery = "" @@ -25,8 +23,9 @@ struct ScreenList: View { init(screens: [MockScreenState.Type]) { let states = screens + // swiftformat:disable:next preferKeyPath .map { $0.stateRenderer } - .flatMap { $0.states } + .flatMap(\.states) allStates = states filteredStates = states diff --git a/RiotSwiftUI/Modules/Common/Mock/ScreenStateInfo.swift b/RiotSwiftUI/Modules/Common/Mock/ScreenStateInfo.swift index 6ebc6f591..0534c80dc 100644 --- a/RiotSwiftUI/Modules/Common/Mock/ScreenStateInfo.swift +++ b/RiotSwiftUI/Modules/Common/Mock/ScreenStateInfo.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Common/Mock/StateRenderer.swift b/RiotSwiftUI/Modules/Common/Mock/StateRenderer.swift index 207146794..627a54803 100644 --- a/RiotSwiftUI/Modules/Common/Mock/StateRenderer.swift +++ b/RiotSwiftUI/Modules/Common/Mock/StateRenderer.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,7 +35,7 @@ class StateRenderer { addNavigation: Bool = false ) -> some View { Group { - ForEach(0..(_ wrap: Bool, view: V) -> some View { if wrap { - NavigationView{ + NavigationView { view .navigationBarTitleDisplayMode(.inline) } diff --git a/RiotSwiftUI/Modules/Common/Test/UI/MockScreenTest.swift b/RiotSwiftUI/Modules/Common/Test/UI/MockScreenTest.swift index 3c00337d1..d5be4d0e4 100644 --- a/RiotSwiftUI/Modules/Common/Test/UI/MockScreenTest.swift +++ b/RiotSwiftUI/Modules/Common/Test/UI/MockScreenTest.swift @@ -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 RiotSwiftUI +import XCTest /// XCTestCase subclass to ease testing of `MockScreenState`. /// Launches the app with an environment variable used to disable animations. @@ -26,7 +26,7 @@ import RiotSwiftUI class MockScreenTestCase: XCTestCase { let app = XCUIApplication() - open override func setUpWithError() throws { + override open func setUpWithError() throws { app.launchEnvironment = ["IS_RUNNING_UI_TESTS": "1"] app.launch() } diff --git a/RiotSwiftUI/Modules/Common/Test/UI/XCUIApplication+Riot.swift b/RiotSwiftUI/Modules/Common/Test/UI/XCUIApplication+Riot.swift index 09e5799f7..a2e7dc2b5 100644 --- a/RiotSwiftUI/Modules/Common/Test/UI/XCUIApplication+Riot.swift +++ b/RiotSwiftUI/Modules/Common/Test/UI/XCUIApplication+Riot.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,11 +23,11 @@ extension XCUIApplication { textFields["searchQueryTextField"].tap() typeText(identifier) - let button = self.buttons[identifier] + let button = buttons[identifier] let footer = staticTexts["footerText"] - while !button.isHittable && !footer.isHittable { - self.tables.firstMatch.swipeUp() + while !button.isHittable, !footer.isHittable { + tables.firstMatch.swipeUp() } button.tap() diff --git a/RiotSwiftUI/Modules/Common/Test/XCTestPublisherExtensions.swift b/RiotSwiftUI/Modules/Common/Test/XCTestPublisherExtensions.swift index 11db89923..d749ec858 100644 --- a/RiotSwiftUI/Modules/Common/Test/XCTestPublisherExtensions.swift +++ b/RiotSwiftUI/Modules/Common/Test/XCTestPublisherExtensions.swift @@ -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 extension XCTestCase { /// XCTest utility to wait for results from publishers, so that the output can be used for assertions. @@ -29,11 +29,9 @@ extension XCTestCase { /// - timeout: A timeout after which we give up. /// - Throws: If it can't get the unwrapped result. /// - Returns: The unwrapped result. - func xcAwait( - _ publisher: T, - timeout: TimeInterval = 10 - ) throws -> T.Output { - return try xcAwaitDeferred(publisher, timeout: timeout)() + func xcAwait(_ publisher: T, + timeout: TimeInterval = 10) throws -> T.Output { + try xcAwaitDeferred(publisher, timeout: timeout)() } /// XCTest utility that allows for a deferred wait of results from publishers, so that the output can be used for assertions. @@ -48,12 +46,10 @@ extension XCTestCase { /// - publisher: The publisher to wait on. /// - timeout: A timeout after which we give up. /// - Returns: A closure that starts the waiting of results when called. The closure will return the unwrapped result. - func xcAwaitDeferred( - _ publisher: T, - timeout: TimeInterval = 10 - ) -> (() throws -> (T.Output)) { + func xcAwaitDeferred(_ publisher: T, + timeout: TimeInterval = 10) -> (() throws -> (T.Output)) { var result: Result? - let expectation = self.expectation(description: "Awaiting publisher") + let expectation = expectation(description: "Awaiting publisher") let cancellable = publisher.sink( receiveCompletion: { completion in diff --git a/RiotSwiftUI/Modules/Common/Theme/ThemeIdentifierExtensions.swift b/RiotSwiftUI/Modules/Common/Theme/ThemeIdentifierExtensions.swift index d5401d27e..90a05a540 100644 --- a/RiotSwiftUI/Modules/Common/Theme/ThemeIdentifierExtensions.swift +++ b/RiotSwiftUI/Modules/Common/Theme/ThemeIdentifierExtensions.swift @@ -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 DesignKit +import Foundation extension ThemeIdentifier { fileprivate static let defaultTheme = DefaultThemeSwiftUI() diff --git a/RiotSwiftUI/Modules/Common/Theme/ThemeKey.swift b/RiotSwiftUI/Modules/Common/Theme/ThemeKey.swift index a2e742b7f..79403c0dc 100644 --- a/RiotSwiftUI/Modules/Common/Theme/ThemeKey.swift +++ b/RiotSwiftUI/Modules/Common/Theme/ThemeKey.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,35 +14,35 @@ // limitations under the License. // +import DesignKit import Foundation import SwiftUI -import DesignKit private struct ThemeKey: EnvironmentKey { static let defaultValue = ThemePublisher.shared.theme } extension EnvironmentValues { - var theme: ThemeSwiftUI { - get { self[ThemeKey.self] } - set { self[ThemeKey.self] = newValue } - } + var theme: ThemeSwiftUI { + get { self[ThemeKey.self] } + set { self[ThemeKey.self] = newValue } + } } extension View { /// A theme modifier for setting the theme for this view and all its descendants in the hierarchy. /// - Parameter theme: A theme to be set as the environment value. /// - Returns: The target view with the theme applied. - func theme(_ theme: ThemeSwiftUI) -> some View { - environment(\.theme, theme) - } + func theme(_ theme: ThemeSwiftUI) -> some View { + environment(\.theme, theme) + } } extension View { /// A theme modifier for setting the theme by id for this view and all its descendants in the hierarchy. /// - Parameter themeId: ThemeIdentifier of a theme to be set as the environment value. /// - Returns: The target view with the theme applied. - func theme(_ themeId: ThemeIdentifier) -> some View { - return environment(\.theme, themeId.themeSwiftUI) - } + func theme(_ themeId: ThemeIdentifier) -> some View { + environment(\.theme, themeId.themeSwiftUI) + } } diff --git a/RiotSwiftUI/Modules/Common/Theme/ThemePublisher.swift b/RiotSwiftUI/Modules/Common/Theme/ThemePublisher.swift index ff0a39eca..1dccf7058 100644 --- a/RiotSwiftUI/Modules/Common/Theme/ThemePublisher.swift +++ b/RiotSwiftUI/Modules/Common/Theme/ThemePublisher.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,21 +14,20 @@ // limitations under the License. // -import Foundation import Combine +import Foundation /// Provides the theme and theme updates to SwiftUI. /// /// Replaces the old ThemeObserver. Riot app can push updates to this class /// removing the dependency of this class on the `ThemeService`. class ThemePublisher: ObservableObject { - - private static var _shared: ThemePublisher? = nil + private static var _shared: ThemePublisher? static var shared: ThemePublisher { - if _shared == nil { - configure(themeId: .light) - } - return _shared! + if _shared == nil { + configure(themeId: .light) + } + return _shared! } @Published private(set) var theme: ThemeSwiftUI @@ -38,7 +37,7 @@ class ThemePublisher: ObservableObject { } init(themeId: ThemeIdentifier) { - _theme = Published.init(initialValue: themeId.themeSwiftUI) + _theme = Published(initialValue: themeId.themeSwiftUI) } func republish(themeIdPublisher: AnyPublisher) { diff --git a/RiotSwiftUI/Modules/Common/Theme/ThemeSwiftUI.swift b/RiotSwiftUI/Modules/Common/Theme/ThemeSwiftUI.swift index f5a15424f..930338076 100644 --- a/RiotSwiftUI/Modules/Common/Theme/ThemeSwiftUI.swift +++ b/RiotSwiftUI/Modules/Common/Theme/ThemeSwiftUI.swift @@ -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 DesignKit +import Foundation protocol ThemeSwiftUI: ThemeSwiftUIType { var identifier: ThemeIdentifier { get } diff --git a/RiotSwiftUI/Modules/Common/Theme/ThemeUsersColorsExtension.swift b/RiotSwiftUI/Modules/Common/Theme/ThemeUsersColorsExtension.swift index ad1eeb222..a75c2f2be 100644 --- a/RiotSwiftUI/Modules/Common/Theme/ThemeUsersColorsExtension.swift +++ b/RiotSwiftUI/Modules/Common/Theme/ThemeUsersColorsExtension.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import Foundation import SwiftUI extension ThemeSwiftUI { - /// Get the stable display user color based on userId. /// - Parameter userId: The user id used to hash. /// - Returns: The SwiftUI color for the associated userId. diff --git a/RiotSwiftUI/Modules/Common/Theme/Themes/DarkThemeSwiftUI.swift b/RiotSwiftUI/Modules/Common/Theme/Themes/DarkThemeSwiftUI.swift index 0e9250070..f418a0203 100644 --- a/RiotSwiftUI/Modules/Common/Theme/Themes/DarkThemeSwiftUI.swift +++ b/RiotSwiftUI/Modules/Common/Theme/Themes/DarkThemeSwiftUI.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,12 +14,12 @@ // limitations under the License. // -import Foundation import DesignKit +import Foundation struct DarkThemeSwiftUI: ThemeSwiftUI { var identifier: ThemeIdentifier = .dark - let isDark: Bool = true + let isDark = true var colors: ColorSwiftUI = DarkColors.swiftUI - var fonts: FontSwiftUI = FontSwiftUI(values: ElementFonts()) + var fonts = FontSwiftUI(values: ElementFonts()) } diff --git a/RiotSwiftUI/Modules/Common/Theme/Themes/DefaultThemeSwiftUI.swift b/RiotSwiftUI/Modules/Common/Theme/Themes/DefaultThemeSwiftUI.swift index 85ba4d810..d0b12fd79 100644 --- a/RiotSwiftUI/Modules/Common/Theme/Themes/DefaultThemeSwiftUI.swift +++ b/RiotSwiftUI/Modules/Common/Theme/Themes/DefaultThemeSwiftUI.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,12 +14,12 @@ // limitations under the License. // -import Foundation import DesignKit +import Foundation struct DefaultThemeSwiftUI: ThemeSwiftUI { var identifier: ThemeIdentifier = .light - let isDark: Bool = false + let isDark = false var colors: ColorSwiftUI = LightColors.swiftUI - var fonts: FontSwiftUI = FontSwiftUI(values: ElementFonts()) + var fonts = FontSwiftUI(values: ElementFonts()) } diff --git a/RiotSwiftUI/Modules/Common/Util/BorderModifier.swift b/RiotSwiftUI/Modules/Common/Util/BorderModifier.swift index 6d5ad7aef..f88e8141f 100644 --- a/RiotSwiftUI/Modules/Common/Util/BorderModifier.swift +++ b/RiotSwiftUI/Modules/Common/Util/BorderModifier.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ import SwiftUI struct BorderModifier: ViewModifier { - var color: Color var borderWidth: CGFloat var shape: Shape diff --git a/RiotSwiftUI/Modules/Common/Util/BorderedInputFieldStyle.swift b/RiotSwiftUI/Modules/Common/Util/BorderedInputFieldStyle.swift index fe75aa300..6859e4712 100644 --- a/RiotSwiftUI/Modules/Common/Util/BorderedInputFieldStyle.swift +++ b/RiotSwiftUI/Modules/Common/Util/BorderedInputFieldStyle.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,20 +15,19 @@ // import Foundation -import SwiftUI import Introspect +import SwiftUI /// A bordered style of text input /// /// As defined in: /// https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=2039%3A26415 struct BorderedInputFieldStyle: TextFieldStyle { - @Environment(\.theme) private var theme: ThemeSwiftUI @Environment(\.isEnabled) private var isEnabled: Bool - var isEditing: Bool = false - var isError: Bool = false + var isEditing = false + var isError = false private var borderColor: Color { if isError { @@ -47,7 +46,7 @@ struct BorderedInputFieldStyle: TextFieldStyle { } private var textColor: Color { - if (theme.identifier == ThemeIdentifier.dark) { + if theme.identifier == ThemeIdentifier.dark { return (isEnabled ? theme.colors.primaryContent : theme.colors.tertiaryContent) } else { return (isEnabled ? theme.colors.primaryContent : theme.colors.quarterlyContent) @@ -55,18 +54,18 @@ struct BorderedInputFieldStyle: TextFieldStyle { } private var backgroundColor: Color { - if !isEnabled && (theme.identifier == ThemeIdentifier.dark) { + if !isEnabled, theme.identifier == ThemeIdentifier.dark { return theme.colors.quinaryContent } return theme.colors.background } private var placeholderColor: Color { - return theme.colors.tertiaryContent + theme.colors.tertiaryContent } private var borderWidth: CGFloat { - return isEditing || isError ? 2.0 : 1.5 + isEditing || isError ? 2.0 : 1.5 } func _body(configuration: TextField<_Label>) -> some View { diff --git a/RiotSwiftUI/Modules/Common/Util/ClearViewModifier.swift b/RiotSwiftUI/Modules/Common/Util/ClearViewModifier.swift index 7eb67d39c..209c61aa1 100644 --- a/RiotSwiftUI/Modules/Common/Util/ClearViewModifier.swift +++ b/RiotSwiftUI/Modules/Common/Util/ClearViewModifier.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,7 @@ import SwiftUI extension ThemableTextEditor { func showClearButton(text: Binding, alignment: VerticalAlignment = .top) -> some View { - return modifier(ClearViewModifier(alignment: alignment, text: text)) + modifier(ClearViewModifier(alignment: alignment, text: text)) } } diff --git a/RiotSwiftUI/Modules/Common/Util/InlineTextButton.swift b/RiotSwiftUI/Modules/Common/Util/InlineTextButton.swift index fa394b827..e5673b12c 100644 --- a/RiotSwiftUI/Modules/Common/Util/InlineTextButton.swift +++ b/RiotSwiftUI/Modules/Common/Util/InlineTextButton.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ import SwiftUI @available(iOS, introduced: 14.0, deprecated: 15.0, message: "Use Text with an AttributedString instead that includes a link and handle the tap by adding an OpenURLAction to the environment.") /// A `Button`, that fakes having a tappable string inside of a regular string. struct InlineTextButton: View { - private struct StringComponent { let string: Substring let isTinted: Bool @@ -33,7 +32,6 @@ struct InlineTextButton: View { private let components: [StringComponent] private let action: () -> Void - // MARK: - Setup /// Creates a new `InlineTextButton`. @@ -43,7 +41,7 @@ struct InlineTextButton: View { /// - action: The action to perform when tapping the button. internal init(_ mainText: String, tappableText: String, action: @escaping () -> Void) { guard let range = mainText.range(of: "%@") else { - self.components = [StringComponent(string: Substring(mainText), isTinted: false)] + components = [StringComponent(string: Substring(mainText), isTinted: false)] self.action = action return } @@ -52,7 +50,7 @@ struct InlineTextButton: View { let middleComponent = StringComponent(string: Substring(tappableText), isTinted: true) let lastComponent = StringComponent(string: mainText[range.upperBound...], isTinted: false) - self.components = [firstComponent, middleComponent, lastComponent] + components = [firstComponent, middleComponent, lastComponent] self.action = action } @@ -63,7 +61,7 @@ struct InlineTextButton: View { EmptyView() } .buttonStyle(Style(components: components)) - .accessibilityLabel(components.map { $0.string }.joined()) + .accessibilityLabel(components.map(\.string).joined()) } private struct Style: ButtonStyle { diff --git a/RiotSwiftUI/Modules/Common/Util/MultilineTextField.swift b/RiotSwiftUI/Modules/Common/Util/MultilineTextField.swift index 5e20f11b0..08e1712ab 100644 --- a/RiotSwiftUI/Modules/Common/Util/MultilineTextField.swift +++ b/RiotSwiftUI/Modules/Common/Util/MultilineTextField.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,14 +17,13 @@ import SwiftUI struct MultilineTextField: View { - @Environment(\.theme) private var theme: ThemeSwiftUI @Binding private var text: String @State private var dynamicHeight: CGFloat = 100 @State private var isEditing = false - private var placeholder: String = "" + private var placeholder = "" private var showingPlaceholder: Bool { text.isEmpty @@ -32,11 +31,11 @@ struct MultilineTextField: View { init(_ placeholder: String, text: Binding) { self.placeholder = placeholder - self._text = text + _text = text } private var textColor: Color { - if (theme.identifier == ThemeIdentifier.dark) { + if theme.identifier == ThemeIdentifier.dark { return theme.colors.primaryContent } else { return theme.colors.primaryContent @@ -44,11 +43,11 @@ struct MultilineTextField: View { } private var backgroundColor: Color { - return theme.colors.background + theme.colors.background } private var placeholderColor: Color { - return theme.colors.tertiaryContent + theme.colors.tertiaryContent } private var borderColor: Color { @@ -60,7 +59,7 @@ struct MultilineTextField: View { } private var borderWidth: CGFloat { - return isEditing ? 2.0 : 1.5 + isEditing ? 2.0 : 1.5 } var body: some View { @@ -91,7 +90,7 @@ struct MultilineTextField: View { } } -fileprivate struct UITextViewWrapper: UIViewRepresentable { +private struct UITextViewWrapper: UIViewRepresentable { typealias UIViewType = UITextView @Binding var text: String @@ -115,8 +114,8 @@ fileprivate struct UITextViewWrapper: UIViewRepresentable { } func updateUIView(_ uiView: UITextView, context: UIViewRepresentableContext) { - if uiView.text != self.text { - uiView.text = self.text + if uiView.text != text { + uiView.text = text } UITextViewWrapper.recalculateHeight(view: uiView, result: $calculatedHeight) @@ -132,7 +131,7 @@ fileprivate struct UITextViewWrapper: UIViewRepresentable { } func makeCoordinator() -> Coordinator { - return Coordinator(text: $text, height: $calculatedHeight, isEditing: $isEditing) + Coordinator(text: $text, height: $calculatedHeight, isEditing: $isEditing) } final class Coordinator: NSObject, UITextViewDelegate { @@ -142,7 +141,7 @@ fileprivate struct UITextViewWrapper: UIViewRepresentable { init(text: Binding, height: Binding, isEditing: Binding) { self.text = text - self.calculatedHeight = height + calculatedHeight = height self.isEditing = isEditing } @@ -171,9 +170,8 @@ fileprivate struct UITextViewWrapper: UIViewRepresentable { } struct MultilineTextField_Previews: PreviewProvider { - static var previews: some View { - return Group { + Group { VStack { PreviewWrapper() PlaceholderPreviewWrapper() diff --git a/RiotSwiftUI/Modules/Common/Util/OptionButton.swift b/RiotSwiftUI/Modules/Common/Util/OptionButton.swift index 17e54bbda..7758ae5c7 100644 --- a/RiotSwiftUI/Modules/Common/Util/OptionButton.swift +++ b/RiotSwiftUI/Modules/Common/Util/OptionButton.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,11 +17,9 @@ import SwiftUI struct OptionButton: View { - // MARK: - Style private struct Style: ButtonStyle { - func makeBody(configuration: Configuration) -> some View { configuration.label .scaleEffect(configuration.isPressed ? 0.97 : 1) @@ -61,8 +59,7 @@ struct OptionButton: View { .background(theme.colors.quinaryContent) .foregroundColor(theme.colors.secondaryContent) .clipShape(RoundedRectangle(cornerRadius: 8)) - } - ) + }) .buttonStyle(Style()) } } @@ -73,14 +70,14 @@ struct OptionButton_Previews: PreviewProvider { static var previews: some View { Group { VStack { - OptionButton(icon: Asset.Images.spaceTypeIcon.image, title: "A title", detailMessage: "Some details for this option", action: {}).theme(.light) - OptionButton(icon: nil, title: "A title", detailMessage: "Some details for this option", action: {}).theme(.light) - OptionButton(icon: nil, title: "A title", detailMessage: nil, action: {}).theme(.light) + OptionButton(icon: Asset.Images.spaceTypeIcon.image, title: "A title", detailMessage: "Some details for this option", action: { }).theme(.light) + OptionButton(icon: nil, title: "A title", detailMessage: "Some details for this option", action: { }).theme(.light) + OptionButton(icon: nil, title: "A title", detailMessage: nil, action: { }).theme(.light) } VStack { - OptionButton(icon: Asset.Images.spaceTypeIcon.image, title: "A title", detailMessage: "Some details for this option", action: {}).theme(.dark) - OptionButton(icon: nil, title: "A title", detailMessage: "Some details for this option", action: {}).theme(.dark) - OptionButton(icon: nil, title: "A title", detailMessage: nil, action: {}).theme(.dark) + OptionButton(icon: Asset.Images.spaceTypeIcon.image, title: "A title", detailMessage: "Some details for this option", action: { }).theme(.dark) + OptionButton(icon: nil, title: "A title", detailMessage: "Some details for this option", action: { }).theme(.dark) + OptionButton(icon: nil, title: "A title", detailMessage: nil, action: { }).theme(.dark) }.preferredColorScheme(.dark) } .padding() diff --git a/RiotSwiftUI/Modules/Common/Util/PasswordButtonModifier.swift b/RiotSwiftUI/Modules/Common/Util/PasswordButtonModifier.swift index 94fd8525a..0e0f38586 100644 --- a/RiotSwiftUI/Modules/Common/Util/PasswordButtonModifier.swift +++ b/RiotSwiftUI/Modules/Common/Util/PasswordButtonModifier.swift @@ -19,7 +19,6 @@ import SwiftUI /// Adds a reveal password button (e.g. an eye button) on the /// right side of the view. For use with `ThemableTextField`. struct PasswordButtonModifier: ViewModifier { - // MARK: - Properties let text: String diff --git a/RiotSwiftUI/Modules/Common/Util/PrimaryActionButtonStyle.swift b/RiotSwiftUI/Modules/Common/Util/PrimaryActionButtonStyle.swift index 461f232ff..07a07f49a 100644 --- a/RiotSwiftUI/Modules/Common/Util/PrimaryActionButtonStyle.swift +++ b/RiotSwiftUI/Modules/Common/Util/PrimaryActionButtonStyle.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,7 +20,7 @@ struct PrimaryActionButtonStyle: ButtonStyle { @Environment(\.theme) private var theme @Environment(\.isEnabled) private var isEnabled - var customColor: Color? = nil + var customColor: Color? private var fontColor: Color { // Always white unless disabled with a dark theme. @@ -65,7 +65,7 @@ struct PrimaryActionButtonStyle_Previews: PreviewProvider { .buttonStyle(PrimaryActionButtonStyle(customColor: .clear)) Button("Red BG") { } - .buttonStyle(PrimaryActionButtonStyle(customColor: .red)) + .buttonStyle(PrimaryActionButtonStyle(customColor: .red)) } .padding() } diff --git a/RiotSwiftUI/Modules/Common/Util/RadioButton.swift b/RiotSwiftUI/Modules/Common/Util/RadioButton.swift index 69e408410..77835c45f 100644 --- a/RiotSwiftUI/Modules/Common/Util/RadioButton.swift +++ b/RiotSwiftUI/Modules/Common/Util/RadioButton.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ import SwiftUI struct RadioButton: View { - // MARK: - Properties var title: String @@ -61,8 +60,8 @@ struct RadioButton_Previews: PreviewProvider { static var buttonGroup: some View { VStack { - RadioButton(title: "A title", selected: false, action: {}) - RadioButton(title: "A title", selected: true, action: {}) + RadioButton(title: "A title", selected: false, action: { }) + RadioButton(title: "A title", selected: true, action: { }) } } } diff --git a/RiotSwiftUI/Modules/Common/Util/ReadableFrameModifier.swift b/RiotSwiftUI/Modules/Common/Util/ReadableFrameModifier.swift index d04f413b2..257431e35 100644 --- a/RiotSwiftUI/Modules/Common/Util/ReadableFrameModifier.swift +++ b/RiotSwiftUI/Modules/Common/Util/ReadableFrameModifier.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,7 @@ import SwiftUI /// Positions this view within an invisible frame that fills the width of its parent view, /// whilst limiting the width of the content to a readable size (which is customizable). -fileprivate struct ReadableFrameModifier: ViewModifier { +private struct ReadableFrameModifier: ViewModifier { var maxWidth: CGFloat func body(content: Content) -> some View { diff --git a/RiotSwiftUI/Modules/Common/Util/ResponderManager.swift b/RiotSwiftUI/Modules/Common/Util/ResponderManager.swift index 21738bae9..3148c2cf4 100644 --- a/RiotSwiftUI/Modules/Common/Util/ResponderManager.swift +++ b/RiotSwiftUI/Modules/Common/Util/ResponderManager.swift @@ -18,8 +18,7 @@ import UIKit /// `ResponderManager` is used to chain `SwiftUI` text editing views that embed `UIKit` text editing views using `UIViewRepresentable` class ResponderManager { - - private static var tagIndex: Int = 1000 + private static var tagIndex = 1000 private static var registeredResponders = NSMapTable(keyOptions: .strongMemory, valueOptions: .weakMemory) private static var nextIndex: Int { @@ -63,7 +62,7 @@ class ResponderManager { /// Tries to get the focused registered responder and give the focus to it's next responder /// - Returns: `True` if the next responder has been found and is successfully focused. `False` otherwise. static func makeActiveNextResponder() -> Bool { - guard let firstResponder = self.firstResponder else { + guard let firstResponder = firstResponder else { return false } diff --git a/RiotSwiftUI/Modules/Common/Util/RoundedBorderTextEditor.swift b/RiotSwiftUI/Modules/Common/Util/RoundedBorderTextEditor.swift index 38e50ff19..240b9ebba 100644 --- a/RiotSwiftUI/Modules/Common/Util/RoundedBorderTextEditor.swift +++ b/RiotSwiftUI/Modules/Common/Util/RoundedBorderTextEditor.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,17 +17,16 @@ import SwiftUI struct RoundedBorderTextEditor: View { - // MARK: - Properties - var title: String? = nil + var title: String? let placeHolder: String @Binding var text: String - var textMaxHeight: CGFloat? = nil - var error: String? = nil + var textMaxHeight: CGFloat? + var error: String? - var onTextChanged: ((String) -> Void)? = nil - var onEditingChanged: ((Bool) -> Void)? = nil + var onTextChanged: ((String) -> Void)? + var onEditingChanged: ((Bool) -> Void)? @State private var editing = false @@ -62,7 +61,7 @@ struct RoundedBorderTextEditor: View { }) .showClearButton(text: $text) // Found no good solution here. Hidding next button for the moment - // .modifier(NextViewModifier(alignment: .bottomTrailing, isEditing: $editing)) + // .modifier(NextViewModifier(alignment: .bottomTrailing, isEditing: $editing)) .padding(EdgeInsets(top: 2, leading: 6, bottom: 0, trailing: 0)) .onChange(of: text, perform: { newText in onTextChanged?(newText) @@ -82,7 +81,7 @@ struct RoundedBorderTextEditor: View { } .background(RoundedRectangle(cornerRadius: 8).fill(theme.colors.background)) .overlay(RoundedRectangle(cornerRadius: 8) - .stroke(editing ? theme.colors.accent : (error == nil ? theme.colors.quinaryContent : theme.colors.alert), lineWidth: editing || error != nil ? 2 : 1)) + .stroke(editing ? theme.colors.accent : (error == nil ? theme.colors.quinaryContent : theme.colors.alert), lineWidth: editing || error != nil ? 2 : 1)) .frame(height: textMaxHeight) if let error = self.error { Text(error) @@ -101,7 +100,6 @@ struct RoundedBorderTextEditor: View { struct ThemableTextEditor_Previews: PreviewProvider { static var previews: some View { - Group { sampleView.theme(.light).preferredColorScheme(.light) sampleView.theme(.dark).preferredColorScheme(.dark) diff --git a/RiotSwiftUI/Modules/Common/Util/RoundedBorderTextField.swift b/RiotSwiftUI/Modules/Common/Util/RoundedBorderTextField.swift index c0c69a209..7acf765cc 100644 --- a/RiotSwiftUI/Modules/Common/Util/RoundedBorderTextField.swift +++ b/RiotSwiftUI/Modules/Common/Util/RoundedBorderTextField.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,22 +17,21 @@ import SwiftUI struct RoundedBorderTextField: View { - // MARK: - Properties - var title: String? = nil + var title: String? let placeHolder: String @Binding var text: String - var footerText: String? = nil - var isError: Bool = false + var footerText: String? + var isError = false var isFirstResponder = false - var configuration: UIKitTextInputConfiguration = UIKitTextInputConfiguration() + var configuration = UIKitTextInputConfiguration() @State var isSecureTextVisible = false - var onTextChanged: ((String) -> Void)? = nil - var onEditingChanged: ((Bool) -> Void)? = nil - var onCommit: (() -> Void)? = nil + var onTextChanged: ((String) -> Void)? + var onEditingChanged: ((Bool) -> Void)? + var onCommit: (() -> Void)? // MARK: Private @@ -101,7 +100,7 @@ struct RoundedBorderTextField: View { private var borderColor: Color { if isEditing { return theme.colors.accent - } else if footerText != nil && isError { + } else if footerText != nil, isError { return theme.colors.alert } else { return theme.colors.quinaryContent @@ -118,7 +117,6 @@ struct RoundedBorderTextField: View { struct TextFieldWithError_Previews: PreviewProvider { static var previews: some View { - Group { sampleView.theme(.light).preferredColorScheme(.light) sampleView.theme(.dark).preferredColorScheme(.dark) diff --git a/RiotSwiftUI/Modules/Common/Util/RoundedCornerShape.swift b/RiotSwiftUI/Modules/Common/Util/RoundedCornerShape.swift index 0fc77b56e..e34197eec 100644 --- a/RiotSwiftUI/Modules/Common/Util/RoundedCornerShape.swift +++ b/RiotSwiftUI/Modules/Common/Util/RoundedCornerShape.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import Foundation import SwiftUI struct RoundedCornerShape: Shape { - let radius: CGFloat let corners: UIRectCorner diff --git a/RiotSwiftUI/Modules/Common/Util/SafeBindingCollectionEnumerator.swift b/RiotSwiftUI/Modules/Common/Util/SafeBindingCollectionEnumerator.swift index 92d6135cd..f6a16c21f 100644 --- a/RiotSwiftUI/Modules/Common/Util/SafeBindingCollectionEnumerator.swift +++ b/RiotSwiftUI/Modules/Common/Util/SafeBindingCollectionEnumerator.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,7 +22,6 @@ import SwiftUI Replace with Swift 5.5 bindings enumerator later. */ struct SafeBindingCollectionEnumerator: View { - typealias BoundElement = Binding private let binding: BoundElement private let content: (BoundElement) -> C diff --git a/RiotSwiftUI/Modules/Common/Util/ScreenTrackerViewModifier.swift b/RiotSwiftUI/Modules/Common/Util/ScreenTrackerViewModifier.swift index b8eaf74d2..fe5ec5bb5 100644 --- a/RiotSwiftUI/Modules/Common/Util/ScreenTrackerViewModifier.swift +++ b/RiotSwiftUI/Modules/Common/Util/ScreenTrackerViewModifier.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,6 +33,6 @@ struct ScreenTrackerViewModifier: ViewModifier { extension View { func track(screen: AnalyticsScreen) -> some View { - return self.modifier(ScreenTrackerViewModifier(screen: screen)) + modifier(ScreenTrackerViewModifier(screen: screen)) } } diff --git a/RiotSwiftUI/Modules/Common/Util/SearchBar.swift b/RiotSwiftUI/Modules/Common/Util/SearchBar.swift index 4edaa2e5c..63b3863b9 100644 --- a/RiotSwiftUI/Modules/Common/Util/SearchBar.swift +++ b/RiotSwiftUI/Modules/Common/Util/SearchBar.swift @@ -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 SearchBar: View { - // MARK: - Properties var placeholder: String @@ -49,7 +48,7 @@ struct SearchBar: View { .foregroundColor(theme.colors.quarterlyContent) .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading) - if isEditing && !text.isEmpty { + if isEditing, !text.isEmpty { Button(action: { self.text = "" }) { diff --git a/RiotSwiftUI/Modules/Common/Util/SecondaryActionButtonStyle.swift b/RiotSwiftUI/Modules/Common/Util/SecondaryActionButtonStyle.swift index 8f0eb6aac..917ad1997 100644 --- a/RiotSwiftUI/Modules/Common/Util/SecondaryActionButtonStyle.swift +++ b/RiotSwiftUI/Modules/Common/Util/SecondaryActionButtonStyle.swift @@ -20,7 +20,7 @@ struct SecondaryActionButtonStyle: ButtonStyle { @Environment(\.theme) private var theme @Environment(\.isEnabled) private var isEnabled - var customColor: Color? = nil + var customColor: Color? func makeBody(configuration: Self.Configuration) -> some View { configuration.label @@ -29,8 +29,8 @@ struct SecondaryActionButtonStyle: ButtonStyle { .foregroundColor(customColor ?? theme.colors.accent) .font(theme.fonts.body) .background(RoundedRectangle(cornerRadius: 8) - .strokeBorder() - .foregroundColor(customColor ?? theme.colors.accent)) + .strokeBorder() + .foregroundColor(customColor ?? theme.colors.accent)) .opacity(opacity(when: configuration.isPressed)) } @@ -62,7 +62,7 @@ struct SecondaryActionButtonStyle_Previews: PreviewProvider { .disabled(true) Button("Red BG") { } - .buttonStyle(SecondaryActionButtonStyle(customColor: .red)) + .buttonStyle(SecondaryActionButtonStyle(customColor: .red)) Button { } label: { Text("Custom") diff --git a/RiotSwiftUI/Modules/Common/Util/StyledText.swift b/RiotSwiftUI/Modules/Common/Util/StyledText.swift index 1c4b0a74f..0ed73d4a9 100644 --- a/RiotSwiftUI/Modules/Common/Util/StyledText.swift +++ b/RiotSwiftUI/Modules/Common/Util/StyledText.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,14 +14,13 @@ // limitations under the License. // -import SwiftUI import DesignKit +import SwiftUI @available(iOS, introduced: 14.0, deprecated: 15.0, message: "Use Text with an AttributedString instead.") /// A `Text` view that renders attributed strings with their `.font` and `.foregroundColor` attributes. /// This view is a workaround for iOS 13/14 not supporting `AttributedString`. struct StyledText: View { - // MARK: - Properties // MARK: Private @@ -31,8 +30,8 @@ struct StyledText: View { /// A string with a bold property. private struct StringComponent { let string: String - var font: Font? = nil - var color: Color? = nil + var font: Font? + var color: Color? } /// Internal representation of the string as composable parts. @@ -47,7 +46,7 @@ struct StyledText: View { let range = NSRange(location: 0, length: attributedString.length) let string = attributedString.string as NSString - attributedString.enumerateAttributes(in: range, options: []) { attributes, range, stop in + attributedString.enumerateAttributes(in: range, options: []) { attributes, range, _ in let font = attributes[.font] as? UIFont let color = attributes[.foregroundColor] as? UIColor @@ -66,7 +65,7 @@ struct StyledText: View { /// Creates a `StyledText` using a plain string. /// - Parameter string: The plain string to display init(_ string: String) { - self.components = [StringComponent(string: string, font: nil)] + components = [StringComponent(string: string, font: nil)] } // MARK: - Views @@ -80,7 +79,6 @@ struct StyledText: View { } } - struct StyledText_Previews: PreviewProvider { static func prettyText() -> NSAttributedString { let string = NSMutableAttributedString(string: "T", attributes: [ diff --git a/RiotSwiftUI/Modules/Common/Util/ThemableButton.swift b/RiotSwiftUI/Modules/Common/Util/ThemableButton.swift index 61a066c38..61dd9a84e 100644 --- a/RiotSwiftUI/Modules/Common/Util/ThemableButton.swift +++ b/RiotSwiftUI/Modules/Common/Util/ThemableButton.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,11 +17,9 @@ import SwiftUI struct ThemableButton: View { - // MARK: - Style private struct Style: ButtonStyle { - func makeBody(configuration: Configuration) -> some View { configuration.label .scaleEffect(configuration.isPressed ? 0.97 : 1) @@ -67,12 +65,12 @@ struct ThemableButton_Previews: PreviewProvider { static var previews: some View { Group { VStack(alignment: .center, spacing: 20) { - ThemableButton(icon: Asset.Images.spaceTypeIcon.image, title: "A title", action: {}).theme(.light).preferredColorScheme(.light) - ThemableButton(icon: nil, title: "A title", action: {}).theme(.light).preferredColorScheme(.light) + ThemableButton(icon: Asset.Images.spaceTypeIcon.image, title: "A title", action: { }).theme(.light).preferredColorScheme(.light) + ThemableButton(icon: nil, title: "A title", action: { }).theme(.light).preferredColorScheme(.light) } VStack(alignment: .center, spacing: 20) { - ThemableButton(icon: Asset.Images.spaceTypeIcon.image, title: "A title", action: {}).theme(.dark).preferredColorScheme(.dark) - ThemableButton(icon: nil, title: "A title", action: {}).theme(.dark).preferredColorScheme(.dark) + ThemableButton(icon: Asset.Images.spaceTypeIcon.image, title: "A title", action: { }).theme(.dark).preferredColorScheme(.dark) + ThemableButton(icon: nil, title: "A title", action: { }).theme(.dark).preferredColorScheme(.dark) } } .padding() diff --git a/RiotSwiftUI/Modules/Common/Util/ThemableNavigationBar.swift b/RiotSwiftUI/Modules/Common/Util/ThemableNavigationBar.swift index 2c6fc3727..3f7bf833e 100644 --- a/RiotSwiftUI/Modules/Common/Util/ThemableNavigationBar.swift +++ b/RiotSwiftUI/Modules/Common/Util/ThemableNavigationBar.swift @@ -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 ThemableNavigationBar: View { - // MARK: - Style // MARK: - Properties @@ -36,8 +35,7 @@ struct ThemableNavigationBar: View { @ViewBuilder var body: some View { HStack { - Button(action: {backAction()}) - { + Button(action: { backAction() }) { Image(uiImage: Asset.Images.spacesModalBack.image) .renderingMode(.template) .foregroundColor(theme.colors.secondaryContent) @@ -49,8 +47,7 @@ struct ThemableNavigationBar: View { .foregroundColor(theme.colors.primaryContent) } Spacer() - Button(action: {closeAction()}) - { + Button(action: { closeAction() }) { Image(uiImage: Asset.Images.spacesModalClose.image) .renderingMode(.template) .foregroundColor(theme.colors.secondaryContent) @@ -68,16 +65,16 @@ struct NavigationBar_Previews: PreviewProvider { static var previews: some View { Group { VStack { - ThemableNavigationBar(title: nil, showBackButton: true, backAction: {}, closeAction: {}) - ThemableNavigationBar(title: "Some Title", showBackButton: true, backAction: {}, closeAction: {}) - ThemableNavigationBar(title: nil, showBackButton: false, backAction: {}, closeAction: {}) - ThemableNavigationBar(title: "Some Title", showBackButton: false, backAction: {}, closeAction: {}) + ThemableNavigationBar(title: nil, showBackButton: true, backAction: { }, closeAction: { }) + ThemableNavigationBar(title: "Some Title", showBackButton: true, backAction: { }, closeAction: { }) + ThemableNavigationBar(title: nil, showBackButton: false, backAction: { }, closeAction: { }) + ThemableNavigationBar(title: "Some Title", showBackButton: false, backAction: { }, closeAction: { }) } VStack { - ThemableNavigationBar(title: nil, showBackButton: true, backAction: {}, closeAction: {}).theme(.dark) - ThemableNavigationBar(title: "Some Title", showBackButton: true, backAction: {}, closeAction: {}).theme(.dark) - ThemableNavigationBar(title: nil, showBackButton: false, backAction: {}, closeAction: {}).theme(.dark) - ThemableNavigationBar(title: "Some Title", showBackButton: false, backAction: {}, closeAction: {}).theme(.dark) + ThemableNavigationBar(title: nil, showBackButton: true, backAction: { }, closeAction: { }).theme(.dark) + ThemableNavigationBar(title: "Some Title", showBackButton: true, backAction: { }, closeAction: { }).theme(.dark) + ThemableNavigationBar(title: nil, showBackButton: false, backAction: { }, closeAction: { }).theme(.dark) + ThemableNavigationBar(title: "Some Title", showBackButton: false, backAction: { }, closeAction: { }).theme(.dark) }.preferredColorScheme(.dark) } .padding() diff --git a/RiotSwiftUI/Modules/Common/Util/ThemableTextEditor.swift b/RiotSwiftUI/Modules/Common/Util/ThemableTextEditor.swift index d9f0d1ca7..bdc529822 100644 --- a/RiotSwiftUI/Modules/Common/Util/ThemableTextEditor.swift +++ b/RiotSwiftUI/Modules/Common/Util/ThemableTextEditor.swift @@ -16,20 +16,18 @@ import SwiftUI - struct ThemableTextEditor: UIViewRepresentable { - // MARK: Properties @Binding var text: String - @State var configuration: UIKitTextInputConfiguration = UIKitTextInputConfiguration() + @State var configuration = UIKitTextInputConfiguration() var onEditingChanged: ((_ edit: Bool) -> Void)? // MARK: Private @Environment(\.theme) private var theme: ThemeSwiftUI - private let textView: UITextView = UITextView() + private let textView = UITextView() private let internalParams = InternalParams() // MARK: Setup @@ -37,8 +35,8 @@ struct ThemableTextEditor: UIViewRepresentable { init(text: Binding, configuration: UIKitTextInputConfiguration = UIKitTextInputConfiguration(), onEditingChanged: ((_ edit: Bool) -> Void)? = nil) { - self._text = text - self._configuration = State(initialValue: configuration) + _text = text + _configuration = State(initialValue: configuration) self.onEditingChanged = onEditingChanged ResponderManager.register(view: textView) @@ -63,8 +61,8 @@ struct ThemableTextEditor: UIViewRepresentable { uiView.textColor = UIColor(theme.colors.primaryContent) uiView.tintColor = UIColor(theme.colors.accent) - if uiView.text != self.text { - uiView.text = self.text + if uiView.text != text { + uiView.text = text } uiView.keyboardType = configuration.keyboardType @@ -81,7 +79,7 @@ struct ThemableTextEditor: UIViewRepresentable { // MARK: - Private private func replaceText(with newText: String) { - self.text = newText + text = newText } private class InternalParams { @@ -91,7 +89,7 @@ struct ThemableTextEditor: UIViewRepresentable { // MARK: - Coordinator func makeCoordinator() -> Coordinator { - return Coordinator(self) + Coordinator(self) } class Coordinator: NSObject, UITextViewDelegate { diff --git a/RiotSwiftUI/Modules/Common/Util/ThemableTextField.swift b/RiotSwiftUI/Modules/Common/Util/ThemableTextField.swift index fa31d1f02..a179d36ab 100644 --- a/RiotSwiftUI/Modules/Common/Util/ThemableTextField.swift +++ b/RiotSwiftUI/Modules/Common/Util/ThemableTextField.swift @@ -19,18 +19,17 @@ import SwiftUI struct UIKitTextInputConfiguration { var keyboardType: UIKeyboardType = .default var returnKeyType: UIReturnKeyType = .default - var isSecureTextEntry: Bool = false + var isSecureTextEntry = false var autocapitalizationType: UITextAutocapitalizationType = .sentences var autocorrectionType: UITextAutocorrectionType = .default } struct ThemableTextField: UIViewRepresentable { - // MARK: Properties @State var placeholder: String? @Binding var text: String - @State var configuration: UIKitTextInputConfiguration = UIKitTextInputConfiguration() + @State var configuration = UIKitTextInputConfiguration() @Binding var isSecureTextVisible: Bool var onEditingChanged: ((_ edit: Bool) -> Void)? var onCommit: (() -> Void)? @@ -39,7 +38,7 @@ struct ThemableTextField: UIViewRepresentable { @Environment(\.theme) private var theme: ThemeSwiftUI - private let textField: UITextField = UITextField() + private let textField = UITextField() private let internalParams = InternalParams() // MARK: Setup @@ -50,10 +49,10 @@ struct ThemableTextField: UIViewRepresentable { isSecureTextVisible: Binding = .constant(false), onEditingChanged: ((_ edit: Bool) -> Void)? = nil, onCommit: (() -> Void)? = nil) { - self._text = text - self._placeholder = State(initialValue: placeholder) - self._configuration = State(initialValue: configuration) - self._isSecureTextVisible = isSecureTextVisible + _text = text + _placeholder = State(initialValue: placeholder) + _configuration = State(initialValue: configuration) + _isSecureTextVisible = isSecureTextVisible self.onEditingChanged = onEditingChanged self.onCommit = onCommit @@ -84,8 +83,8 @@ struct ThemableTextField: UIViewRepresentable { uiView.textColor = UIColor(theme.colors.primaryContent) uiView.tintColor = UIColor(theme.colors.accent) - if uiView.text != self.text { - uiView.text = self.text + if uiView.text != text { + uiView.text = text } uiView.placeholder = placeholder @@ -103,17 +102,16 @@ struct ThemableTextField: UIViewRepresentable { // MARK: - Private private func replaceText(with newText: String) { - self.text = newText + text = newText } // MARK: - Coordinator func makeCoordinator() -> Coordinator { - return Coordinator(self) + Coordinator(self) } class Coordinator: NSObject, UITextFieldDelegate { - var parent: ThemableTextField init(_ parent: ThemableTextField) { @@ -146,14 +144,13 @@ struct ThemableTextField: UIViewRepresentable { private class InternalParams { var isFirstResponder = false } - } // MARK: - modifiers extension ThemableTextField { func makeFirstResponder() -> ThemableTextField { - return makeFirstResponder(true) + makeFirstResponder(true) } func makeFirstResponder(_ isFirstResponder: Bool) -> ThemableTextField { @@ -167,7 +164,7 @@ extension ThemableTextField { /// - alignment: The vertical alignment of the button in the text field. Default to `center` @ViewBuilder func addButton(_ show: Bool, alignment: VerticalAlignment = .center) -> some View { - if show && configuration.isSecureTextEntry { + if show, configuration.isSecureTextEntry { modifier(PasswordButtonModifier(text: text, isSecureTextVisible: $isSecureTextVisible, alignment: alignment)) diff --git a/RiotSwiftUI/Modules/Common/Util/View+Riot.swift b/RiotSwiftUI/Modules/Common/Util/View+Riot.swift index d126ec8d0..89aae532c 100644 --- a/RiotSwiftUI/Modules/Common/Util/View+Riot.swift +++ b/RiotSwiftUI/Modules/Common/Util/View+Riot.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,7 +20,7 @@ import SwiftUI extension View { @ViewBuilder func isHidden(_ isHidden: Bool) -> some View { if isHidden { - self.hidden() + hidden() } else { self } diff --git a/RiotSwiftUI/Modules/Common/Util/WaitOverlay.swift b/RiotSwiftUI/Modules/Common/Util/WaitOverlay.swift index 60f7315bb..db88cc486 100644 --- a/RiotSwiftUI/Modules/Common/Util/WaitOverlay.swift +++ b/RiotSwiftUI/Modules/Common/Util/WaitOverlay.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import SwiftUI /// A modifier for showing the wait overlay view over a view. struct WaitOverlayModifier: ViewModifier { - var allowUserInteraction: Bool var show: Bool var message: String? @@ -27,15 +26,16 @@ struct WaitOverlayModifier: ViewModifier { func body(content: Content) -> some View { content .modifier(WaitOverlay( - allowUserInteraction: allowUserInteraction, - message: message, - isLoading: show)) + allowUserInteraction: allowUserInteraction, + message: message, + isLoading: show + )) } } extension View { func waitOverlay(show: Bool, message: String? = nil, allowUserInteraction: Bool = true) -> some View { - self.modifier(WaitOverlayModifier(allowUserInteraction: allowUserInteraction, show: show, message: message)) + modifier(WaitOverlayModifier(allowUserInteraction: allowUserInteraction, show: show, message: message)) } } @@ -44,7 +44,7 @@ struct WaitOverlay: ViewModifier { // MARK: - Properties var alignment: Alignment = .center - var allowUserInteraction: Bool = true + var allowUserInteraction = true var message: String? var isLoading: Bool @@ -66,8 +66,7 @@ struct WaitOverlay: ViewModifier { // MARK: - Public - public func body(content: Content) -> some View - { + public func body(content: Content) -> some View { ZStack { content if isLoading { @@ -89,7 +88,7 @@ struct WaitOverlay: ViewModifier { } .padding(12) .background(RoundedRectangle(cornerRadius: 8, style: .continuous) - .fill(theme.colors.navigation.opacity(0.9))) + .fill(theme.colors.navigation.opacity(0.9))) } .edgesIgnoringSafeArea(.all) .transition(.opacity) @@ -103,24 +102,24 @@ struct WaitOverlay_Previews: PreviewProvider { static var previews: some View { Group { VStack { - ThemableNavigationBar(title: nil, showBackButton: true, backAction: {}, closeAction: {}) - ThemableNavigationBar(title: "Some Title", showBackButton: true, backAction: {}, closeAction: {}) - ThemableNavigationBar(title: nil, showBackButton: false, backAction: {}, closeAction: {}) - ThemableNavigationBar(title: "Some Title", showBackButton: false, backAction: {}, closeAction: {}) + ThemableNavigationBar(title: nil, showBackButton: true, backAction: { }, closeAction: { }) + ThemableNavigationBar(title: "Some Title", showBackButton: true, backAction: { }, closeAction: { }) + ThemableNavigationBar(title: nil, showBackButton: false, backAction: { }, closeAction: { }) + ThemableNavigationBar(title: "Some Title", showBackButton: false, backAction: { }, closeAction: { }) } .modifier(WaitOverlay(isLoading: true)) VStack { - ThemableNavigationBar(title: nil, showBackButton: true, backAction: {}, closeAction: {}) - ThemableNavigationBar(title: "Some Title", showBackButton: true, backAction: {}, closeAction: {}) - ThemableNavigationBar(title: nil, showBackButton: false, backAction: {}, closeAction: {}) - ThemableNavigationBar(title: "Some Title", showBackButton: false, backAction: {}, closeAction: {}) + ThemableNavigationBar(title: nil, showBackButton: true, backAction: { }, closeAction: { }) + ThemableNavigationBar(title: "Some Title", showBackButton: true, backAction: { }, closeAction: { }) + ThemableNavigationBar(title: nil, showBackButton: false, backAction: { }, closeAction: { }) + ThemableNavigationBar(title: "Some Title", showBackButton: false, backAction: { }, closeAction: { }) } - .modifier(WaitOverlay(alignment:.topLeading, isLoading: true)) + .modifier(WaitOverlay(alignment: .topLeading, isLoading: true)) VStack { - ThemableNavigationBar(title: nil, showBackButton: true, backAction: {}, closeAction: {}).theme(.dark) - ThemableNavigationBar(title: "Some Title", showBackButton: true, backAction: {}, closeAction: {}).theme(.dark) - ThemableNavigationBar(title: nil, showBackButton: false, backAction: {}, closeAction: {}).theme(.dark) - ThemableNavigationBar(title: "Some Title", showBackButton: false, backAction: {}, closeAction: {}).theme(.dark) + ThemableNavigationBar(title: nil, showBackButton: true, backAction: { }, closeAction: { }).theme(.dark) + ThemableNavigationBar(title: "Some Title", showBackButton: true, backAction: { }, closeAction: { }).theme(.dark) + ThemableNavigationBar(title: nil, showBackButton: false, backAction: { }, closeAction: { }).theme(.dark) + ThemableNavigationBar(title: "Some Title", showBackButton: false, backAction: { }, closeAction: { }).theme(.dark) } .modifier(WaitOverlay(isLoading: true)).theme(.dark) diff --git a/RiotSwiftUI/Modules/Common/ViewFrameReader/FramePreferenceKey.swift b/RiotSwiftUI/Modules/Common/ViewFrameReader/FramePreferenceKey.swift index 1eb7e97dd..63eb8df9d 100644 --- a/RiotSwiftUI/Modules/Common/ViewFrameReader/FramePreferenceKey.swift +++ b/RiotSwiftUI/Modules/Common/ViewFrameReader/FramePreferenceKey.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Common/ViewFrameReader/ViewFrameReader.swift b/RiotSwiftUI/Modules/Common/ViewFrameReader/ViewFrameReader.swift index 834c018a7..1bb6c50de 100644 --- a/RiotSwiftUI/Modules/Common/ViewFrameReader/ViewFrameReader.swift +++ b/RiotSwiftUI/Modules/Common/ViewFrameReader/ViewFrameReader.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Common/ViewModel/BindableState.swift b/RiotSwiftUI/Modules/Common/ViewModel/BindableState.swift index 79e658af4..8e3d9ce79 100644 --- a/RiotSwiftUI/Modules/Common/ViewModel/BindableState.swift +++ b/RiotSwiftUI/Modules/Common/ViewModel/BindableState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Common/ViewModel/StateStoreViewModel.swift b/RiotSwiftUI/Modules/Common/ViewModel/StateStoreViewModel.swift index 63c1ae7ae..30641c7f9 100644 --- a/RiotSwiftUI/Modules/Common/ViewModel/StateStoreViewModel.swift +++ b/RiotSwiftUI/Modules/Common/ViewModel/StateStoreViewModel.swift @@ -14,12 +14,11 @@ // limitations under the License. // -import Foundation import Combine - import Foundation -import Combine +import Combine +import Foundation /// A constrained and concise interface for interacting with the ViewModel. /// @@ -34,7 +33,7 @@ import Combine /// It provides a nice layer of consistency and also safety. As we are not passing the `ViewModel` to the view directly, shortcuts/hacks /// can't be made into the `ViewModel`. @dynamicMemberLookup -class ViewModelContext: ObservableObject { +class ViewModelContext: ObservableObject { // MARK: - Properties // MARK: Private @@ -75,7 +74,6 @@ class ViewModelContext: ObservableObject { /// If we decide to add more features to our state management (like doing state processing off the main thread) /// we can do it in this centralised place. class StateStoreViewModel { - typealias Context = ViewModelContext // MARK: - Properties @@ -98,8 +96,8 @@ class StateStoreViewModel { // MARK: Setup init(initialViewState: State) { - self.context = Context(initialViewState: initialViewState) - self.context.viewActions.sink { [weak self] action in + context = Context(initialViewState: initialViewState) + context.viewActions.sink { [weak self] action in guard let self = self else { return } self.process(viewAction: action) } @@ -131,12 +129,12 @@ class StateStoreViewModel { /// - state: The `inout` state to be modified, /// - action: The action that defines which state modification should take place. class func reducer(state: inout State, action: StateAction) { - //Default implementation, -no-op + // Default implementation, -no-op } /// Override to handles incoming `ViewAction`s from the `ViewModel`. /// - Parameter viewAction: The `ViewAction` to be processed in `ViewModel` implementation. func process(viewAction: ViewAction) { - //Default implementation, -no-op + // Default implementation, -no-op } } diff --git a/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/Coordinator/LiveLocationLabPromotionCoordinator.swift b/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/Coordinator/LiveLocationLabPromotionCoordinator.swift index fbc5c6c9f..4bbb7c8bf 100644 --- a/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/Coordinator/LiveLocationLabPromotionCoordinator.swift +++ b/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/Coordinator/LiveLocationLabPromotionCoordinator.swift @@ -17,7 +17,6 @@ import SwiftUI final class LiveLocationLabPromotionCoordinator: NSObject, Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -50,7 +49,7 @@ final class LiveLocationLabPromotionCoordinator: NSObject, Coordinator, Presenta func start() { MXLog.debug("[LiveLocationLabPromotionCoordinator] did start.") - self.liveLocationLabPromotionViewModel.completion = { [weak self] enableLiveLocation in + liveLocationLabPromotionViewModel.completion = { [weak self] enableLiveLocation in guard let self = self else { return } RiotSettings.shared.enableLiveLocationSharing = enableLiveLocation @@ -62,15 +61,14 @@ final class LiveLocationLabPromotionCoordinator: NSObject, Coordinator, Presenta } func toPresentable() -> UIViewController { - return self.liveLocationLabPromotionHostingController + liveLocationLabPromotionHostingController } } // MARK: - UIAdaptivePresentationControllerDelegate extension LiveLocationLabPromotionCoordinator: UIAdaptivePresentationControllerDelegate { - func presentationControllerDidDismiss(_ presentationController: UIPresentationController) { - self.completion?(RiotSettings.shared.enableLiveLocationSharing) + completion?(RiotSettings.shared.enableLiveLocationSharing) } } diff --git a/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/LiveLocationLabPromotionModels.swift b/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/LiveLocationLabPromotionModels.swift index 266b2d01c..7f5f19429 100644 --- a/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/LiveLocationLabPromotionModels.swift +++ b/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/LiveLocationLabPromotionModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ import Foundation // MARK: View struct LiveLocationLabPromotionViewState: BindableState { - var bindings: LiveLocationLabPromotionBindings } diff --git a/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/LiveLocationLabPromotionViewModel.swift b/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/LiveLocationLabPromotionViewModel.swift index eb4ea189c..6a6b48a7d 100644 --- a/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/LiveLocationLabPromotionViewModel.swift +++ b/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/LiveLocationLabPromotionViewModel.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,11 +17,10 @@ import SwiftUI typealias LiveLocationLabPromotionViewModelType = StateStoreViewModel + Never, + LiveLocationLabPromotionViewAction> class LiveLocationLabPromotionViewModel: LiveLocationLabPromotionViewModelType, LiveLocationLabPromotionViewModelProtocol { - // MARK: - Properties // MARK: Private @@ -42,7 +41,7 @@ class LiveLocationLabPromotionViewModel: LiveLocationLabPromotionViewModelType, override func process(viewAction: LiveLocationLabPromotionViewAction) { switch viewAction { case .complete: - completion?(self.state.bindings.enableLabFlag) + completion?(state.bindings.enableLabFlag) } } } diff --git a/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/LiveLocationLabPromotionViewModelProtocol.swift b/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/LiveLocationLabPromotionViewModelProtocol.swift index a8d741751..45d75cd1c 100644 --- a/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/LiveLocationLabPromotionViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/LiveLocationLabPromotionViewModelProtocol.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ import Foundation protocol LiveLocationLabPromotionViewModelProtocol { - /// Closure called when screen completes. Indicates true if the lab flag has been enabled. var completion: ((Bool) -> Void)? { get set } diff --git a/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/MockLiveLocationLabPromotionScreenState.swift b/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/MockLiveLocationLabPromotionScreenState.swift index f062bfe5f..c49c9e1de 100644 --- a/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/MockLiveLocationLabPromotionScreenState.swift +++ b/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/MockLiveLocationLabPromotionScreenState.swift @@ -31,7 +31,7 @@ enum MockLiveLocationLabPromotionScreenState: MockScreenState, CaseIterable { } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let viewModel = LiveLocationLabPromotionViewModel() // can simulate service and viewModel actions here if needs be. @@ -39,6 +39,7 @@ enum MockLiveLocationLabPromotionScreenState: MockScreenState, CaseIterable { return ( [self, viewModel], AnyView(LiveLocationLabPromotionView(viewModel: viewModel.context) - )) + ) + ) } } diff --git a/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/Test/UI/LiveLocationLabPromotionUITests.swift b/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/Test/UI/LiveLocationLabPromotionUITests.swift index 4b71228fc..4a8af4a5b 100644 --- a/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/Test/UI/LiveLocationLabPromotionUITests.swift +++ b/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/Test/UI/LiveLocationLabPromotionUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class LiveLocationLabPromotionUITests: MockScreenTestCase { // Nothing to test as the view is completely static diff --git a/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/Test/Unit/LiveLocationLabPromotionViewModelTests.swift b/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/Test/Unit/LiveLocationLabPromotionViewModelTests.swift index 284b27694..9dc77e699 100644 --- a/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/Test/Unit/LiveLocationLabPromotionViewModelTests.swift +++ b/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/Test/Unit/LiveLocationLabPromotionViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/View/LiveLocationLabPromotionView.swift b/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/View/LiveLocationLabPromotionView.swift index 8ca11dd23..c92c0e2df 100644 --- a/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/View/LiveLocationLabPromotionView.swift +++ b/RiotSwiftUI/Modules/LocationSharing/LiveLocationLabPromotion/View/LiveLocationLabPromotionView.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ import SwiftUI struct LiveLocationLabPromotionView: View { - // MARK: - Properties // MARK: Private @@ -49,7 +48,6 @@ struct LiveLocationLabPromotionView: View { .padding(.top, 1) Toggle(isOn: $viewModel.enableLabFlag) { - Text(VectorL10n.locationSharingLiveLabPromotionActivation) .font(theme.fonts.body) .foregroundColor(theme.colors.primaryContent) diff --git a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Coordinator/LiveLocationSharingViewerCoordinator.swift b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Coordinator/LiveLocationSharingViewerCoordinator.swift index 19be80eec..fc5c6b87a 100644 --- a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Coordinator/LiveLocationSharingViewerCoordinator.swift +++ b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Coordinator/LiveLocationSharingViewerCoordinator.swift @@ -23,7 +23,6 @@ struct LiveLocationSharingViewerCoordinatorParameters { } final class LiveLocationSharingViewerCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -51,7 +50,8 @@ final class LiveLocationSharingViewerCoordinator: Coordinator, Presentable { let viewModel = LiveLocationSharingViewerViewModel( mapStyleURL: parameters.session.vc_homeserverConfiguration().tileServer.mapStyleURL, - service: service) + service: service + ) let view = LiveLocationSharingViewer(viewModel: viewModel.context) .addDependency(AvatarService.instantiate(mediaManager: parameters.session.mediaManager)) liveLocationSharingViewerViewModel = viewModel @@ -61,6 +61,7 @@ final class LiveLocationSharingViewerCoordinator: Coordinator, Presentable { } // MARK: - Public + func start() { MXLog.debug("[LiveLocationSharingViewerCoordinator] did start.") liveLocationSharingViewerViewModel.completion = { [weak self] result in @@ -74,7 +75,7 @@ final class LiveLocationSharingViewerCoordinator: Coordinator, Presentable { } } - let viewController: UIViewController = self.liveLocationSharingViewerHostingController + let viewController: UIViewController = liveLocationSharingViewerHostingController if navigationRouter.modules.count > 1 { navigationRouter.push(viewController, animated: true, popCompletion: nil) @@ -84,14 +85,13 @@ final class LiveLocationSharingViewerCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return navigationRouter.toPresentable() + navigationRouter.toPresentable() .vc_setModalFullScreen(true) // Set fullscreen as DSBottomSheet is not working with modal pan gesture recognizer } func presentLocationActivityController(with coordinate: CLLocationCoordinate2D) { - let shareActivityController = shareLocationActivityControllerBuilder.build(with: coordinate) - self.liveLocationSharingViewerHostingController.present(shareActivityController, animated: true) + liveLocationSharingViewerHostingController.present(shareActivityController, animated: true) } } diff --git a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/LiveLocationSharingViewerModels.swift b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/LiveLocationSharingViewerModels.swift index 3cf3271cc..5c4f8a841 100644 --- a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/LiveLocationSharingViewerModels.swift +++ b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/LiveLocationSharingViewerModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,15 +14,15 @@ // limitations under the License. // -import Foundation import Combine import CoreLocation +import Foundation // MARK: - Coordinator // MARK: View model -enum LiveLocationSharingViewerViewModelResult { +enum LiveLocationSharingViewerViewModelResult { case done case share(_ coordinate: CLLocationCoordinate2D) } @@ -30,7 +30,6 @@ enum LiveLocationSharingViewerViewModelResult { // MARK: View struct LiveLocationSharingViewerViewState: BindableState { - /// Map style URL let mapStyleURL: URL @@ -43,7 +42,7 @@ struct LiveLocationSharingViewerViewState: BindableState { /// Live location list items var listItemsViewData: [LiveLocationListItemViewData] - var showLoadingIndicator: Bool = false + var showLoadingIndicator = false var shareButtonEnabled: Bool { !showLoadingIndicator @@ -51,14 +50,14 @@ struct LiveLocationSharingViewerViewState: BindableState { /// True to indicate that everybody stopped to share live location sharing in the room var isAllLocationSharingEnded: Bool { - return listItemsViewData.isEmpty + listItemsViewData.isEmpty } var isBottomSheetVisible: Bool { - return isAllLocationSharingEnded == false + isAllLocationSharingEnded == false } - var showMapLoadingError: Bool = false + var showMapLoadingError = false let errorSubject = PassthroughSubject() diff --git a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/LiveLocationSharingViewerViewModel.swift b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/LiveLocationSharingViewerViewModel.swift index 9a20870d6..9037b3af6 100644 --- a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/LiveLocationSharingViewerViewModel.swift +++ b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/LiveLocationSharingViewerViewModel.swift @@ -14,15 +14,14 @@ // limitations under the License. // -import SwiftUI import Combine import Mapbox +import SwiftUI typealias LiveLocationSharingViewerViewModelType = StateStoreViewModel + Never, + LiveLocationSharingViewerViewAction> class LiveLocationSharingViewerViewModel: LiveLocationSharingViewerViewModelType, LiveLocationSharingViewerViewModelProtocol { - // MARK: - Properties // MARK: Private @@ -44,7 +43,6 @@ class LiveLocationSharingViewerViewModel: LiveLocationSharingViewerViewModelType // MARK: - Setup init(mapStyleURL: URL, service: LiveLocationSharingViewerServiceProtocol) { - let viewState = LiveLocationSharingViewerViewState(mapStyleURL: mapStyleURL, annotations: [], highlightedAnnotation: nil, listItemsViewData: []) liveLocationSharingViewerService = service @@ -57,8 +55,8 @@ class LiveLocationSharingViewerViewModel: LiveLocationSharingViewerViewModelType self.processError(error) }.store(in: &cancellables) - self.setupLocationSharingService() - self.setupScreenUpdateTimer() + setupLocationSharingService() + setupScreenUpdateTimer() } // MARK: - Public @@ -70,7 +68,7 @@ class LiveLocationSharingViewerViewModel: LiveLocationSharingViewerViewModelType case .stopSharing: stopUserLocationSharing() case .tapListItem(let userId): - self.highlighAnnotation(with: userId) + highlighAnnotation(with: userId) case .share(let userLocationAnnotation): completion?(.share(userLocationAnnotation.coordinate)) case .mapCreditsDidTap: @@ -81,20 +79,20 @@ class LiveLocationSharingViewerViewModel: LiveLocationSharingViewerViewModelType // MARK: - Private private func setupLocationSharingService() { - self.updateUsersLiveLocation(highlightFirstLocation: true) + updateUsersLiveLocation(highlightFirstLocation: true) liveLocationSharingViewerService.didUpdateUsersLiveLocation = { [weak self] liveLocations in self?.update(with: liveLocations, highlightFirstLocation: false) } - self.liveLocationSharingViewerService.startListeningLiveLocationUpdates() + liveLocationSharingViewerService.startListeningLiveLocationUpdates() } private func updateUsersLiveLocation(highlightFirstLocation: Bool) { - self.update(with: liveLocationSharingViewerService.usersLiveLocation, highlightFirstLocation: highlightFirstLocation) + update(with: liveLocationSharingViewerService.usersLiveLocation, highlightFirstLocation: highlightFirstLocation) } private func setupScreenUpdateTimer() { - self.screenUpdateTimer = Timer.scheduledTimer(withTimeInterval: 30, repeats: true) { [weak self] timer in + screenUpdateTimer = Timer.scheduledTimer(withTimeInterval: 30, repeats: true) { [weak self] _ in self?.updateUsersLiveLocation(highlightFirstLocation: false) } @@ -113,7 +111,7 @@ class LiveLocationSharingViewerViewModel: LiveLocationSharingViewerViewModelType switch error { case .invalidLocationAuthorization: - if let applicationSettingsURL = URL(string:UIApplication.openSettingsURLString) { + if let applicationSettingsURL = URL(string: UIApplication.openSettingsURLString) { UIApplication.shared.open(applicationSettingsURL) } else { self?.completion?(.done) @@ -127,21 +125,19 @@ class LiveLocationSharingViewerViewModel: LiveLocationSharingViewerViewModelType } private func userLocationAnnotations(from usersLiveLocation: [UserLiveLocation]) -> [UserLocationAnnotation] { - - return usersLiveLocation.map { userLiveLocation in - return UserLocationAnnotation(avatarData: userLiveLocation.avatarData, coordinate: userLiveLocation.coordinate) + usersLiveLocation.map { userLiveLocation in + UserLocationAnnotation(avatarData: userLiveLocation.avatarData, coordinate: userLiveLocation.coordinate) } } private func currentUserLocationAnnotation(from annotations: [UserLocationAnnotation]) -> UserLocationAnnotation? { annotations.first { annotation in - return liveLocationSharingViewerService.isCurrentUserId(annotation.userId) + liveLocationSharingViewerService.isCurrentUserId(annotation.userId) } } private func getHighlightedAnnotation(from annotations: [UserLocationAnnotation]) -> UserLocationAnnotation? { - - if let userAnnotation = self.currentUserLocationAnnotation(from: annotations) { + if let userAnnotation = currentUserLocationAnnotation(from: annotations) { return userAnnotation } else { return annotations.first @@ -149,25 +145,22 @@ class LiveLocationSharingViewerViewModel: LiveLocationSharingViewerViewModelType } private func listItemsViewData(from usersLiveLocation: [UserLiveLocation]) -> [LiveLocationListItemViewData] { - var listItemsViewData: [LiveLocationListItemViewData] = [] let sortedUsersLiveLocation = usersLiveLocation.sorted { userLiveLocation1, userLiveLocation2 in - return userLiveLocation1.displayName > userLiveLocation2.displayName + userLiveLocation1.displayName > userLiveLocation2.displayName } - listItemsViewData = sortedUsersLiveLocation.map({ userLiveLocation in - return self.listItemViewData(from: userLiveLocation) - }) - + listItemsViewData = sortedUsersLiveLocation.map { userLiveLocation in + self.listItemViewData(from: userLiveLocation) + } let currentUserIndex = listItemsViewData.firstIndex { viewData in - return viewData.isCurrentUser + viewData.isCurrentUser } // Move current user as first item if let currentUserIndex = currentUserIndex { - let currentUserViewData = listItemsViewData[currentUserIndex] listItemsViewData.remove(at: currentUserIndex) listItemsViewData.insert(currentUserViewData, at: 0) @@ -177,41 +170,39 @@ class LiveLocationSharingViewerViewModel: LiveLocationSharingViewerViewModelType } private func listItemViewData(from userLiveLocation: UserLiveLocation) -> LiveLocationListItemViewData { + let isCurrentUser = liveLocationSharingViewerService.isCurrentUserId(userLiveLocation.userId) - let isCurrentUser = self.liveLocationSharingViewerService.isCurrentUserId(userLiveLocation.userId) - - let expirationDate = userLiveLocation.timestamp + userLiveLocation.timeout + let expirationDate = userLiveLocation.timestamp + userLiveLocation.timeout return LiveLocationListItemViewData(userId: userLiveLocation.userId, isCurrentUser: isCurrentUser, avatarData: userLiveLocation.avatarData, displayName: userLiveLocation.displayName, expirationDate: expirationDate, lastUpdate: userLiveLocation.lastUpdate) } private func update(with usersLiveLocation: [UserLiveLocation], highlightFirstLocation: Bool) { - - let annotations: [UserLocationAnnotation] = self.userLocationAnnotations(from: usersLiveLocation) + let annotations: [UserLocationAnnotation] = userLocationAnnotations(from: usersLiveLocation) var highlightedAnnotation: LocationAnnotation? if highlightFirstLocation { - highlightedAnnotation = self.getHighlightedAnnotation(from: annotations) + highlightedAnnotation = getHighlightedAnnotation(from: annotations) } - if let highlightableAnnotation = self.getHighlightedAnnotation(from: annotations) { - self.lastHighlightableAnnotation = highlightableAnnotation + if let highlightableAnnotation = getHighlightedAnnotation(from: annotations) { + lastHighlightableAnnotation = highlightableAnnotation } - if let lastHighlightableAnnotation = self.lastHighlightableAnnotation, usersLiveLocation.isEmpty { + if let lastHighlightableAnnotation = lastHighlightableAnnotation, usersLiveLocation.isEmpty { highlightedAnnotation = InvisibleLocationAnnotation(coordinate: lastHighlightableAnnotation.coordinate) } - let listViewItems = self.listItemsViewData(from: usersLiveLocation) + let listViewItems = listItemsViewData(from: usersLiveLocation) - self.state.annotations = annotations - self.state.highlightedAnnotation = highlightedAnnotation - self.state.listItemsViewData = listViewItems + state.annotations = annotations + state.highlightedAnnotation = highlightedAnnotation + state.listItemsViewData = listViewItems } private func highlighAnnotation(with userId: String) { - let foundUserAnnotation = self.state.annotations.first { annotation in + let foundUserAnnotation = state.annotations.first { annotation in annotation.userId == userId } @@ -219,20 +210,19 @@ class LiveLocationSharingViewerViewModel: LiveLocationSharingViewerViewModelType return } - self.state.highlightedAnnotation = foundUserAnnotation + state.highlightedAnnotation = foundUserAnnotation } private func stopUserLocationSharing() { + state.showLoadingIndicator = true - self.state.showLoadingIndicator = true - - self.liveLocationSharingViewerService.stopUserLiveLocationSharing { result in + liveLocationSharingViewerService.stopUserLiveLocationSharing { result in self.state.showLoadingIndicator = false switch result { case .success: break - case.failure: + case .failure: self.state.bindings.alertInfo = AlertInfo(id: .stopLocationSharingError, title: VectorL10n.error, message: VectorL10n.locationSharingLiveStopSharingError, diff --git a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/LiveLocationSharingViewerViewModelProtocol.swift b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/LiveLocationSharingViewerViewModelProtocol.swift index a8626b528..890b96cf7 100644 --- a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/LiveLocationSharingViewerViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/LiveLocationSharingViewerViewModelProtocol.swift @@ -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 LiveLocationSharingViewerViewModelProtocol { - var completion: ((LiveLocationSharingViewerViewModelResult) -> Void)? { get set } var context: LiveLocationSharingViewerViewModelType.Context { get } } diff --git a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/MockLiveLocationSharingViewerScreenState.swift b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/MockLiveLocationSharingViewerScreenState.swift index 61353c169..a3451f669 100644 --- a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/MockLiveLocationSharingViewerScreenState.swift +++ b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/MockLiveLocationSharingViewerScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,12 +33,11 @@ enum MockLiveLocationSharingViewerScreenState: MockScreenState, CaseIterable { /// A list of screen state definitions static var allCases: [MockLiveLocationSharingViewerScreenState] { - return [.currentUser, .multipleUsers] + [.currentUser, .multipleUsers] } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { - + var screenView: ([Any], AnyView) { let service: LiveLocationSharingViewerServiceProtocol switch self { diff --git a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Service/LiveLocationSharingViewerServiceProtocol.swift b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Service/LiveLocationSharingViewerServiceProtocol.swift index 3b0cbeeaa..cb9e107a5 100644 --- a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Service/LiveLocationSharingViewerServiceProtocol.swift +++ b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Service/LiveLocationSharingViewerServiceProtocol.swift @@ -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 CoreLocation +import Foundation protocol LiveLocationSharingViewerServiceProtocol { - /// All shared users live location var usersLiveLocation: [UserLiveLocation] { get } diff --git a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Service/MatrixSDK/LiveLocationSharingViewerService.swift b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Service/MatrixSDK/LiveLocationSharingViewerService.swift index f7b4155b6..9b646a1bf 100644 --- a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Service/MatrixSDK/LiveLocationSharingViewerService.swift +++ b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Service/MatrixSDK/LiveLocationSharingViewerService.swift @@ -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 CoreLocation +import Foundation import MatrixSDK class LiveLocationSharingViewerService: LiveLocationSharingViewerServiceProtocol { - // MARK: - Properties private(set) var usersLiveLocation: [UserLiveLocation] = [] @@ -40,17 +39,17 @@ class LiveLocationSharingViewerService: LiveLocationSharingViewerServiceProtocol self.session = session self.roomId = roomId - self.updateUsersLiveLocation(notifyUpdate: false) + updateUsersLiveLocation(notifyUpdate: false) } // MARK: - Public func isCurrentUserId(_ userId: String) -> Bool { - return self.session.myUserId == userId + session.myUserId == userId } func startListeningLiveLocationUpdates() { - self.beaconInfoSummaryListener = self.session.aggregations.beaconAggregations.listenToBeaconInfoSummaryUpdateInRoom(withId: self.roomId) { [weak self] _ in + beaconInfoSummaryListener = session.aggregations.beaconAggregations.listenToBeaconInfoSummaryUpdateInRoom(withId: roomId) { [weak self] _ in self?.updateUsersLiveLocation(notifyUpdate: true) } @@ -58,17 +57,17 @@ class LiveLocationSharingViewerService: LiveLocationSharingViewerServiceProtocol func stopListeningLiveLocationUpdates() { if let listener = beaconInfoSummaryListener { - self.session.aggregations.removeListener(listener) - self.beaconInfoSummaryListener = nil + session.aggregations.removeListener(listener) + beaconInfoSummaryListener = nil } } func stopUserLiveLocationSharing(completion: @escaping (Result) -> Void) { - self.session.locationService.stopUserLocationSharing(inRoomWithId: roomId) { response in + session.locationService.stopUserLocationSharing(inRoomWithId: roomId) { response in switch response { case .success: - completion(.success(Void())) + completion(.success(())) case .failure(let error): completion(.failure(error)) } @@ -78,17 +77,16 @@ class LiveLocationSharingViewerService: LiveLocationSharingViewerServiceProtocol // MARK: - Private private func updateUsersLiveLocation(notifyUpdate: Bool) { - let beaconInfoSummaries = self.session.locationService.getDisplayableBeaconInfoSummaries(inRoomWithId: roomId) - self.usersLiveLocation = Self.usersLiveLocation(fromBeaconInfoSummaries: beaconInfoSummaries, session: session) + let beaconInfoSummaries = session.locationService.getDisplayableBeaconInfoSummaries(inRoomWithId: roomId) + usersLiveLocation = Self.usersLiveLocation(fromBeaconInfoSummaries: beaconInfoSummaries, session: session) if notifyUpdate { - self.didUpdateUsersLiveLocation?(self.usersLiveLocation) + didUpdateUsersLiveLocation?(usersLiveLocation) } } - class private func usersLiveLocation(fromBeaconInfoSummaries beaconInfoSummaries: [MXBeaconInfoSummaryProtocol], session: MXSession) -> [UserLiveLocation] { - - return beaconInfoSummaries.compactMap { beaconInfoSummary in + private class func usersLiveLocation(fromBeaconInfoSummaries beaconInfoSummaries: [MXBeaconInfoSummaryProtocol], session: MXSession) -> [UserLiveLocation] { + beaconInfoSummaries.compactMap { beaconInfoSummary in let beaconInfo = beaconInfoSummary.beaconInfo @@ -98,9 +96,9 @@ class LiveLocationSharingViewerService: LiveLocationSharingViewerServiceProtocol let avatarData = session.avatarInput(for: beaconInfoSummary.userId) - let timestamp = TimeInterval(beaconInfo.timestamp/1000) - let timeout = TimeInterval(beaconInfo.timeout/1000) - let lastUpdate = TimeInterval(lastBeacon.timestamp/1000) + let timestamp = TimeInterval(beaconInfo.timestamp / 1000) + let timeout = TimeInterval(beaconInfo.timeout / 1000) + let lastUpdate = TimeInterval(lastBeacon.timestamp / 1000) let coordinate = CLLocationCoordinate2D(latitude: lastBeacon.location.latitude, longitude: lastBeacon.location.longitude) diff --git a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Service/Mock/MockLiveLocationSharingViewerService.swift b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Service/Mock/MockLiveLocationSharingViewerService.swift index ac192ec37..cfb34ef04 100644 --- a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Service/Mock/MockLiveLocationSharingViewerService.swift +++ b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Service/Mock/MockLiveLocationSharingViewerService.swift @@ -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 CoreLocation +import Foundation class MockLiveLocationSharingViewerService: LiveLocationSharingViewerServiceProtocol { - // MARK: Properties private(set) var usersLiveLocation: [UserLiveLocation] = [] @@ -29,17 +28,15 @@ class MockLiveLocationSharingViewerService: LiveLocationSharingViewerServiceProt // MARK: Setup init(generateRandomUsers: Bool = false) { + let firstUserLiveLocation = createFirstUserLiveLocation() - let firstUserLiveLocation = self.createFirstUserLiveLocation() - - let secondUserLiveLocation = self.createSecondUserLiveLocation() + let secondUserLiveLocation = createSecondUserLiveLocation() var usersLiveLocation: [UserLiveLocation] = [firstUserLiveLocation, secondUserLiveLocation] - if generateRandomUsers { for _ in 1...20 { - let randomUser = self.createRandomUserLiveLocation() + let randomUser = createRandomUserLiveLocation() usersLiveLocation.append(randomUser) } } @@ -50,20 +47,14 @@ class MockLiveLocationSharingViewerService: LiveLocationSharingViewerServiceProt // MARK: Public func isCurrentUserId(_ userId: String) -> Bool { - return "@alice:matrix.org" == userId + userId == "@alice:matrix.org" } - func startListeningLiveLocationUpdates() { - - } + func startListeningLiveLocationUpdates() { } - func stopListeningLiveLocationUpdates() { - - } + func stopListeningLiveLocationUpdates() { } - func stopUserLiveLocationSharing(completion: @escaping (Result) -> Void) { - - } + func stopUserLiveLocationSharing(completion: @escaping (Result) -> Void) { } // MARK: Private @@ -80,7 +71,6 @@ class MockLiveLocationSharingViewerService: LiveLocationSharingViewerServiceProt } private func createSecondUserLiveLocation() -> UserLiveLocation { - let userAvatarData = AvatarInput(mxContentUri: nil, matrixItemId: "@bob:matrix.org", displayName: "Bob") let coordinate = CLLocationCoordinate2D(latitude: 51.4952641, longitude: -0.259096) @@ -93,9 +83,7 @@ class MockLiveLocationSharingViewerService: LiveLocationSharingViewerServiceProt return UserLiveLocation(avatarData: userAvatarData, timestamp: timestamp, timeout: timeout, lastUpdate: lastUpdate, coordinate: coordinate) } - private func createRandomUserLiveLocation() -> UserLiveLocation { - let uuidString = UUID().uuidString.suffix(8) let random = Double.random(in: 0.005...0.010) diff --git a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Service/UserLiveLocation.swift b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Service/UserLiveLocation.swift index 015d09088..dc8c9898d 100644 --- a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Service/UserLiveLocation.swift +++ b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Service/UserLiveLocation.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,18 +14,17 @@ // limitations under the License. // -import Foundation import CoreLocation +import Foundation /// Represents user live location struct UserLiveLocation { - var userId: String { - return avatarData.matrixItemId + avatarData.matrixItemId } var displayName: String { - return avatarData.displayName ?? self.userId + avatarData.displayName ?? userId } let avatarData: AvatarInputProtocol diff --git a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Test/UI/LiveLocationSharingViewerUITests.swift b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Test/UI/LiveLocationSharingViewerUITests.swift index 6d4333d4c..de996c2b0 100644 --- a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Test/UI/LiveLocationSharingViewerUITests.swift +++ b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Test/UI/LiveLocationSharingViewerUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class LiveLocationSharingViewerUITests: MockScreenTestCase { // Tests to be implemented. diff --git a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Test/Unit/LiveLocationSharingViewerViewModelTests.swift b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Test/Unit/LiveLocationSharingViewerViewModelTests.swift index 39718e54d..cefe1c2ed 100644 --- a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Test/Unit/LiveLocationSharingViewerViewModelTests.swift +++ b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/Test/Unit/LiveLocationSharingViewerViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,13 +14,12 @@ // limitations under the License. // -import XCTest import Combine +import XCTest @testable import RiotSwiftUI class LiveLocationSharingViewerViewModelTests: XCTestCase { - var service: MockLiveLocationSharingViewerService! var viewModel: LiveLocationSharingViewerViewModelProtocol! var context: LiveLocationSharingViewerViewModelType.Context! diff --git a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/View/LiveLocationListItem.swift b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/View/LiveLocationListItem.swift index b6af40483..e32de2818 100644 --- a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/View/LiveLocationListItem.swift +++ b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/View/LiveLocationListItem.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ import SwiftUI struct LiveLocationListItem: View { - // MARK: - Properties // MARK: Private @@ -29,10 +28,9 @@ struct LiveLocationListItem: View { let viewData: LiveLocationListItemViewData var timeoutText: String { - let timeLeftString: String - if let elapsedTimeString = self.elapsedTimeString(from: viewData.expirationDate, isPastDate: false) { + if let elapsedTimeString = elapsedTimeString(from: viewData.expirationDate, isPastDate: false) { timeLeftString = VectorL10n.locationSharingLiveListItemTimeLeft(elapsedTimeString) } else { timeLeftString = VectorL10n.locationSharingLiveListItemSharingExpired @@ -42,10 +40,9 @@ struct LiveLocationListItem: View { } var lastUpdateText: String { - let timeLeftString: String - if let elapsedTimeString = self.elapsedTimeString(from: viewData.lastUpdate, isPastDate: true) { + if let elapsedTimeString = elapsedTimeString(from: viewData.lastUpdate, isPastDate: true) { timeLeftString = VectorL10n.locationSharingLiveListItemLastUpdate(elapsedTimeString) } else { timeLeftString = VectorL10n.locationSharingLiveListItemLastUpdateInvalid @@ -55,12 +52,12 @@ struct LiveLocationListItem: View { } var displayName: String { - return viewData.isCurrentUser ? VectorL10n.locationSharingLiveListItemCurrentUserDisplayName : viewData.displayName + viewData.isCurrentUser ? VectorL10n.locationSharingLiveListItemCurrentUserDisplayName : viewData.displayName } - var onStopSharingAction: (() -> (Void))? = nil + var onStopSharingAction: (() -> Void)? - var onBackgroundTap: ((String) -> (Void))? = nil + var onBackgroundTap: ((String) -> Void)? // MARK: - Body @@ -69,9 +66,9 @@ struct LiveLocationListItem: View { HStack(spacing: 18) { AvatarImage(avatarData: viewData.avatarData, size: .medium) .border() - VStack(alignment: .leading, spacing: 2) { Text(displayName) - .font(theme.fonts.bodySB) - .foregroundColor(theme.colors.primaryContent) + VStack(alignment: .leading, spacing: 2) { Text(displayName) + .font(theme.fonts.bodySB) + .foregroundColor(theme.colors.primaryContent) Text(timeoutText) .font(theme.fonts.caption1) .foregroundColor(theme.colors.primaryContent) @@ -97,7 +94,6 @@ struct LiveLocationListItem: View { // MARK: - Private private func elapsedTimeString(from timestamp: TimeInterval, isPastDate: Bool) -> String? { - let formatter = DateComponentsFormatter() formatter.unitsStyle = .abbreviated @@ -121,19 +117,16 @@ struct LiveLocationListItem: View { } struct LiveLocationListPreview: View { - let liveLocationSharingViewerService: LiveLocationSharingViewerServiceProtocol = MockLiveLocationSharingViewerService() var viewDataList: [LiveLocationListItemViewData] { - return self.listItemsViewData(from: liveLocationSharingViewerService.usersLiveLocation) + listItemsViewData(from: liveLocationSharingViewerService.usersLiveLocation) } var body: some View { VStack(alignment: .leading, spacing: 14) { ForEach(viewDataList) { viewData in - LiveLocationListItem(viewData: viewData, onStopSharingAction: { - - }, onBackgroundTap: { userId in + LiveLocationListItem(viewData: viewData, onStopSharingAction: { }, onBackgroundTap: { _ in }) } @@ -143,24 +136,22 @@ struct LiveLocationListPreview: View { } private func listItemsViewData(from usersLiveLocation: [UserLiveLocation]) -> [LiveLocationListItemViewData] { - var listItemsViewData: [LiveLocationListItemViewData] = [] let sortedUsersLiveLocation = usersLiveLocation.sorted { userLiveLocation1, userLiveLocation2 in - return userLiveLocation1.displayName > userLiveLocation2.displayName + userLiveLocation1.displayName > userLiveLocation2.displayName } - listItemsViewData = sortedUsersLiveLocation.map({ userLiveLocation in - return self.listItemViewData(from: userLiveLocation) - }) + listItemsViewData = sortedUsersLiveLocation.map { userLiveLocation in + self.listItemViewData(from: userLiveLocation) + } let currentUserIndex = listItemsViewData.firstIndex { viewData in - return viewData.isCurrentUser + viewData.isCurrentUser } // Move current user as first item if let currentUserIndex = currentUserIndex { - let currentUserViewData = listItemsViewData[currentUserIndex] listItemsViewData.remove(at: currentUserIndex) listItemsViewData.insert(currentUserViewData, at: 0) @@ -170,10 +161,9 @@ struct LiveLocationListPreview: View { } private func listItemViewData(from userLiveLocation: UserLiveLocation) -> LiveLocationListItemViewData { + let isCurrentUser = liveLocationSharingViewerService.isCurrentUserId(userLiveLocation.userId) - let isCurrentUser = self.liveLocationSharingViewerService.isCurrentUserId(userLiveLocation.userId) - - let expirationDate = userLiveLocation.timestamp + userLiveLocation.timeout + let expirationDate = userLiveLocation.timestamp + userLiveLocation.timeout return LiveLocationListItemViewData(userId: userLiveLocation.userId, isCurrentUser: isCurrentUser, avatarData: userLiveLocation.avatarData, displayName: userLiveLocation.displayName, expirationDate: expirationDate, lastUpdate: userLiveLocation.lastUpdate) } diff --git a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/View/LiveLocationListItemViewData.swift b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/View/LiveLocationListItemViewData.swift index 3e2392225..e87b0bd3d 100644 --- a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/View/LiveLocationListItemViewData.swift +++ b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/View/LiveLocationListItemViewData.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,9 +18,8 @@ import Foundation /// View data for LiveLocationListItem struct LiveLocationListItemViewData: Identifiable { - var id: String { - return userId + userId } let userId: String diff --git a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/View/LiveLocationSharingViewer.swift b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/View/LiveLocationSharingViewer.swift index 1fd256b5a..9678028b8 100644 --- a/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/View/LiveLocationSharingViewer.swift +++ b/RiotSwiftUI/Modules/LocationSharing/LiveLocationSharingViewer/View/LiveLocationSharingViewer.swift @@ -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 SwiftUI import DSBottomSheet +import SwiftUI struct LiveLocationSharingViewer: View { - // MARK: - Properties // MARK: Private @@ -37,7 +36,6 @@ struct LiveLocationSharingViewer: View { var body: some View { ZStack(alignment: .bottom) { - if !viewModel.viewState.showMapLoadingError { LocationSharingMapView(tileServerMapURL: viewModel.viewState.mapStyleURL, annotations: viewModel.viewState.annotations, @@ -48,10 +46,10 @@ struct LiveLocationSharingViewer: View { userLocation: Binding.constant(nil), mapCenterCoordinate: Binding.constant(nil), onCalloutTap: { annotation in - if let userLocationAnnotation = annotation as? UserLocationAnnotation { - viewModel.send(viewAction: .share(userLocationAnnotation)) - } - }, + if let userLocationAnnotation = annotation as? UserLocationAnnotation { + viewModel.send(viewAction: .share(userLocationAnnotation)) + } + }, errorSubject: viewModel.viewState.errorSubject) // Show map credits above collapsed bottom sheet height if bottom sheet is visible @@ -61,7 +59,7 @@ struct LiveLocationSharingViewer: View { MapCreditsView(action: { viewModel.send(viewAction: .mapCreditsDidTap) }) - .offset(y: -(bottomSheetCollapsedHeight)) // Put the copyright action above the collapsed bottom sheet + .offset(y: -bottomSheetCollapsedHeight) // Put the copyright action above the collapsed bottom sheet .padding(.bottom, 10) } .ignoresSafeArea() @@ -112,7 +110,7 @@ struct LiveLocationSharingViewer: View { .background(theme.colors.system.ignoresSafeArea()) .bottomSheet(sheet, if: viewModel.viewState.isBottomSheetVisible) .actionSheet(isPresented: $viewModel.showMapCreditsSheet) { - return MapCreditsActionSheet(openURL: { url in + MapCreditsActionSheet(openURL: { url in openURL(url) }).sheet } @@ -142,8 +140,8 @@ struct LiveLocationSharingViewer: View { } // MARK: - Bottom sheet -extension LiveLocationSharingViewer { +extension LiveLocationSharingViewer { var sheetStyle: BottomSheetStyle { var bottomSheetStyle = BottomSheetStyle.standard @@ -162,9 +160,10 @@ extension LiveLocationSharingViewer { isExpanded: $isBottomSheetExpanded, minHeight: .points(bottomSheetCollapsedHeight), maxHeight: .available, - style: sheetStyle) { - userLocationList - } + style: sheetStyle + ) { + userLocationList + } } } diff --git a/RiotSwiftUI/Modules/LocationSharing/MapCredits/MapCreditsActionSheet.swift b/RiotSwiftUI/Modules/LocationSharing/MapCredits/MapCreditsActionSheet.swift index 3f08da5ac..927aceef0 100644 --- a/RiotSwiftUI/Modules/LocationSharing/MapCredits/MapCreditsActionSheet.swift +++ b/RiotSwiftUI/Modules/LocationSharing/MapCredits/MapCreditsActionSheet.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ import SwiftUI struct MapCreditsActionSheet { - // Open URL action let openURL: (URL) -> Void diff --git a/RiotSwiftUI/Modules/LocationSharing/MapCredits/View/MapCreditsView.swift b/RiotSwiftUI/Modules/LocationSharing/MapCredits/View/MapCreditsView.swift index 3edb2fbfc..3d30f358b 100644 --- a/RiotSwiftUI/Modules/LocationSharing/MapCredits/View/MapCreditsView.swift +++ b/RiotSwiftUI/Modules/LocationSharing/MapCredits/View/MapCreditsView.swift @@ -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 MapCreditsView: View { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/LocationSharing/MapError/MapViewErrorAlertInfoBuilder.swift b/RiotSwiftUI/Modules/LocationSharing/MapError/MapViewErrorAlertInfoBuilder.swift index 9f1120d2a..fa02eef50 100644 --- a/RiotSwiftUI/Modules/LocationSharing/MapError/MapViewErrorAlertInfoBuilder.swift +++ b/RiotSwiftUI/Modules/LocationSharing/MapError/MapViewErrorAlertInfoBuilder.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,30 +17,27 @@ import Foundation struct MapViewErrorAlertInfoBuilder { - func build(with error: LocationSharingViewError, primaryButtonCompletion: (() -> Void)?) -> AlertInfo? { - let alertInfo: AlertInfo? switch error { case .failedLoadingMap: alertInfo = AlertInfo(id: .mapLoadingError, - title: VectorL10n.locationSharingLoadingMapErrorTitle(AppInfo.current.displayName), - primaryButton: (VectorL10n.ok, primaryButtonCompletion)) + title: VectorL10n.locationSharingLoadingMapErrorTitle(AppInfo.current.displayName), + primaryButton: (VectorL10n.ok, primaryButtonCompletion)) case .failedLocatingUser: alertInfo = AlertInfo(id: .userLocatingError, - title: VectorL10n.locationSharingLocatingUserErrorTitle(AppInfo.current.displayName), - primaryButton: (VectorL10n.ok, primaryButtonCompletion)) + title: VectorL10n.locationSharingLocatingUserErrorTitle(AppInfo.current.displayName), + primaryButton: (VectorL10n.ok, primaryButtonCompletion)) case .invalidLocationAuthorization: alertInfo = AlertInfo(id: .authorizationError, - title: VectorL10n.locationSharingInvalidAuthorizationErrorTitle(AppInfo.current.displayName), - primaryButton: (VectorL10n.locationSharingInvalidAuthorizationNotNow, primaryButtonCompletion), - secondaryButton: (VectorL10n.locationSharingInvalidAuthorizationSettings, primaryButtonCompletion)) + title: VectorL10n.locationSharingInvalidAuthorizationErrorTitle(AppInfo.current.displayName), + primaryButton: (VectorL10n.locationSharingInvalidAuthorizationNotNow, primaryButtonCompletion), + secondaryButton: (VectorL10n.locationSharingInvalidAuthorizationSettings, primaryButtonCompletion)) default: alertInfo = nil } return alertInfo } - } diff --git a/RiotSwiftUI/Modules/LocationSharing/MapError/View/MapLoadingErrorView.swift b/RiotSwiftUI/Modules/LocationSharing/MapError/View/MapLoadingErrorView.swift index 018d4a0ed..dc65ab4b5 100644 --- a/RiotSwiftUI/Modules/LocationSharing/MapError/View/MapLoadingErrorView.swift +++ b/RiotSwiftUI/Modules/LocationSharing/MapError/View/MapLoadingErrorView.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ import SwiftUI struct MapLoadingErrorView: View { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/LocationSharing/MapView/LocationAnnotation.swift b/RiotSwiftUI/Modules/LocationSharing/MapView/LocationAnnotation.swift index 1ddec21c5..1bd69ff27 100644 --- a/RiotSwiftUI/Modules/LocationSharing/MapView/LocationAnnotation.swift +++ b/RiotSwiftUI/Modules/LocationSharing/MapView/LocationAnnotation.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ import Mapbox /// Base class to handle a map annotation class LocationAnnotation: NSObject, MGLAnnotation { - // MARK: - Properties // Title property is needed to enable annotation selection and callout view showing @@ -36,15 +35,14 @@ class LocationAnnotation: NSObject, MGLAnnotation { } /// POI map annotation -class PinLocationAnnotation: LocationAnnotation {} +class PinLocationAnnotation: LocationAnnotation { } /// User map annotation class UserLocationAnnotation: LocationAnnotation { - // MARK: - Properties var userId: String { - return avatarData.matrixItemId + avatarData.matrixItemId } let avatarData: AvatarInputProtocol @@ -53,13 +51,12 @@ class UserLocationAnnotation: LocationAnnotation { init(avatarData: AvatarInputProtocol, coordinate: CLLocationCoordinate2D) { - self.avatarData = avatarData super.init(coordinate: coordinate) - super.title = self.avatarData.displayName ?? self.userId + super.title = self.avatarData.displayName ?? userId } } /// Invisible annotation -class InvisibleLocationAnnotation: LocationAnnotation {} +class InvisibleLocationAnnotation: LocationAnnotation { } diff --git a/RiotSwiftUI/Modules/LocationSharing/MapView/View/LocationSharingMapView.swift b/RiotSwiftUI/Modules/LocationSharing/MapView/View/LocationSharingMapView.swift index d244437ae..9b5073b33 100644 --- a/RiotSwiftUI/Modules/LocationSharing/MapView/View/LocationSharingMapView.swift +++ b/RiotSwiftUI/Modules/LocationSharing/MapView/View/LocationSharingMapView.swift @@ -14,15 +14,14 @@ // limitations under the License. // -import SwiftUI import Combine import Mapbox +import SwiftUI struct LocationSharingMapView: UIViewRepresentable { - // MARK: - Constants - private struct Constants { + private enum Constants { static let mapZoomLevel = 15.0 } @@ -41,10 +40,10 @@ struct LocationSharingMapView: UIViewRepresentable { let userAvatarData: AvatarInputProtocol? /// True to indicate to show and follow current user location - var showsUserLocation: Bool = false + var showsUserLocation = false /// True to indicate that a touch on user annotation can show a callout - var userAnnotationCanShowCallout: Bool = false + var userAnnotationCanShowCallout = false /// Last user location if `showsUserLocation` has been enabled @Binding var userLocation: CLLocationCoordinate2D? @@ -64,8 +63,7 @@ struct LocationSharingMapView: UIViewRepresentable { // MARK: - UIViewRepresentable func makeUIView(context: Context) -> MGLMapView { - - let mapView = self.makeMapView() + let mapView = makeMapView() mapView.delegate = context.coordinator let panGesture = UIPanGestureRecognizer(target: context.coordinator, action: #selector(context.coordinator.didPan)) panGesture.delegate = context.coordinator @@ -74,15 +72,14 @@ struct LocationSharingMapView: UIViewRepresentable { } func updateUIView(_ mapView: MGLMapView, context: Context) { - mapView.vc_removeAllAnnotations() - mapView.addAnnotations(self.annotations) + mapView.addAnnotations(annotations) - if let highlightedAnnotation = self.highlightedAnnotation { + if let highlightedAnnotation = highlightedAnnotation { mapView.setCenter(highlightedAnnotation.coordinate, zoomLevel: Constants.mapZoomLevel, animated: false) } - if self.showsUserLocation { + if showsUserLocation { mapView.showsUserLocation = true mapView.userTrackingMode = .follow } else { @@ -108,24 +105,22 @@ struct LocationSharingMapView: UIViewRepresentable { } // MARK: - Coordinator + extension LocationSharingMapView { - class Coordinator: NSObject, MGLMapViewDelegate, UIGestureRecognizerDelegate { - // MARK: - Properties var locationSharingMapView: LocationSharingMapView // MARK: - Setup - init(_ locationSharingMapView: LocationSharingMapView) { - self.locationSharingMapView = locationSharingMapView - } + init(_ locationSharingMapView: LocationSharingMapView) { + self.locationSharingMapView = locationSharingMapView + } // MARK: - MGLMapViewDelegate func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? { - if let userLocationAnnotation = annotation as? UserLocationAnnotation { return LocationAnnotationView(userLocationAnnotation: userLocationAnnotation) } else if let pinLocationAnnotation = annotation as? PinLocationAnnotation { @@ -168,7 +163,7 @@ extension LocationSharingMapView { // MARK: Callout func mapView(_ mapView: MGLMapView, annotationCanShowCallout annotation: MGLAnnotation) -> Bool { - return annotation is UserLocationAnnotation && locationSharingMapView.userAnnotationCanShowCallout + annotation is UserLocationAnnotation && locationSharingMapView.userAnnotationCanShowCallout } func mapView(_ mapView: MGLMapView, calloutViewFor annotation: MGLAnnotation) -> MGLCalloutView? { @@ -188,7 +183,7 @@ extension LocationSharingMapView { // MARK: UIGestureRecognizer func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { - return gestureRecognizer is UIPanGestureRecognizer + gestureRecognizer is UIPanGestureRecognizer } @objc @@ -199,12 +194,12 @@ extension LocationSharingMapView { } // MARK: - MGLMapView convenient methods + extension MGLMapView { - func vc_removeAllAnnotations() { - guard let annotations = self.annotations else { + guard let annotations = annotations else { return } - self.removeAnnotations(annotations) + removeAnnotations(annotations) } } diff --git a/RiotSwiftUI/Modules/LocationSharing/MapView/View/LocationSharingMarkerView.swift b/RiotSwiftUI/Modules/LocationSharing/MapView/View/LocationSharingMarkerView.swift index 0450b16a3..7cf7f7e4a 100644 --- a/RiotSwiftUI/Modules/LocationSharing/MapView/View/LocationSharingMarkerView.swift +++ b/RiotSwiftUI/Modules/LocationSharing/MapView/View/LocationSharingMarkerView.swift @@ -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 LocationSharingMarkerView: View { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/LocationSharing/MapView/View/UserAnnotationCalloutContentView.swift b/RiotSwiftUI/Modules/LocationSharing/MapView/View/UserAnnotationCalloutContentView.swift index 419213972..556b76030 100644 --- a/RiotSwiftUI/Modules/LocationSharing/MapView/View/UserAnnotationCalloutContentView.swift +++ b/RiotSwiftUI/Modules/LocationSharing/MapView/View/UserAnnotationCalloutContentView.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import Foundation import Reusable class UserAnnotationCalloutContentView: UIView, Themable, NibLoadable { - // MARK: - Constants private static let sizingView = UserAnnotationCalloutContentView.instantiate() @@ -39,16 +38,16 @@ class UserAnnotationCalloutContentView: UIView, Themable, NibLoadable { // MARK: - Setup static func instantiate() -> UserAnnotationCalloutContentView { - return UserAnnotationCalloutContentView.loadFromNib() + UserAnnotationCalloutContentView.loadFromNib() } // MARK: - Public func update(theme: Theme) { - self.backgroundView.backgroundColor = theme.colors.background - self.titleLabel.textColor = theme.colors.secondaryContent - self.titleLabel.font = theme.fonts.callout - self.shareButton.tintColor = theme.colors.secondaryContent + backgroundView.backgroundColor = theme.colors.background + titleLabel.textColor = theme.colors.secondaryContent + titleLabel.font = theme.fonts.callout + shareButton.tintColor = theme.colors.secondaryContent } // MARK: - Life cycle @@ -56,18 +55,18 @@ class UserAnnotationCalloutContentView: UIView, Themable, NibLoadable { override func awakeFromNib() { super.awakeFromNib() - self.titleLabel.text = VectorL10n.locationSharingLiveMapCalloutTitle - self.backgroundView.layer.masksToBounds = true + titleLabel.text = VectorL10n.locationSharingLiveMapCalloutTitle + backgroundView.layer.masksToBounds = true } override func layoutSubviews() { super.layoutSubviews() - self.backgroundView.layer.cornerRadius = Constants.cornerRadius + backgroundView.layer.cornerRadius = Constants.cornerRadius } static func contentViewSize() -> CGSize { - let sizingView = self.sizingView + let sizingView = sizingView sizingView.frame = CGRect(x: 0, y: 0, width: 1, height: Constants.height) @@ -77,8 +76,8 @@ class UserAnnotationCalloutContentView: UIView, Themable, NibLoadable { let fittingSize = CGSize(width: UIView.layoutFittingCompressedSize.width, height: Constants.height) let size = sizingView.systemLayoutSizeFitting(fittingSize, - withHorizontalFittingPriority: .fittingSizeLevel, - verticalFittingPriority: .required) + withHorizontalFittingPriority: .fittingSizeLevel, + verticalFittingPriority: .required) return size } diff --git a/RiotSwiftUI/Modules/LocationSharing/MapView/View/UserAnnotationCalloutView.swift b/RiotSwiftUI/Modules/LocationSharing/MapView/View/UserAnnotationCalloutView.swift index 64edcfd30..f405c179a 100644 --- a/RiotSwiftUI/Modules/LocationSharing/MapView/View/UserAnnotationCalloutView.swift +++ b/RiotSwiftUI/Modules/LocationSharing/MapView/View/UserAnnotationCalloutView.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ import Mapbox class UserAnnotationCalloutView: UIView, MGLCalloutView, Themable { - // MARK: - Constants private enum Constants { @@ -31,16 +30,16 @@ class UserAnnotationCalloutView: UIView, MGLCalloutView, Themable { var representedObject: MGLAnnotation - lazy var leftAccessoryView: UIView = UIView() + lazy var leftAccessoryView = UIView() - lazy var rightAccessoryView: UIView = UIView() + lazy var rightAccessoryView = UIView() var delegate: MGLCalloutViewDelegate? // Allow the callout to remain open during panning. - let dismissesAutomatically: Bool = false + let dismissesAutomatically = false - let isAnchoredToAnnotation: Bool = true + let isAnchoredToAnnotation = true // https://github.com/mapbox/mapbox-gl-native/issues/9228 override var center: CGPoint { @@ -50,33 +49,31 @@ class UserAnnotationCalloutView: UIView, MGLCalloutView, Themable { super.center = newCenter } get { - return super.center + super.center } } // MARK: Private - lazy var contentView: UserAnnotationCalloutContentView = { - return UserAnnotationCalloutContentView.instantiate() - }() + lazy var contentView = UserAnnotationCalloutContentView.instantiate() // MARK: - Setup required init(userLocationAnnotation: UserLocationAnnotation) { - - self.representedObject = userLocationAnnotation + representedObject = userLocationAnnotation super.init(frame: .zero) - self.vc_addSubViewMatchingParent(self.contentView) + vc_addSubViewMatchingParent(contentView) - self.update(theme: ThemeService.shared().theme) + update(theme: ThemeService.shared().theme) let size = UserAnnotationCalloutContentView.contentViewSize() - self.frame = CGRect(origin: .zero, size: size) + frame = CGRect(origin: .zero, size: size) } + @available(*, unavailable) required init?(coder decoder: NSCoder) { fatalError("init(coder:) has not been implemented") } @@ -84,16 +81,15 @@ class UserAnnotationCalloutView: UIView, MGLCalloutView, Themable { // MARK: - Public func update(theme: Theme) { - self.contentView.update(theme: theme) + contentView.update(theme: theme) } // MARK: - Overrides func presentCallout(from rect: CGRect, in view: UIView, constrainedTo constrainedRect: CGRect, animated: Bool) { - // Set callout above the marker view - self.center = view.center.applying(CGAffineTransform(translationX: 0, y: view.bounds.height/2 + self.bounds.height)) + center = view.center.applying(CGAffineTransform(translationX: 0, y: view.bounds.height / 2 + bounds.height)) delegate?.calloutViewWillAppear?(self) @@ -101,10 +97,10 @@ class UserAnnotationCalloutView: UIView, MGLCalloutView, Themable { if isCalloutTappable() { // Handle taps and eventually try to send them to the delegate (usually the map view). - self.contentView.shareButton.addTarget(self, action: #selector(UserAnnotationCalloutView.calloutTapped), for: .touchUpInside) + contentView.shareButton.addTarget(self, action: #selector(UserAnnotationCalloutView.calloutTapped), for: .touchUpInside) } else { // Disable tapping and highlighting. - self.contentView.shareButton.isUserInteractionEnabled = false + contentView.shareButton.isUserInteractionEnabled = false } if animated { @@ -124,7 +120,7 @@ class UserAnnotationCalloutView: UIView, MGLCalloutView, Themable { } func dismissCallout(animated: Bool) { - if (superview != nil) { + if superview != nil { if animated { UIView.animate(withDuration: Constants.animationDuration, animations: { [weak self] in self?.alpha = 0 @@ -149,7 +145,7 @@ class UserAnnotationCalloutView: UIView, MGLCalloutView, Themable { } @objc func calloutTapped() { - if isCalloutTappable() && delegate!.responds(to: #selector(MGLCalloutViewDelegate.calloutViewTapped)) { + if isCalloutTappable(), delegate!.responds(to: #selector(MGLCalloutViewDelegate.calloutViewTapped)) { delegate!.calloutViewTapped!(self) } } diff --git a/RiotSwiftUI/Modules/LocationSharing/MapView/View/UserLocationAnnotationView.swift b/RiotSwiftUI/Modules/LocationSharing/MapView/View/UserLocationAnnotationView.swift index 4662ae485..25a5b9848 100644 --- a/RiotSwiftUI/Modules/LocationSharing/MapView/View/UserLocationAnnotationView.swift +++ b/RiotSwiftUI/Modules/LocationSharing/MapView/View/UserLocationAnnotationView.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,11 +15,10 @@ // import Foundation -import SwiftUI import Mapbox +import SwiftUI class LocationAnnotationView: MGLUserLocationAnnotationView { - // MARK: - Constants private enum Constants { @@ -34,31 +33,30 @@ class LocationAnnotationView: MGLUserLocationAnnotationView { override init(annotation: MGLAnnotation?, reuseIdentifier: String?) { super.init(annotation: annotation, reuseIdentifier: - reuseIdentifier) - self.frame = Constants.defaultFrame + reuseIdentifier) + frame = Constants.defaultFrame } convenience init(avatarData: AvatarInputProtocol) { self.init(annotation: nil, reuseIdentifier: nil) - self.addUserMarkerView(with: avatarData) + addUserMarkerView(with: avatarData) } convenience init(userLocationAnnotation: UserLocationAnnotation) { - // TODO: Use a reuseIdentifier self.init(annotation: userLocationAnnotation, reuseIdentifier: nil) - self.addUserMarkerView(with: userLocationAnnotation.avatarData) + addUserMarkerView(with: userLocationAnnotation.avatarData) } convenience init(pinLocationAnnotation: PinLocationAnnotation) { - // TODO: Use a reuseIdentifier self.init(annotation: pinLocationAnnotation, reuseIdentifier: nil) - self.addPinMarkerView() + addPinMarkerView() } + @available(*, unavailable) required init?(coder: NSCoder) { fatalError() } @@ -66,7 +64,6 @@ class LocationAnnotationView: MGLUserLocationAnnotationView { // MARK: - Private private func addUserMarkerView(with avatarData: AvatarInputProtocol) { - guard let avatarMarkerView = UIHostingController(rootView: LocationSharingMarkerView(backgroundColor: theme.userColor(for: avatarData.matrixItemId)) { AvatarImage(avatarData: avatarData, size: .medium) .border() @@ -90,11 +87,10 @@ class LocationAnnotationView: MGLUserLocationAnnotationView { } private func addMarkerView(_ markerView: UIView) { - markerView.backgroundColor = .clear addSubview(markerView) - markerView.frame = self.bounds + markerView.frame = bounds } } diff --git a/RiotSwiftUI/Modules/LocationSharing/ShareLocationActivity/ShareLocationActivityController.swift b/RiotSwiftUI/Modules/LocationSharing/ShareLocationActivity/ShareLocationActivityController.swift index 4b3e6ca72..6c5f00154 100644 --- a/RiotSwiftUI/Modules/LocationSharing/ShareLocationActivity/ShareLocationActivityController.swift +++ b/RiotSwiftUI/Modules/LocationSharing/ShareLocationActivity/ShareLocationActivityController.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,16 +14,15 @@ // limitations under the License. // -import Foundation import CoreLocation +import Foundation /// Build a UIActivityViewController to share a location class ShareLocationActivityControllerBuilder { - func build(with location: CLLocationCoordinate2D) -> UIActivityViewController { - return UIActivityViewController(activityItems: [ShareToMapsAppActivity.urlForMapsAppType(.apple, location: location)], - applicationActivities: [ShareToMapsAppActivity(type: .apple, location: location), - ShareToMapsAppActivity(type: .google, location: location), - ShareToMapsAppActivity(type: .osm, location: location)]) + UIActivityViewController(activityItems: [ShareToMapsAppActivity.urlForMapsAppType(.apple, location: location)], + applicationActivities: [ShareToMapsAppActivity(type: .apple, location: location), + ShareToMapsAppActivity(type: .google, location: location), + ShareToMapsAppActivity(type: .osm, location: location)]) } } diff --git a/RiotSwiftUI/Modules/LocationSharing/ShareLocationActivity/ShareToMapsAppActivity.swift b/RiotSwiftUI/Modules/LocationSharing/ShareLocationActivity/ShareToMapsAppActivity.swift index 53b96121d..1d325e733 100644 --- a/RiotSwiftUI/Modules/LocationSharing/ShareLocationActivity/ShareToMapsAppActivity.swift +++ b/RiotSwiftUI/Modules/LocationSharing/ShareLocationActivity/ShareToMapsAppActivity.swift @@ -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 UIKit import CoreLocation +import UIKit extension UIActivity.ActivityType { static let shareToMapsApp = UIActivity.ActivityType("Element.ShareToMapsApp") @@ -31,7 +31,7 @@ class ShareToMapsAppActivity: UIActivity { private let type: MapsAppType private let location: CLLocationCoordinate2D - private override init() { + override private init() { fatalError() } @@ -63,15 +63,15 @@ class ShareToMapsAppActivity: UIActivity { } var activityCategory: UIActivity.Category { - return .action + .action } override var activityType: UIActivity.ActivityType { - return .shareToMapsApp + .shareToMapsApp } override func canPerform(withActivityItems activityItems: [Any]) -> Bool { - return true + true } override func prepare(withActivityItems activityItems: [Any]) { diff --git a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Coordinator/LocationSharingCoordinator.swift b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Coordinator/LocationSharingCoordinator.swift index b6d0669cd..266d5e03b 100644 --- a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Coordinator/LocationSharingCoordinator.swift +++ b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Coordinator/LocationSharingCoordinator.swift @@ -15,9 +15,9 @@ // import Foundation -import UIKit -import SwiftUI import MatrixSDK +import SwiftUI +import UIKit struct LocationSharingCoordinatorParameters { let session: MXSession @@ -57,7 +57,6 @@ extension LocationSharingCoordinateType { } final class LocationSharingCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -83,7 +82,8 @@ final class LocationSharingCoordinator: Coordinator, Presentable { mapStyleURL: parameters.session.vc_homeserverConfiguration().tileServer.mapStyleURL, avatarData: parameters.avatarData, isLiveLocationSharingEnabled: true, - service: locationSharingService) + service: locationSharingService + ) let view = LocationSharingView(context: viewModel.context) .addDependency(AvatarService.instantiate(mediaManager: parameters.mediaManager)) @@ -93,6 +93,7 @@ final class LocationSharingCoordinator: Coordinator, Presentable { } // MARK: - Public + func start() { locationSharingViewModel.completion = { [weak self] result in guard let self = self else { return } @@ -111,22 +112,22 @@ final class LocationSharingCoordinator: Coordinator, Presentable { } static func shareLocationActivityController(_ location: CLLocationCoordinate2D) -> UIActivityViewController { - return UIActivityViewController(activityItems: [ShareToMapsAppActivity.urlForMapsAppType(.apple, location: location)], - applicationActivities: [ShareToMapsAppActivity(type: .apple, location: location), - ShareToMapsAppActivity(type: .google, location: location), - ShareToMapsAppActivity(type: .osm, location: location)]) + UIActivityViewController(activityItems: [ShareToMapsAppActivity.urlForMapsAppType(.apple, location: location)], + applicationActivities: [ShareToMapsAppActivity(type: .apple, location: location), + ShareToMapsAppActivity(type: .google, location: location), + ShareToMapsAppActivity(type: .osm, location: location)]) } // MARK: - Private private func presentShareLocationActivity(with location: CLLocationCoordinate2D) { - self.locationSharingHostingController.present(Self.shareLocationActivityController(location), animated: true) + locationSharingHostingController.present(Self.shareLocationActivityController(location), animated: true) } private func shareStaticLocation(latitude: Double, longitude: Double, coordinateType: LocationSharingCoordinateType) { - self.locationSharingViewModel.startLoading() + locationSharingViewModel.startLoading() - self.parameters.roomDataSource.sendLocation(withLatitude: latitude, longitude: longitude, description: nil, coordinateType: coordinateType.eventAssetType()) { [weak self] _ in + parameters.roomDataSource.sendLocation(withLatitude: latitude, longitude: longitude, description: nil, coordinateType: coordinateType.eventAssetType()) { [weak self] _ in guard let self = self else { return } self.locationSharingViewModel.stopLoading() @@ -140,8 +141,8 @@ final class LocationSharingCoordinator: Coordinator, Presentable { } private func startLiveLocationSharing(with timeout: TimeInterval) { - guard let locationService = self.parameters.roomDataSource.mxSession.locationService, let roomId = self.parameters.roomDataSource.roomId else { - self.locationSharingViewModel.stopLoading(error: .locationSharingError) + guard let locationService = parameters.roomDataSource.mxSession.locationService, let roomId = parameters.roomDataSource.roomId else { + locationSharingViewModel.stopLoading(error: .locationSharingError) return } @@ -166,16 +167,15 @@ final class LocationSharingCoordinator: Coordinator, Presentable { } private func checkLiveLocationCanBeStarted(completion: @escaping ((Result) -> Void)) { - - guard self.canShareLiveLocation() else { + guard canShareLiveLocation() else { completion(.failure(LiveLocationStartError.powerLevelNotHighEnough)) return } - self.showLabFlagPromotionIfNeeded { labFlagEnabled in + showLabFlagPromotionIfNeeded { labFlagEnabled in if labFlagEnabled { - completion(.success(Void())) + completion(.success(())) } else { completion(.failure(LiveLocationStartError.labFlagNotEnabled)) } @@ -184,18 +184,18 @@ final class LocationSharingCoordinator: Coordinator, Presentable { // Check if user can send beacon info state event private func canShareLiveLocation() -> Bool { - guard let myUserId = self.parameters.roomDataSource.mxSession.myUserId else { + guard let myUserId = parameters.roomDataSource.mxSession.myUserId else { return false } - let userPowerLevelRawValue = self.parameters.roomDataSource.roomState.powerLevels.powerLevelOfUser(withUserID: myUserId) + let userPowerLevelRawValue = parameters.roomDataSource.roomState.powerLevels.powerLevelOfUser(withUserID: myUserId) guard let userPowerLevel = RoomPowerLevel(rawValue: userPowerLevelRawValue) else { return false } return userPowerLevel.rawValue >= RoomPowerLevel.moderator.rawValue - } + } private func showLabFlagPromotionIfNeeded(completion: @escaping ((Bool) -> Void)) { guard RiotSettings.shared.enableLiveLocationSharing == false else { @@ -204,11 +204,10 @@ final class LocationSharingCoordinator: Coordinator, Presentable { return } - self.showLabFlagPromotion(completion: completion) + showLabFlagPromotion(completion: completion) } private func showLabFlagPromotion(completion: @escaping ((Bool) -> Void)) { - // TODO: Use a NavigationRouter instead of using NavigationView inside LocationSharingView // In order to use `NavigationRouter.present` @@ -224,14 +223,14 @@ final class LocationSharingCoordinator: Coordinator, Presentable { } } - self.locationSharingHostingController.present(coordinator.toPresentable(), animated: true) + locationSharingHostingController.present(coordinator.toPresentable(), animated: true) - self.add(childCoordinator: coordinator) + add(childCoordinator: coordinator) } // MARK: - Presentable func toPresentable() -> UIViewController { - return locationSharingHostingController + locationSharingHostingController } } diff --git a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/LocationSharingModels.swift b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/LocationSharingModels.swift index 1a5304b87..3178bcb87 100644 --- a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/LocationSharingModels.swift +++ b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/LocationSharingModels.swift @@ -14,10 +14,10 @@ // limitations under the License. // -import Foundation -import SwiftUI import Combine import CoreLocation +import Foundation +import SwiftUI // This is the equivalent of MXEventAssetType in the MatrixSDK enum LocationSharingCoordinateType { @@ -27,9 +27,9 @@ enum LocationSharingCoordinateType { enum LiveLocationSharingTimeout: TimeInterval { // Timer are in milliseconde because timestamp are in millisecond in Matrix SDK - case short = 900000 // 15 minutes - case medium = 3600000 // 1 hour - case long = 28800000 // 8 hours + case short = 900_000 // 15 minutes + case medium = 3_600_000 // 1 hour + case long = 28_800_000 // 8 hours } enum LocationSharingViewAction { @@ -47,7 +47,7 @@ enum LocationSharingViewModelResult { case cancel case share(latitude: Double, longitude: Double, coordinateType: LocationSharingCoordinateType) case shareLiveLocation(timeout: TimeInterval) - case checkLiveLocationCanBeStarted(_ completion: ((Result) -> Void)) + case checkLiveLocationCanBeStarted(_ completion: (Result) -> Void) } enum LiveLocationStartError: Error { @@ -63,7 +63,6 @@ enum LocationSharingViewError { } struct LocationSharingViewState: BindableState { - /// Map style URL let mapStyleURL: URL @@ -77,21 +76,21 @@ struct LocationSharingViewState: BindableState { var highlightedAnnotation: LocationAnnotation? /// Indicates whether the user has moved around the map to drop a pin somewhere other than their current location - var isPinDropSharing: Bool = false + var isPinDropSharing = false - var showLoadingIndicator: Bool = false + var showLoadingIndicator = false /// True to indicate to show and follow current user location - var showsUserLocation: Bool = false + var showsUserLocation = false /// Used to hide live location sharing features - var isLiveLocationSharingEnabled: Bool = false + var isLiveLocationSharingEnabled = false var shareButtonEnabled: Bool { !showLoadingIndicator } - var showMapLoadingError: Bool = false + var showMapLoadingError = false let errorSubject = PassthroughSubject() diff --git a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/LocationSharingScreenState.swift b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/LocationSharingScreenState.swift index defbf11fc..3b86f4e89 100644 --- a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/LocationSharingScreenState.swift +++ b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/LocationSharingScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,9 +14,9 @@ // limitations under the License. // +import CoreLocation import Foundation import SwiftUI -import CoreLocation enum MockLocationSharingScreenState: MockScreenState, CaseIterable { case shareUserLocation @@ -25,8 +25,7 @@ enum MockLocationSharingScreenState: MockScreenState, CaseIterable { LocationSharingView.self } - var screenView: ([Any], AnyView) { - + var screenView: ([Any], AnyView) { let locationSharingService = MockLocationSharingService() let mapStyleURL = URL(string: "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx")! @@ -35,6 +34,6 @@ enum MockLocationSharingScreenState: MockScreenState, CaseIterable { isLiveLocationSharingEnabled: true, service: locationSharingService) return ([viewModel], AnyView(LocationSharingView(context: viewModel.context) - .addDependency(MockAvatarService.example))) + .addDependency(MockAvatarService.example))) } } diff --git a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/LocationSharingViewModel.swift b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/LocationSharingViewModel.swift index 56cdb1f1c..cbde1a243 100644 --- a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/LocationSharingViewModel.swift +++ b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/LocationSharingViewModel.swift @@ -14,15 +14,14 @@ // limitations under the License. // -import SwiftUI import Combine import CoreLocation +import SwiftUI typealias LocationSharingViewModelType = StateStoreViewModel + Never, + LocationSharingViewAction> class LocationSharingViewModel: LocationSharingViewModelType, LocationSharingViewModelProtocol { - // MARK: - Properties // MARK: Private @@ -36,8 +35,7 @@ class LocationSharingViewModel: LocationSharingViewModelType, LocationSharingVie // MARK: - Setup init(mapStyleURL: URL, avatarData: AvatarInputProtocol, isLiveLocationSharingEnabled: Bool = false, service: LocationSharingServiceProtocol) { - - self.locationSharingService = service + locationSharingService = service let viewState = LocationSharingViewState(mapStyleURL: mapStyleURL, userAvatarData: avatarData, @@ -79,7 +77,7 @@ class LocationSharingViewModel: LocationSharingViewModelType, LocationSharingVie state.showsUserLocation = true state.isPinDropSharing = false case .startLiveSharing: - self.startLiveLocationSharing() + startLiveLocationSharing() case .shareLiveLocation(let timeout): state.bindings.showingTimerSelector = false completion?(.shareLiveLocation(timeout: timeout.rawValue)) @@ -101,8 +99,7 @@ class LocationSharingViewModel: LocationSharingViewModelType, LocationSharingVie state.showLoadingIndicator = false if let error = error { - - let alertInfo: AlertInfo + let alertInfo: AlertInfo switch error { case .locationSharingPowerLevelError: @@ -128,7 +125,7 @@ class LocationSharingViewModel: LocationSharingViewModelType, LocationSharingVie return } - let primaryButtonCompletion = { [weak self] () -> Void in + let primaryButtonCompletion: (() -> Void)? = { [weak self] () in self?.completion?(.cancel) } @@ -149,16 +146,15 @@ class LocationSharingViewModel: LocationSharingViewModelType, LocationSharingVie title: VectorL10n.locationSharingInvalidAuthorizationErrorTitle(AppInfo.current.displayName), primaryButton: (VectorL10n.locationSharingInvalidAuthorizationNotNow, primaryButtonCompletion), secondaryButton: (VectorL10n.locationSharingInvalidAuthorizationSettings, { - UIApplication.shared.vc_openSettings() - })) + UIApplication.shared.vc_openSettings() + })) default: break } } private func checkLocationAuthorizationAndPresentTimerSelector() { - - self.locationSharingService.requestAuthorization { [weak self] authorizationStatus in + locationSharingService.requestAuthorization { [weak self] authorizationStatus in guard let self = self else { return @@ -168,15 +164,15 @@ class LocationSharingViewModel: LocationSharingViewModelType, LocationSharingVie case .unknown, .denied: // Show error alert self.state.bindings.alertInfo = AlertInfo(id: .userLocatingError, - title: VectorL10n.locationSharingLocatingUserErrorTitle(AppInfo.current.displayName), + title: VectorL10n.locationSharingLocatingUserErrorTitle(AppInfo.current.displayName), primaryButton: (VectorL10n.ok, { UIApplication.shared.vc_openSettings() - })) + })) case .authorizedInForeground: // When user only authorized location in foreground, advize to use background location self.state.bindings.alertInfo = AlertInfo(id: .userLocatingError, title: VectorL10n.locationSharingAllowBackgroundLocationTitle, - message: VectorL10n.locationSharingAllowBackgroundLocationMessage, - primaryButton: (VectorL10n.locationSharingAllowBackgroundLocationCancelAction, {}), + message: VectorL10n.locationSharingAllowBackgroundLocationMessage, + primaryButton: (VectorL10n.locationSharingAllowBackgroundLocationCancelAction, { }), secondaryButton: (VectorL10n.locationSharingAllowBackgroundLocationValidateAction, { UIApplication.shared.vc_openSettings() })) case .authorizedAlways: self.state.bindings.showingTimerSelector = true @@ -185,12 +181,11 @@ class LocationSharingViewModel: LocationSharingViewModelType, LocationSharingVie } private func startLiveLocationSharing() { - guard let completion = completion else { return } - completion(.checkLiveLocationCanBeStarted({ result in + completion(.checkLiveLocationCanBeStarted { result in switch result { case .success: @@ -200,6 +195,6 @@ class LocationSharingViewModel: LocationSharingViewModelType, LocationSharingVie self.stopLoading(error: .locationSharingPowerLevelError) } } - })) + }) } } diff --git a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/LocationSharingViewModelProtocol.swift b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/LocationSharingViewModelProtocol.swift index a15349a3b..eeed96aff 100644 --- a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/LocationSharingViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/LocationSharingViewModelProtocol.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Service/LocationSharingServiceProtocol.swift b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Service/LocationSharingServiceProtocol.swift index 64cfac575..288a7cc7a 100644 --- a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Service/LocationSharingServiceProtocol.swift +++ b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Service/LocationSharingServiceProtocol.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,15 +14,14 @@ // limitations under the License. // -import Foundation import Combine import CoreLocation +import Foundation /// Location authorization request handler typealias LocationAuthorizationHandler = (_ authorizationStatus: LocationAuthorizationStatus) -> Void protocol LocationSharingServiceProtocol { - /// Request location authorization func requestAuthorization(_ handler: @escaping LocationAuthorizationHandler) } diff --git a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Service/MatrixSDK/LocationSharingService.swift b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Service/MatrixSDK/LocationSharingService.swift index d7692c29e..980220384 100644 --- a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Service/MatrixSDK/LocationSharingService.swift +++ b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Service/MatrixSDK/LocationSharingService.swift @@ -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 CoreLocation +import Foundation import MatrixSDK class LocationSharingService: LocationSharingServiceProtocol { - // MARK: - Properties // MARK: Private @@ -27,7 +26,7 @@ class LocationSharingService: LocationSharingServiceProtocol { private let session: MXSession private var userLocationService: UserLocationServiceProtocol? { - return self.session.userLocationService + session.userLocationService } // MARK: Public @@ -41,8 +40,7 @@ class LocationSharingService: LocationSharingServiceProtocol { // MARK: - Public func requestAuthorization(_ handler: @escaping LocationAuthorizationHandler) { - guard let userLocationService = self.userLocationService else { - + guard let userLocationService = userLocationService else { MXLog.error("[LocationSharingService] No userLocationService found for the current session") handler(LocationAuthorizationStatus.unknown) return diff --git a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Service/Mock/MockLocationSharingService.swift b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Service/Mock/MockLocationSharingService.swift index 8b8de5a5a..a36d3b726 100644 --- a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Service/Mock/MockLocationSharingService.swift +++ b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Service/Mock/MockLocationSharingService.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,9 +14,9 @@ // limitations under the License. // -import Foundation import Combine import CoreLocation +import Foundation class MockLocationSharingService: LocationSharingServiceProtocol { func requestAuthorization(_ handler: @escaping LocationAuthorizationHandler) { diff --git a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Test/UI/LocationSharingUITests.swift b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Test/UI/LocationSharingUITests.swift index d9fb19faa..0b55053f8 100644 --- a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Test/UI/LocationSharingUITests.swift +++ b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Test/UI/LocationSharingUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class LocationSharingUITests: MockScreenTestCase { func testInitialUserLocation() { diff --git a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Test/Unit/LocationSharingViewModelTests.swift b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Test/Unit/LocationSharingViewModelTests.swift index 1eacdee00..1914b4478 100644 --- a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Test/Unit/LocationSharingViewModelTests.swift +++ b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/Test/Unit/LocationSharingViewModelTests.swift @@ -14,14 +14,13 @@ // limitations under the License. // -import XCTest import Combine import CoreLocation +import XCTest @testable import RiotSwiftUI class LocationSharingViewModelTests: XCTestCase { - var cancellables = Set() func testInitialState() { @@ -40,7 +39,7 @@ class LocationSharingViewModelTests: XCTestCase { func testCancellation() { let viewModel = buildViewModel() - let expectation = self.expectation(description: "Cancellation completion should be invoked") + let expectation = expectation(description: "Cancellation completion should be invoked") viewModel.completion = { result in switch result { @@ -95,10 +94,9 @@ class LocationSharingViewModelTests: XCTestCase { } private func buildViewModel() -> LocationSharingViewModel { - let service = MockLocationSharingService() return LocationSharingViewModel(mapStyleURL: URL(string: "http://empty.com")!, - avatarData: AvatarInput(mxContentUri: "", matrixItemId: "", displayName: ""), service: service) + avatarData: AvatarInput(mxContentUri: "", matrixItemId: "", displayName: ""), service: service) } } diff --git a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/View/LocationSharingOptionButton.swift b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/View/LocationSharingOptionButton.swift index 964784f57..556f410f4 100644 --- a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/View/LocationSharingOptionButton.swift +++ b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/View/LocationSharingOptionButton.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ import SwiftUI struct LocationSharingOptionButton: View { - // MARK: - Properties // MARK: Private @@ -25,7 +24,7 @@ struct LocationSharingOptionButton: View { @Environment(\.theme) private var theme: ThemeSwiftUI let text: String - let action: () -> (Void) + let action: () -> Void @ViewBuilder var buttonIcon: Content var body: some View { @@ -44,21 +43,15 @@ struct LocationSharingOptionButton: View { struct LocationSharingOptionButton_Previews: PreviewProvider { static var previews: some View { VStack(alignment: .leading) { - LocationSharingOptionButton(text: VectorL10n.locationSharingStaticShareTitle) { - - } buttonIcon: { + LocationSharingOptionButton(text: VectorL10n.locationSharingStaticShareTitle) { } buttonIcon: { AvatarImage(avatarData: AvatarInput(mxContentUri: nil, matrixItemId: "Alice", displayName: "Alice"), size: .medium) .border() } - LocationSharingOptionButton(text: VectorL10n.locationSharingLiveShareTitle) { - - } buttonIcon: { + LocationSharingOptionButton(text: VectorL10n.locationSharingLiveShareTitle) { } buttonIcon: { Image(uiImage: Asset.Images.locationLiveIcon.image) .resizable() } - LocationSharingOptionButton(text: VectorL10n.locationSharingPinDropShareTitle) { - - } buttonIcon: { + LocationSharingOptionButton(text: VectorL10n.locationSharingPinDropShareTitle) { } buttonIcon: { Image(uiImage: Asset.Images.locationPinIcon.image) .resizable() } diff --git a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/View/LocationSharingView.swift b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/View/LocationSharingView.swift index 5f82bce08..a2acb30f1 100644 --- a/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/View/LocationSharingView.swift +++ b/RiotSwiftUI/Modules/LocationSharing/StartLocationSharing/View/LocationSharingView.swift @@ -14,11 +14,10 @@ // limitations under the License. // -import SwiftUI import CoreLocation +import SwiftUI struct LocationSharingView: View { - // MARK: - Properties // MARK: Private @@ -39,7 +38,6 @@ struct LocationSharingView: View { } VStack(spacing: 0) { - if context.viewState.showMapLoadingError { MapLoadingErrorView() } else { @@ -50,7 +48,7 @@ struct LocationSharingView: View { }) .padding(.bottom, 10.0) .actionSheet(isPresented: $context.showMapCreditsSheet) { - return MapCreditsActionSheet(openURL: { url in + MapCreditsActionSheet(openURL: { url in openURL(url) }).sheet } @@ -99,8 +97,8 @@ struct LocationSharingView: View { mapCenterCoordinate: $context.pinLocation, errorSubject: context.viewState.errorSubject, userDidPan: { - context.send(viewAction: .userDidPan) - }) + context.send(viewAction: .userDidPan) + }) if context.viewState.isPinDropSharing { LocationSharingMarkerView(backgroundColor: theme.colors.accent) { Image(uiImage: Asset.Images.locationPinIcon.image) diff --git a/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/Coordinator/StaticLocationViewingCoordinator.swift b/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/Coordinator/StaticLocationViewingCoordinator.swift index 9475eeac8..b125fbcd6 100644 --- a/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/Coordinator/StaticLocationViewingCoordinator.swift +++ b/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/Coordinator/StaticLocationViewingCoordinator.swift @@ -15,9 +15,9 @@ // import Foundation -import UIKit -import SwiftUI import MatrixSDK +import SwiftUI +import UIKit struct StaticLocationViewingCoordinatorParameters { let session: MXSession @@ -28,7 +28,6 @@ struct StaticLocationViewingCoordinatorParameters { } final class StaticLocationViewingCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -54,7 +53,8 @@ final class StaticLocationViewingCoordinator: Coordinator, Presentable { mapStyleURL: parameters.session.vc_homeserverConfiguration().tileServer.mapStyleURL, avatarData: parameters.avatarData, location: parameters.location, - coordinateType: parameters.coordinateType) + coordinateType: parameters.coordinateType + ) let view = StaticLocationView(viewModel: viewModel.context) .addDependency(AvatarService.instantiate(mediaManager: parameters.mediaManager)) staticLocationViewingViewModel = viewModel @@ -62,6 +62,7 @@ final class StaticLocationViewingCoordinator: Coordinator, Presentable { } // MARK: - Public + func start() { MXLog.debug("[StaticLocationSharingViewerCoordinator] did start.") staticLocationViewingViewModel.completion = { [weak self] result in @@ -77,13 +78,12 @@ final class StaticLocationViewingCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.staticLocationViewingHostingController + staticLocationViewingHostingController } func presentLocationActivityController(with coordinate: CLLocationCoordinate2D) { - let shareActivityController = shareLocationActivityControllerBuilder.build(with: coordinate) - self.staticLocationViewingHostingController.present(shareActivityController, animated: true) + staticLocationViewingHostingController.present(shareActivityController, animated: true) } } diff --git a/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/MockStaticLocationViewingScreenState.swift b/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/MockStaticLocationViewingScreenState.swift index 800057980..2ea0f0aec 100644 --- a/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/MockStaticLocationViewingScreenState.swift +++ b/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/MockStaticLocationViewingScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,9 +14,9 @@ // limitations under the License. // +import CoreLocation import Foundation import SwiftUI -import CoreLocation /// Using an enum for the screen allows you define the different state cases with /// the relevant associated data for each case. @@ -34,11 +34,11 @@ enum MockStaticLocationViewingScreenState: MockScreenState, CaseIterable { /// A list of screen state definitions static var allCases: [MockStaticLocationViewingScreenState] { - return [.showUserLocation, .showPinLocation] + [.showUserLocation, .showPinLocation] } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let location = CLLocationCoordinate2D(latitude: 51.4932641, longitude: -0.257096) let coordinateType: LocationSharingCoordinateType = self == .showUserLocation ? .user : .pin @@ -50,7 +50,6 @@ enum MockStaticLocationViewingScreenState: MockScreenState, CaseIterable { return ([viewModel], AnyView(StaticLocationView(viewModel: viewModel.context) - .addDependency(MockAvatarService.example)) - ) + .addDependency(MockAvatarService.example))) } } diff --git a/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/StaticLocationViewingModels.swift b/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/StaticLocationViewingModels.swift index f51c26c63..f25b16e48 100644 --- a/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/StaticLocationViewingModels.swift +++ b/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/StaticLocationViewingModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,9 +14,9 @@ // limitations under the License. // -import Foundation import Combine import CoreLocation +import Foundation // MARK: View model @@ -33,7 +33,6 @@ enum StaticLocationViewingViewModelResult { // MARK: View struct StaticLocationViewingViewState: BindableState { - /// Map style URL let mapStyleURL: URL @@ -43,7 +42,7 @@ struct StaticLocationViewingViewState: BindableState { /// Shared annotation to display existing location let sharedAnnotation: LocationAnnotation - var showLoadingIndicator: Bool = false + var showLoadingIndicator = false var shareButtonEnabled: Bool { !showLoadingIndicator diff --git a/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/StaticLocationViewingViewModel.swift b/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/StaticLocationViewingViewModel.swift index 8564596a1..1f63e248e 100644 --- a/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/StaticLocationViewingViewModel.swift +++ b/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/StaticLocationViewingViewModel.swift @@ -14,14 +14,13 @@ // limitations under the License. // -import SwiftUI import CoreLocation +import SwiftUI typealias StaticLocationViewingViewModelType = StateStoreViewModel + Never, + StaticLocationViewingViewAction> class StaticLocationViewingViewModel: StaticLocationViewingViewModelType, StaticLocationViewingViewModelProtocol { - // MARK: - Properties // MARK: Private @@ -79,7 +78,7 @@ class StaticLocationViewingViewModel: StaticLocationViewingViewModelType, Static switch error { case .invalidLocationAuthorization: - if let applicationSettingsURL = URL(string:UIApplication.openSettingsURLString) { + if let applicationSettingsURL = URL(string: UIApplication.openSettingsURLString) { UIApplication.shared.open(applicationSettingsURL) } else { self?.completion?(.close) diff --git a/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/StaticLocationViewingViewModelProtocol.swift b/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/StaticLocationViewingViewModelProtocol.swift index 7835e5c4e..e61ed6b3a 100644 --- a/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/StaticLocationViewingViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/StaticLocationViewingViewModelProtocol.swift @@ -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 StaticLocationViewingViewModelProtocol { - var completion: ((StaticLocationViewingViewModelResult) -> Void)? { get set } var context: StaticLocationViewingViewModelType.Context { get } } diff --git a/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/Test/UI/StaticLocationViewingUITests.swift b/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/Test/UI/StaticLocationViewingUITests.swift index d6f26f247..ae2cea9aa 100644 --- a/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/Test/UI/StaticLocationViewingUITests.swift +++ b/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/Test/UI/StaticLocationViewingUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class StaticLocationViewingUITests: MockScreenTestCase { // This test has issues running consistently on CI. Removed for now until the issue has been fixed. diff --git a/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/Test/Unit/StaticLocationViewingViewModelTests.swift b/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/Test/Unit/StaticLocationViewingViewModelTests.swift index 22ce395a7..f9aa24324 100644 --- a/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/Test/Unit/StaticLocationViewingViewModelTests.swift +++ b/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/Test/Unit/StaticLocationViewingViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,14 +14,13 @@ // limitations under the License. // -import XCTest import Combine import CoreLocation +import XCTest @testable import RiotSwiftUI class StaticLocationViewingViewModelTests: XCTestCase { - var cancellables = Set() func testInitialState() { @@ -39,7 +38,7 @@ class StaticLocationViewingViewModelTests: XCTestCase { func testCancellation() { let viewModel = buildViewModel() - let expectation = self.expectation(description: "Cancellation completion should be invoked") + let expectation = expectation(description: "Cancellation completion should be invoked") viewModel.completion = { result in switch result { @@ -58,7 +57,7 @@ class StaticLocationViewingViewModelTests: XCTestCase { func testShareExistingLocation() { let viewModel = buildViewModel() - let expectation = self.expectation(description: "Share completion should be invoked") + let expectation = expectation(description: "Share completion should be invoked") viewModel.completion = { result in switch result { diff --git a/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/View/StaticLocationView.swift b/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/View/StaticLocationView.swift index 7436aa5e8..3b12fa00c 100644 --- a/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/View/StaticLocationView.swift +++ b/RiotSwiftUI/Modules/LocationSharing/StaticLocationSharingViewer/View/StaticLocationView.swift @@ -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 StaticLocationView: View { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Onboarding/Avatar/Coordinator/OnboardingAvatarCoordinator.swift b/RiotSwiftUI/Modules/Onboarding/Avatar/Coordinator/OnboardingAvatarCoordinator.swift index 216a65ea4..e3f3de9cd 100644 --- a/RiotSwiftUI/Modules/Onboarding/Avatar/Coordinator/OnboardingAvatarCoordinator.swift +++ b/RiotSwiftUI/Modules/Onboarding/Avatar/Coordinator/OnboardingAvatarCoordinator.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import SwiftUI import CommonKit +import SwiftUI struct OnboardingAvatarCoordinatorParameters { let userSession: UserSession @@ -32,7 +32,6 @@ enum OnboardingAvatarCoordinatorResult { } final class OnboardingAvatarCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -84,7 +83,6 @@ final class OnboardingAvatarCoordinator: Coordinator, Presentable { indicatorPresenter = UserIndicatorTypePresenter(presentingViewController: onboardingAvatarHostingController) } - // MARK: - Public func start() { @@ -106,7 +104,7 @@ final class OnboardingAvatarCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.onboardingAvatarHostingController + onboardingAvatarHostingController } // MARK: - Private @@ -144,8 +142,8 @@ final class OnboardingAvatarCoordinator: Coordinator, Presentable { guard let avatarData = MXKTools.forceImageOrientationUp(image)?.jpegData(compressionQuality: 0.5) else { MXLog.error("[OnboardingAvatarCoordinator] Failed to create jpeg data.") - self.stopWaiting() - self.onboardingAvatarViewModel.processError(nil) + stopWaiting() + onboardingAvatarViewModel.processError(nil) return } diff --git a/RiotSwiftUI/Modules/Onboarding/Avatar/MockOnboardingAvatarScreenState.swift b/RiotSwiftUI/Modules/Onboarding/Avatar/MockOnboardingAvatarScreenState.swift index 7cf96984a..3c972b602 100644 --- a/RiotSwiftUI/Modules/Onboarding/Avatar/MockOnboardingAvatarScreenState.swift +++ b/RiotSwiftUI/Modules/Onboarding/Avatar/MockOnboardingAvatarScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -43,7 +43,7 @@ enum MockOnboardingAvatarScreenState: MockScreenState, CaseIterable { } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let avatarColorCount = DefaultThemeSwiftUI().colors.namesAndAvatars.count let viewModel: OnboardingAvatarViewModel switch self { diff --git a/RiotSwiftUI/Modules/Onboarding/Avatar/OnboardingAvatarModels.swift b/RiotSwiftUI/Modules/Onboarding/Avatar/OnboardingAvatarModels.swift index 7f0187ebb..036498577 100644 --- a/RiotSwiftUI/Modules/Onboarding/Avatar/OnboardingAvatarModels.swift +++ b/RiotSwiftUI/Modules/Onboarding/Avatar/OnboardingAvatarModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Onboarding/Avatar/OnboardingAvatarViewModel.swift b/RiotSwiftUI/Modules/Onboarding/Avatar/OnboardingAvatarViewModel.swift index 7d1c23f5c..47bcf70a5 100644 --- a/RiotSwiftUI/Modules/Onboarding/Avatar/OnboardingAvatarViewModel.swift +++ b/RiotSwiftUI/Modules/Onboarding/Avatar/OnboardingAvatarViewModel.swift @@ -14,15 +14,14 @@ // limitations under the License. // -import SwiftUI import Combine +import SwiftUI typealias OnboardingAvatarViewModelType = StateStoreViewModel + Never, + OnboardingAvatarViewAction> class OnboardingAvatarViewModel: OnboardingAvatarViewModelType, OnboardingAvatarViewModelProtocol { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Onboarding/Avatar/OnboardingAvatarViewModelProtocol.swift b/RiotSwiftUI/Modules/Onboarding/Avatar/OnboardingAvatarViewModelProtocol.swift index 0c3eb58c8..bda30b06e 100644 --- a/RiotSwiftUI/Modules/Onboarding/Avatar/OnboardingAvatarViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Onboarding/Avatar/OnboardingAvatarViewModelProtocol.swift @@ -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 protocol OnboardingAvatarViewModelProtocol { - var callback: ((OnboardingAvatarViewModelResult) -> Void)? { get set } var context: OnboardingAvatarViewModelType.Context { get } diff --git a/RiotSwiftUI/Modules/Onboarding/Avatar/Test/UI/OnboardingAvatarUITests.swift b/RiotSwiftUI/Modules/Onboarding/Avatar/Test/UI/OnboardingAvatarUITests.swift index dc71847b5..13318da78 100644 --- a/RiotSwiftUI/Modules/Onboarding/Avatar/Test/UI/OnboardingAvatarUITests.swift +++ b/RiotSwiftUI/Modules/Onboarding/Avatar/Test/UI/OnboardingAvatarUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class OnboardingAvatarUITests: MockScreenTestCase { let userId = "@example:matrix.org" diff --git a/RiotSwiftUI/Modules/Onboarding/Avatar/Test/Unit/OnboardingAvatarViewModelTests.swift b/RiotSwiftUI/Modules/Onboarding/Avatar/Test/Unit/OnboardingAvatarViewModelTests.swift index fd0f284d3..228ae6c01 100644 --- a/RiotSwiftUI/Modules/Onboarding/Avatar/Test/Unit/OnboardingAvatarViewModelTests.swift +++ b/RiotSwiftUI/Modules/Onboarding/Avatar/Test/Unit/OnboardingAvatarViewModelTests.swift @@ -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 diff --git a/RiotSwiftUI/Modules/Onboarding/Avatar/View/OnboardingAvatarScreen.swift b/RiotSwiftUI/Modules/Onboarding/Avatar/View/OnboardingAvatarScreen.swift index dcb1af1dd..f93f4cfff 100644 --- a/RiotSwiftUI/Modules/Onboarding/Avatar/View/OnboardingAvatarScreen.swift +++ b/RiotSwiftUI/Modules/Onboarding/Avatar/View/OnboardingAvatarScreen.swift @@ -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 SwiftUI import DesignKit +import SwiftUI struct OnboardingAvatarScreen: View { - // MARK: - Properties // MARK: Private @@ -53,7 +52,6 @@ struct OnboardingAvatarScreen: View { .accentColor(theme.colors.accent) } - /// The user's avatar along with a picker button var avatar: some View { Group { diff --git a/RiotSwiftUI/Modules/Onboarding/Celebration/Coordinator/OnboardingCelebrationCoordinator.swift b/RiotSwiftUI/Modules/Onboarding/Celebration/Coordinator/OnboardingCelebrationCoordinator.swift index 5cfcd8d95..9f0ea9273 100644 --- a/RiotSwiftUI/Modules/Onboarding/Celebration/Coordinator/OnboardingCelebrationCoordinator.swift +++ b/RiotSwiftUI/Modules/Onboarding/Celebration/Coordinator/OnboardingCelebrationCoordinator.swift @@ -21,7 +21,6 @@ struct OnboardingCelebrationCoordinatorParameters { } final class OnboardingCelebrationCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -49,6 +48,7 @@ final class OnboardingCelebrationCoordinator: Coordinator, Presentable { } // MARK: - Public + func start() { MXLog.debug("[OnboardingCelebrationCoordinator] did start.") onboardingCelebrationViewModel.completion = { [weak self] in @@ -59,6 +59,6 @@ final class OnboardingCelebrationCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.onboardingCelebrationHostingController + onboardingCelebrationHostingController } } diff --git a/RiotSwiftUI/Modules/Onboarding/Celebration/MockOnboardingCelebrationScreenState.swift b/RiotSwiftUI/Modules/Onboarding/Celebration/MockOnboardingCelebrationScreenState.swift index 630fbe6bc..d911f8249 100644 --- a/RiotSwiftUI/Modules/Onboarding/Celebration/MockOnboardingCelebrationScreenState.swift +++ b/RiotSwiftUI/Modules/Onboarding/Celebration/MockOnboardingCelebrationScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,7 +31,7 @@ enum MockOnboardingCelebrationScreenState: MockScreenState, CaseIterable { } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let viewModel = OnboardingCelebrationViewModel() // can simulate service and viewModel actions here if needs be. diff --git a/RiotSwiftUI/Modules/Onboarding/Celebration/OnboardingCelebrationModels.swift b/RiotSwiftUI/Modules/Onboarding/Celebration/OnboardingCelebrationModels.swift index 49549b9e1..5029fa7f0 100644 --- a/RiotSwiftUI/Modules/Onboarding/Celebration/OnboardingCelebrationModels.swift +++ b/RiotSwiftUI/Modules/Onboarding/Celebration/OnboardingCelebrationModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Onboarding/Celebration/OnboardingCelebrationViewModel.swift b/RiotSwiftUI/Modules/Onboarding/Celebration/OnboardingCelebrationViewModel.swift index 67bee880d..4bba32dea 100644 --- a/RiotSwiftUI/Modules/Onboarding/Celebration/OnboardingCelebrationViewModel.swift +++ b/RiotSwiftUI/Modules/Onboarding/Celebration/OnboardingCelebrationViewModel.swift @@ -17,11 +17,10 @@ import SwiftUI typealias OnboardingCelebrationViewModelType = StateStoreViewModel + Never, + OnboardingCelebrationViewAction> class OnboardingCelebrationViewModel: OnboardingCelebrationViewModelType, OnboardingCelebrationViewModelProtocol { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Onboarding/Celebration/OnboardingCelebrationViewModelProtocol.swift b/RiotSwiftUI/Modules/Onboarding/Celebration/OnboardingCelebrationViewModelProtocol.swift index 7c16672b4..c3c5550f2 100644 --- a/RiotSwiftUI/Modules/Onboarding/Celebration/OnboardingCelebrationViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Onboarding/Celebration/OnboardingCelebrationViewModelProtocol.swift @@ -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 OnboardingCelebrationViewModelProtocol { - var completion: (() -> Void)? { get set } var context: OnboardingCelebrationViewModelType.Context { get } } diff --git a/RiotSwiftUI/Modules/Onboarding/Celebration/Test/UI/OnboardingCelebrationUITests.swift b/RiotSwiftUI/Modules/Onboarding/Celebration/Test/UI/OnboardingCelebrationUITests.swift index 12d0f210a..587dfb576 100644 --- a/RiotSwiftUI/Modules/Onboarding/Celebration/Test/UI/OnboardingCelebrationUITests.swift +++ b/RiotSwiftUI/Modules/Onboarding/Celebration/Test/UI/OnboardingCelebrationUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class OnboardingCelebrationUITests: MockScreenTestCase { // Nothing to test as the view is completely static diff --git a/RiotSwiftUI/Modules/Onboarding/Celebration/Test/Unit/OnboardingCelebrationViewModelTests.swift b/RiotSwiftUI/Modules/Onboarding/Celebration/Test/Unit/OnboardingCelebrationViewModelTests.swift index 3874d1dd2..c512e319b 100644 --- a/RiotSwiftUI/Modules/Onboarding/Celebration/Test/Unit/OnboardingCelebrationViewModelTests.swift +++ b/RiotSwiftUI/Modules/Onboarding/Celebration/Test/Unit/OnboardingCelebrationViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Onboarding/Celebration/View/OnboardingCelebrationScreen.swift b/RiotSwiftUI/Modules/Onboarding/Celebration/View/OnboardingCelebrationScreen.swift index 1d6638114..2ebe7aa28 100644 --- a/RiotSwiftUI/Modules/Onboarding/Celebration/View/OnboardingCelebrationScreen.swift +++ b/RiotSwiftUI/Modules/Onboarding/Celebration/View/OnboardingCelebrationScreen.swift @@ -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 SwiftUI import SceneKit +import SwiftUI struct OnboardingCelebrationScreen: View { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Onboarding/Common/OnboardingBreakerScreenBackground.swift b/RiotSwiftUI/Modules/Onboarding/Common/OnboardingBreakerScreenBackground.swift index 39fd14915..d690ade43 100644 --- a/RiotSwiftUI/Modules/Onboarding/Common/OnboardingBreakerScreenBackground.swift +++ b/RiotSwiftUI/Modules/Onboarding/Common/OnboardingBreakerScreenBackground.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ import SwiftUI struct OnboardingBreakerScreenBackground: View { - @Environment(\.theme) private var theme /// Flag indicating whether the gradient enabled on light theme @@ -43,21 +42,20 @@ struct OnboardingBreakerScreenBackground: View { ZStack(alignment: .top) { theme.colors.background - if isGradientEnabled && !theme.isDark { + if isGradientEnabled, !theme.isDark { LinearGradient(gradient: gradient, startPoint: .leading, endPoint: .trailing) - .opacity(0.3) - .mask(LinearGradient(colors: [.white, .clear], - startPoint: .top, - endPoint: .bottom)) - .frame(height: geometry.size.height * 0.65) + .opacity(0.3) + .mask(LinearGradient(colors: [.white, .clear], + startPoint: .top, + endPoint: .bottom)) + .frame(height: geometry.size.height * 0.65) } } } .ignoresSafeArea() } - } // MARK: - Previews diff --git a/RiotSwiftUI/Modules/Onboarding/Common/OnboardingButtonStyle.swift b/RiotSwiftUI/Modules/Onboarding/Common/OnboardingButtonStyle.swift index f0ba669dd..f4ee8a8ba 100644 --- a/RiotSwiftUI/Modules/Onboarding/Common/OnboardingButtonStyle.swift +++ b/RiotSwiftUI/Modules/Onboarding/Common/OnboardingButtonStyle.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Onboarding/Common/OnboardingIcon.swift b/RiotSwiftUI/Modules/Onboarding/Common/OnboardingIcon.swift index 598f07446..4993ce002 100644 --- a/RiotSwiftUI/Modules/Onboarding/Common/OnboardingIcon.swift +++ b/RiotSwiftUI/Modules/Onboarding/Common/OnboardingIcon.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ import SwiftUI struct OnboardingIconImage: View { - @Environment(\.theme) private var theme let image: ImageAsset diff --git a/RiotSwiftUI/Modules/Onboarding/Common/OnboardingMetrics.swift b/RiotSwiftUI/Modules/Onboarding/Common/OnboardingMetrics.swift index 6eb697ed3..654d0e0f0 100644 --- a/RiotSwiftUI/Modules/Onboarding/Common/OnboardingMetrics.swift +++ b/RiotSwiftUI/Modules/Onboarding/Common/OnboardingMetrics.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Onboarding/Common/OnboardingTintedFullStopText.swift b/RiotSwiftUI/Modules/Onboarding/Common/OnboardingTintedFullStopText.swift index 5c6aa2ab3..d79484065 100644 --- a/RiotSwiftUI/Modules/Onboarding/Common/OnboardingTintedFullStopText.swift +++ b/RiotSwiftUI/Modules/Onboarding/Common/OnboardingTintedFullStopText.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,10 +19,10 @@ import SwiftUI /// A view that displays text, highlighting the first occurrence of /// the character `.` in the theme's accent color. struct OnboardingTintedFullStopText: View { - // MARK: - Properties // MARK: Private + @Environment(\.theme) private var theme private struct StringComponent { diff --git a/RiotSwiftUI/Modules/Onboarding/Congratulations/Coordinator/OnboardingCongratulationsCoordinator.swift b/RiotSwiftUI/Modules/Onboarding/Congratulations/Coordinator/OnboardingCongratulationsCoordinator.swift index 59cec36c4..57cd09d5c 100644 --- a/RiotSwiftUI/Modules/Onboarding/Congratulations/Coordinator/OnboardingCongratulationsCoordinator.swift +++ b/RiotSwiftUI/Modules/Onboarding/Congratulations/Coordinator/OnboardingCongratulationsCoordinator.swift @@ -32,7 +32,6 @@ enum OnboardingCongratulationsCoordinatorResult { } final class OnboardingCongratulationsCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -62,6 +61,7 @@ final class OnboardingCongratulationsCoordinator: Coordinator, Presentable { } // MARK: - Public + func start() { MXLog.debug("[OnboardingCongratulationsCoordinator] did start.") onboardingCongratulationsViewModel.completion = { [weak self] result in @@ -78,6 +78,6 @@ final class OnboardingCongratulationsCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.onboardingCongratulationsHostingController + onboardingCongratulationsHostingController } } diff --git a/RiotSwiftUI/Modules/Onboarding/Congratulations/MockOnboardingCongratulationsScreenState.swift b/RiotSwiftUI/Modules/Onboarding/Congratulations/MockOnboardingCongratulationsScreenState.swift index afe5fb92e..98e45e2c3 100644 --- a/RiotSwiftUI/Modules/Onboarding/Congratulations/MockOnboardingCongratulationsScreenState.swift +++ b/RiotSwiftUI/Modules/Onboarding/Congratulations/MockOnboardingCongratulationsScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,7 +32,7 @@ enum MockOnboardingCongratulationsScreenState: MockScreenState, CaseIterable { } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let viewModel: OnboardingCongratulationsViewModel switch self { diff --git a/RiotSwiftUI/Modules/Onboarding/Congratulations/OnboardingCongratulationsModels.swift b/RiotSwiftUI/Modules/Onboarding/Congratulations/OnboardingCongratulationsModels.swift index bfc53c682..afe3f94f9 100644 --- a/RiotSwiftUI/Modules/Onboarding/Congratulations/OnboardingCongratulationsModels.swift +++ b/RiotSwiftUI/Modules/Onboarding/Congratulations/OnboardingCongratulationsModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Onboarding/Congratulations/OnboardingCongratulationsViewModel.swift b/RiotSwiftUI/Modules/Onboarding/Congratulations/OnboardingCongratulationsViewModel.swift index 5bb90c0d7..f61c3f4b0 100644 --- a/RiotSwiftUI/Modules/Onboarding/Congratulations/OnboardingCongratulationsViewModel.swift +++ b/RiotSwiftUI/Modules/Onboarding/Congratulations/OnboardingCongratulationsViewModel.swift @@ -17,11 +17,10 @@ import SwiftUI typealias OnboardingCongratulationsViewModelType = StateStoreViewModel + Never, + OnboardingCongratulationsViewAction> class OnboardingCongratulationsViewModel: OnboardingCongratulationsViewModelType, OnboardingCongratulationsViewModelProtocol { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Onboarding/Congratulations/OnboardingCongratulationsViewModelProtocol.swift b/RiotSwiftUI/Modules/Onboarding/Congratulations/OnboardingCongratulationsViewModelProtocol.swift index 531e5614a..15e985922 100644 --- a/RiotSwiftUI/Modules/Onboarding/Congratulations/OnboardingCongratulationsViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Onboarding/Congratulations/OnboardingCongratulationsViewModelProtocol.swift @@ -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 OnboardingCongratulationsViewModelProtocol { - var completion: ((OnboardingCongratulationsViewModelResult) -> Void)? { get set } var context: OnboardingCongratulationsViewModelType.Context { get } } diff --git a/RiotSwiftUI/Modules/Onboarding/Congratulations/Test/UI/OnboardingCongratulationsUITests.swift b/RiotSwiftUI/Modules/Onboarding/Congratulations/Test/UI/OnboardingCongratulationsUITests.swift index 9b4c8f9f6..ca32b079b 100644 --- a/RiotSwiftUI/Modules/Onboarding/Congratulations/Test/UI/OnboardingCongratulationsUITests.swift +++ b/RiotSwiftUI/Modules/Onboarding/Congratulations/Test/UI/OnboardingCongratulationsUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class OnboardingCongratulationsUITests: MockScreenTestCase { func testButtons() { diff --git a/RiotSwiftUI/Modules/Onboarding/Congratulations/Test/Unit/OnboardingCongratulationsViewModelTests.swift b/RiotSwiftUI/Modules/Onboarding/Congratulations/Test/Unit/OnboardingCongratulationsViewModelTests.swift index 8d46382e8..d46d1be32 100644 --- a/RiotSwiftUI/Modules/Onboarding/Congratulations/Test/Unit/OnboardingCongratulationsViewModelTests.swift +++ b/RiotSwiftUI/Modules/Onboarding/Congratulations/Test/Unit/OnboardingCongratulationsViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Onboarding/Congratulations/View/OnboardingCongratulationsScreen.swift b/RiotSwiftUI/Modules/Onboarding/Congratulations/View/OnboardingCongratulationsScreen.swift index d0ca409b0..a6f165920 100644 --- a/RiotSwiftUI/Modules/Onboarding/Congratulations/View/OnboardingCongratulationsScreen.swift +++ b/RiotSwiftUI/Modules/Onboarding/Congratulations/View/OnboardingCongratulationsScreen.swift @@ -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 OnboardingCongratulationsScreen: View { - // MARK: - Properties // MARK: Private @@ -62,7 +61,7 @@ struct OnboardingCongratulationsScreen: View { .overlay(effects.ignoresSafeArea()) .background(theme.colors.accent.ignoresSafeArea()) .navigationBarHidden(true) - .preferredColorScheme(.dark) // make the status bar white + .preferredColorScheme(.dark) // make the status bar white .accentColor(.white) } diff --git a/RiotSwiftUI/Modules/Onboarding/DisplayName/Coordinator/OnboardingDisplayNameCoordinator.swift b/RiotSwiftUI/Modules/Onboarding/DisplayName/Coordinator/OnboardingDisplayNameCoordinator.swift index feeab4018..78837e8a2 100644 --- a/RiotSwiftUI/Modules/Onboarding/DisplayName/Coordinator/OnboardingDisplayNameCoordinator.swift +++ b/RiotSwiftUI/Modules/Onboarding/DisplayName/Coordinator/OnboardingDisplayNameCoordinator.swift @@ -14,15 +14,14 @@ // limitations under the License. // -import SwiftUI import CommonKit +import SwiftUI struct OnboardingDisplayNameCoordinatorParameters { let userSession: UserSession } final class OnboardingDisplayNameCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -58,6 +57,7 @@ final class OnboardingDisplayNameCoordinator: Coordinator, Presentable { } // MARK: - Public + func start() { MXLog.debug("[OnboardingDisplayNameCoordinator] did start.") onboardingDisplayNameViewModel.completion = { [weak self] result in @@ -74,7 +74,7 @@ final class OnboardingDisplayNameCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.onboardingDisplayNameHostingController + onboardingDisplayNameHostingController } // MARK: - Private diff --git a/RiotSwiftUI/Modules/Onboarding/DisplayName/MockOnboardingDisplayNameScreenState.swift b/RiotSwiftUI/Modules/Onboarding/DisplayName/MockOnboardingDisplayNameScreenState.swift index 0e50d478c..b9a027d31 100644 --- a/RiotSwiftUI/Modules/Onboarding/DisplayName/MockOnboardingDisplayNameScreenState.swift +++ b/RiotSwiftUI/Modules/Onboarding/DisplayName/MockOnboardingDisplayNameScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -44,7 +44,7 @@ enum MockOnboardingDisplayNameScreenState: MockScreenState, CaseIterable { } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let viewModel: OnboardingDisplayNameViewModel switch self { case .emptyTextField: diff --git a/RiotSwiftUI/Modules/Onboarding/DisplayName/OnboardingDisplayNameModels.swift b/RiotSwiftUI/Modules/Onboarding/DisplayName/OnboardingDisplayNameModels.swift index 22857f69c..bae11189e 100644 --- a/RiotSwiftUI/Modules/Onboarding/DisplayName/OnboardingDisplayNameModels.swift +++ b/RiotSwiftUI/Modules/Onboarding/DisplayName/OnboardingDisplayNameModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Onboarding/DisplayName/OnboardingDisplayNameViewModel.swift b/RiotSwiftUI/Modules/Onboarding/DisplayName/OnboardingDisplayNameViewModel.swift index 547a71b22..cfc7998f2 100644 --- a/RiotSwiftUI/Modules/Onboarding/DisplayName/OnboardingDisplayNameViewModel.swift +++ b/RiotSwiftUI/Modules/Onboarding/DisplayName/OnboardingDisplayNameViewModel.swift @@ -14,15 +14,14 @@ // limitations under the License. // -import SwiftUI import Combine +import SwiftUI typealias OnboardingDisplayNameViewModelType = StateStoreViewModel + Never, + OnboardingDisplayNameViewAction> class OnboardingDisplayNameViewModel: OnboardingDisplayNameViewModelType, OnboardingDisplayNameViewModelProtocol { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Onboarding/DisplayName/OnboardingDisplayNameViewModelProtocol.swift b/RiotSwiftUI/Modules/Onboarding/DisplayName/OnboardingDisplayNameViewModelProtocol.swift index 7380bee9a..ae768a816 100644 --- a/RiotSwiftUI/Modules/Onboarding/DisplayName/OnboardingDisplayNameViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Onboarding/DisplayName/OnboardingDisplayNameViewModelProtocol.swift @@ -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 OnboardingDisplayNameViewModelProtocol { - var completion: ((OnboardingDisplayNameViewModelResult) -> Void)? { get set } var context: OnboardingDisplayNameViewModelType.Context { get } diff --git a/RiotSwiftUI/Modules/Onboarding/DisplayName/Test/UI/OnboardingDisplayNameUITests.swift b/RiotSwiftUI/Modules/Onboarding/DisplayName/Test/UI/OnboardingDisplayNameUITests.swift index 6c27e09de..9c006dc6b 100644 --- a/RiotSwiftUI/Modules/Onboarding/DisplayName/Test/UI/OnboardingDisplayNameUITests.swift +++ b/RiotSwiftUI/Modules/Onboarding/DisplayName/Test/UI/OnboardingDisplayNameUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class OnboardingDisplayNameUITests: MockScreenTestCase { func testEmptyTextField() { @@ -55,8 +55,8 @@ class OnboardingDisplayNameUITests: MockScreenTestCase { func testLongDisplayName() { let displayName = """ - Bacon ipsum dolor amet filet mignon chicken kevin andouille. Doner shoulder beef, brisket bresaola turkey jowl venison. Ham hock cow turducken, chislic venison doner short loin strip steak tri-tip jowl. Sirloin pork belly hamburger ribeye. Tail capicola alcatra short ribs turkey doner. - """ + Bacon ipsum dolor amet filet mignon chicken kevin andouille. Doner shoulder beef, brisket bresaola turkey jowl venison. Ham hock cow turducken, chislic venison doner short loin strip steak tri-tip jowl. Sirloin pork belly hamburger ribeye. Tail capicola alcatra short ribs turkey doner. + """ app.goToScreenWithIdentifier(MockOnboardingDisplayNameScreenState.longDisplayName(displayName: displayName).title) let textField = app.textFields.element diff --git a/RiotSwiftUI/Modules/Onboarding/DisplayName/Test/Unit/OnboardingDisplayNameViewModelTests.swift b/RiotSwiftUI/Modules/Onboarding/DisplayName/Test/Unit/OnboardingDisplayNameViewModelTests.swift index c9b72f045..2dbc015e3 100644 --- a/RiotSwiftUI/Modules/Onboarding/DisplayName/Test/Unit/OnboardingDisplayNameViewModelTests.swift +++ b/RiotSwiftUI/Modules/Onboarding/DisplayName/Test/Unit/OnboardingDisplayNameViewModelTests.swift @@ -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 diff --git a/RiotSwiftUI/Modules/Onboarding/DisplayName/View/OnboardingDisplayNameScreen.swift b/RiotSwiftUI/Modules/Onboarding/DisplayName/View/OnboardingDisplayNameScreen.swift index 005a33f2c..09fc1ac10 100644 --- a/RiotSwiftUI/Modules/Onboarding/DisplayName/View/OnboardingDisplayNameScreen.swift +++ b/RiotSwiftUI/Modules/Onboarding/DisplayName/View/OnboardingDisplayNameScreen.swift @@ -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 OnboardingDisplayNameScreen: View { - // MARK: - Properties // MARK: Private @@ -64,7 +63,6 @@ struct OnboardingDisplayNameScreen: View { /// The icon, title and message views. var header: some View { VStack(spacing: 8) { - OnboardingIconImage(image: Asset.Images.onboardingCongratulationsIcon) .padding(.bottom, 8) diff --git a/RiotSwiftUI/Modules/Onboarding/SplashScreen/Coordinator/OnboardingSplashScreenCoordinator.swift b/RiotSwiftUI/Modules/Onboarding/SplashScreen/Coordinator/OnboardingSplashScreenCoordinator.swift index 534bb4e64..27c4b3dbc 100644 --- a/RiotSwiftUI/Modules/Onboarding/SplashScreen/Coordinator/OnboardingSplashScreenCoordinator.swift +++ b/RiotSwiftUI/Modules/Onboarding/SplashScreen/Coordinator/OnboardingSplashScreenCoordinator.swift @@ -14,15 +14,14 @@ // limitations under the License. // -import SwiftUI import CommonKit +import SwiftUI protocol OnboardingSplashScreenCoordinatorProtocol: Coordinator, Presentable { var completion: ((OnboardingSplashScreenViewModelResult) -> Void)? { get set } } final class OnboardingSplashScreenCoordinator: OnboardingSplashScreenCoordinatorProtocol { - // MARK: - Properties // MARK: Private @@ -52,6 +51,7 @@ final class OnboardingSplashScreenCoordinator: OnboardingSplashScreenCoordinator } // MARK: - Public + func start() { MXLog.debug("[OnboardingSplashScreenCoordinator] did start.") onboardingSplashScreenViewModel.completion = { [weak self] result in @@ -68,7 +68,7 @@ final class OnboardingSplashScreenCoordinator: OnboardingSplashScreenCoordinator } func toPresentable() -> UIViewController { - return onboardingSplashScreenHostingController + onboardingSplashScreenHostingController } /// Stops any ongoing activities in the coordinator. diff --git a/RiotSwiftUI/Modules/Onboarding/SplashScreen/MockOnboardingSplashScreenScreenState.swift b/RiotSwiftUI/Modules/Onboarding/SplashScreen/MockOnboardingSplashScreenScreenState.swift index 511e7cb6e..6e823719a 100644 --- a/RiotSwiftUI/Modules/Onboarding/SplashScreen/MockOnboardingSplashScreenScreenState.swift +++ b/RiotSwiftUI/Modules/Onboarding/SplashScreen/MockOnboardingSplashScreenScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,7 +36,7 @@ enum MockOnboardingSplashScreenScreenState: MockScreenState, CaseIterable { } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let viewModel = OnboardingSplashScreenViewModel() // can simulate service and viewModel actions here if needs be. diff --git a/RiotSwiftUI/Modules/Onboarding/SplashScreen/OnboardingSplashScreenModels.swift b/RiotSwiftUI/Modules/Onboarding/SplashScreen/OnboardingSplashScreenModels.swift index 6bd22223f..3b81de78e 100644 --- a/RiotSwiftUI/Modules/Onboarding/SplashScreen/OnboardingSplashScreenModels.swift +++ b/RiotSwiftUI/Modules/Onboarding/SplashScreen/OnboardingSplashScreenModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,7 +36,6 @@ enum OnboardingSplashScreenViewModelResult { // MARK: View struct OnboardingSplashScreenViewState: BindableState, CustomDebugStringConvertible { - /// The colours of the background gradient shown behind the 4 pages. private let gradientColors = [ Color(red: 0.95, green: 0.98, blue: 0.96), @@ -67,7 +66,7 @@ struct OnboardingSplashScreenViewState: BindableState, CustomDebugStringConverti let locale = Locale.current let page4Title = locale.identifier.hasPrefix("en") ? "Cut the slack from teams." : VectorL10n.onboardingSplashPage4TitleNoPun - self.content = [ + content = [ OnboardingSplashScreenPageContent(title: VectorL10n.onboardingSplashPage1Title, message: VectorL10n.onboardingSplashPage1Message, image: Asset.Images.onboardingSplashScreenPage1, @@ -83,9 +82,9 @@ struct OnboardingSplashScreenViewState: BindableState, CustomDebugStringConverti OnboardingSplashScreenPageContent(title: page4Title, message: VectorL10n.onboardingSplashPage4Message, image: Asset.Images.onboardingSplashScreenPage4, - darkImage: Asset.Images.onboardingSplashScreenPage4Dark), + darkImage: Asset.Images.onboardingSplashScreenPage4Dark) ] - self.bindings = OnboardingSplashScreenBindings() + bindings = OnboardingSplashScreenBindings() } } diff --git a/RiotSwiftUI/Modules/Onboarding/SplashScreen/OnboardingSplashScreenViewModel.swift b/RiotSwiftUI/Modules/Onboarding/SplashScreen/OnboardingSplashScreenViewModel.swift index 222f70f60..6d1c936ea 100644 --- a/RiotSwiftUI/Modules/Onboarding/SplashScreen/OnboardingSplashScreenViewModel.swift +++ b/RiotSwiftUI/Modules/Onboarding/SplashScreen/OnboardingSplashScreenViewModel.swift @@ -14,12 +14,12 @@ // limitations under the License. // -import SwiftUI import Combine +import SwiftUI typealias OnboardingSplashScreenViewModelType = StateStoreViewModel + Never, + OnboardingSplashScreenViewAction> protocol OnboardingSplashScreenViewModelProtocol { var completion: ((OnboardingSplashScreenViewModelResult) -> Void)? { get set } @@ -27,7 +27,6 @@ protocol OnboardingSplashScreenViewModelProtocol { } class OnboardingSplashScreenViewModel: OnboardingSplashScreenViewModelType, OnboardingSplashScreenViewModelProtocol { - // MARK: - Properties // MARK: Private @@ -55,7 +54,7 @@ class OnboardingSplashScreenViewModel: OnboardingSplashScreenViewModelType, Onbo state.bindings.pageIndex = (state.bindings.pageIndex + 1) % state.content.count case .previousPage: // Prevent the hidden page at index -1 from being shown. - state.bindings.pageIndex = max(0, (state.bindings.pageIndex - 1)) + state.bindings.pageIndex = max(0, state.bindings.pageIndex - 1) case .hiddenPage: // Hidden page for a nicer animation when looping back to the start. state.bindings.pageIndex = -1 diff --git a/RiotSwiftUI/Modules/Onboarding/SplashScreen/Test/Unit/OnboardingSplashScreenViewModelTests.swift b/RiotSwiftUI/Modules/Onboarding/SplashScreen/Test/Unit/OnboardingSplashScreenViewModelTests.swift index 4b47e0501..55b19703b 100644 --- a/RiotSwiftUI/Modules/Onboarding/SplashScreen/Test/Unit/OnboardingSplashScreenViewModelTests.swift +++ b/RiotSwiftUI/Modules/Onboarding/SplashScreen/Test/Unit/OnboardingSplashScreenViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,11 +14,9 @@ // limitations under the License. // -import XCTest import Combine +import XCTest @testable import RiotSwiftUI -class OnboardingSplashScreenViewModelTests: XCTestCase { - -} +class OnboardingSplashScreenViewModelTests: XCTestCase { } diff --git a/RiotSwiftUI/Modules/Onboarding/SplashScreen/View/OnboardingSplashScreen.swift b/RiotSwiftUI/Modules/Onboarding/SplashScreen/View/OnboardingSplashScreen.swift index 6afe46726..b34239882 100644 --- a/RiotSwiftUI/Modules/Onboarding/SplashScreen/View/OnboardingSplashScreen.swift +++ b/RiotSwiftUI/Modules/Onboarding/SplashScreen/View/OnboardingSplashScreen.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import SwiftUI /// The splash screen shown at the beginning of the onboarding flow. struct OnboardingSplashScreen: View { - // MARK: - Properties // MARK: Private @@ -46,7 +45,6 @@ struct OnboardingSplashScreen: View { // The main content of the carousel HStack(alignment: .top, spacing: 0) { - // Add a hidden page at the start of the carousel duplicating the content of the last page OnboardingSplashScreenPage(content: viewModel.viewState.content[pageCount - 1]) .frame(width: geometry.size.width) @@ -55,7 +53,6 @@ struct OnboardingSplashScreen: View { OnboardingSplashScreenPage(content: viewModel.viewState.content[index]) .frame(width: geometry.size.width) } - } .offset(x: pageOffset(in: geometry)) @@ -63,8 +60,8 @@ struct OnboardingSplashScreen: View { OnboardingSplashScreenPageIndicator(pageCount: pageCount, pageIndex: viewModel.pageIndex) - .frame(width: geometry.size.width) - .padding(.bottom) + .frame(width: geometry.size.width) + .padding(.bottom) Spacer() @@ -130,7 +127,7 @@ struct OnboardingSplashScreen: View { private func startTimer() { guard pageTimer == nil else { return } - pageTimer = Timer.scheduledTimer(withTimeInterval: 5, repeats: true) { timer in + pageTimer = Timer.scheduledTimer(withTimeInterval: 5, repeats: true) { _ in if viewModel.pageIndex == pageCount - 1 { viewModel.send(viewAction: .hiddenPage) @@ -164,7 +161,7 @@ struct OnboardingSplashScreen: View { /// - Parameter width: The gesture's translation width. /// - Returns: `true` if there is another page to drag to. private func shouldSwipeForTranslation(_ width: CGFloat) -> Bool { - if viewModel.pageIndex == 0 { + if viewModel.pageIndex == 0 { return isLeftToRight ? width < 0 : width > 0 } else if viewModel.pageIndex == pageCount - 1 { return isLeftToRight ? width > 0 : width < 0 diff --git a/RiotSwiftUI/Modules/Onboarding/SplashScreen/View/OnboardingSplashScreenPage.swift b/RiotSwiftUI/Modules/Onboarding/SplashScreen/View/OnboardingSplashScreenPage.swift index e8e66d773..4047580d9 100644 --- a/RiotSwiftUI/Modules/Onboarding/SplashScreen/View/OnboardingSplashScreenPage.swift +++ b/RiotSwiftUI/Modules/Onboarding/SplashScreen/View/OnboardingSplashScreenPage.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,13 +17,14 @@ import SwiftUI struct OnboardingSplashScreenPage: View { - // MARK: - Properties // MARK: Private + @Environment(\.theme) private var theme // MARK: Public + /// The content that this page should display. let content: OnboardingSplashScreenPageContent @@ -35,8 +36,8 @@ struct OnboardingSplashScreenPage: View { .resizable() .scaledToFit() .frame(maxWidth: 310) // This value is problematic. 300 results in dropped frames - // on iPhone 12/13 Mini. 305 the same on iPhone 12/13. As of - // iOS 15, 310 seems fine on all supported screen widths 🤞. + // on iPhone 12/13 Mini. 305 the same on iPhone 12/13. As of + // iOS 15, 310 seems fine on all supported screen widths 🤞. .padding(20) .accessibilityHidden(true) @@ -60,7 +61,7 @@ struct OnboardingSplashScreenPage: View { struct OnboardingSplashScreenPage_Previews: PreviewProvider { static let content = OnboardingSplashScreenViewState().content static var previews: some View { - ForEach(0.. UIViewController { - return self.onboardingUseCaseHostingController + onboardingUseCaseHostingController } /// Stops any ongoing activities in the coordinator. diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/MockOnboardingUseCaseScreenState.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/MockOnboardingUseCaseScreenState.swift index 4eb90c305..ed580b834 100644 --- a/RiotSwiftUI/Modules/Onboarding/UseCase/MockOnboardingUseCaseScreenState.swift +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/MockOnboardingUseCaseScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,7 +37,7 @@ enum MockOnboardingUseCaseSelectionScreenState: MockScreenState, CaseIterable { } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let viewModel = OnboardingUseCaseViewModel() // can simulate service and viewModel actions here if needs be. diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseModels.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseModels.swift index a7160ee67..8ee4f408b 100644 --- a/RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseModels.swift +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseViewModel.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseViewModel.swift index 4d0cc3135..b96c35ca2 100644 --- a/RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseViewModel.swift +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseViewModel.swift @@ -17,11 +17,10 @@ import SwiftUI typealias OnboardingUseCaseViewModelType = StateStoreViewModel + OnboardingUseCaseStateAction, + OnboardingUseCaseViewAction> class OnboardingUseCaseViewModel: OnboardingUseCaseViewModelType, OnboardingUseCaseViewModelProtocol { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseViewModelProtocol.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseViewModelProtocol.swift index 44d56cfba..f9a89e4eb 100644 --- a/RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseViewModelProtocol.swift @@ -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 OnboardingUseCaseViewModelProtocol { - var completion: ((OnboardingUseCaseViewModelResult) -> Void)? { get set } var context: OnboardingUseCaseViewModelType.Context { get } } diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/Test/UI/OnboardingUseCaseUITests.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/Test/UI/OnboardingUseCaseUITests.swift index fbb0a9a64..375c93865 100644 --- a/RiotSwiftUI/Modules/Onboarding/UseCase/Test/UI/OnboardingUseCaseUITests.swift +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/Test/UI/OnboardingUseCaseUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class OnboardingUseCaseUITests: MockScreenTestCase { // The view has no parameters or changing state to test. diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/Test/Unit/OnboardingUseCaseViewModelTests.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/Test/Unit/OnboardingUseCaseViewModelTests.swift index 9f5fa2b8f..eed714cf5 100644 --- a/RiotSwiftUI/Modules/Onboarding/UseCase/Test/Unit/OnboardingUseCaseViewModelTests.swift +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/Test/Unit/OnboardingUseCaseViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCaseButton.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCaseButton.swift index 7916fe280..bbbd9999c 100644 --- a/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCaseButton.swift +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCaseButton.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import SwiftUI /// A button used for the Use Case selection. struct OnboardingUseCaseButton: View { - // MARK: Private @Environment(\.theme) private var theme diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCaseSelectionScreen.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCaseSelectionScreen.swift index f0fbbfa61..c4761aa47 100644 --- a/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCaseSelectionScreen.swift +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCaseSelectionScreen.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import SwiftUI /// The screen shown to a new user to select their use case for the app. struct OnboardingUseCaseSelectionScreen: View { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Room/AllChatsOnboarding/AllChatsOnboardingModels.swift b/RiotSwiftUI/Modules/Room/AllChatsOnboarding/AllChatsOnboardingModels.swift index c33638ddc..76beb1205 100644 --- a/RiotSwiftUI/Modules/Room/AllChatsOnboarding/AllChatsOnboardingModels.swift +++ b/RiotSwiftUI/Modules/Room/AllChatsOnboarding/AllChatsOnboardingModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Room/AllChatsOnboarding/AllChatsOnboardingViewModel.swift b/RiotSwiftUI/Modules/Room/AllChatsOnboarding/AllChatsOnboardingViewModel.swift index 75712d550..1e8111a7a 100644 --- a/RiotSwiftUI/Modules/Room/AllChatsOnboarding/AllChatsOnboardingViewModel.swift +++ b/RiotSwiftUI/Modules/Room/AllChatsOnboarding/AllChatsOnboardingViewModel.swift @@ -14,15 +14,14 @@ // limitations under the License. // -import SwiftUI import Combine +import SwiftUI typealias AllChatsOnboardingViewModelType = StateStoreViewModel + Never, + AllChatsOnboardingViewAction> class AllChatsOnboardingViewModel: AllChatsOnboardingViewModelType, AllChatsOnboardingViewModelProtocol { - // MARK: - Properties // MARK: Private @@ -34,7 +33,7 @@ class AllChatsOnboardingViewModel: AllChatsOnboardingViewModelType, AllChatsOnbo // MARK: - Setup static func makeAllChatsOnboardingViewModel() -> AllChatsOnboardingViewModelProtocol { - return AllChatsOnboardingViewModel() + AllChatsOnboardingViewModel() } private init() { @@ -42,7 +41,7 @@ class AllChatsOnboardingViewModel: AllChatsOnboardingViewModelType, AllChatsOnbo } private static func defaultState() -> AllChatsOnboardingViewState { - return AllChatsOnboardingViewState(pages: [ + AllChatsOnboardingViewState(pages: [ AllChatsOnboardingPageData(image: Asset.Images.allChatsOnboarding1.image, title: VectorL10n.allChatsOnboardingPageTitle1, message: VectorL10n.allChatsOnboardingPageMessage1), diff --git a/RiotSwiftUI/Modules/Room/AllChatsOnboarding/AllChatsOnboardingViewModelProtocol.swift b/RiotSwiftUI/Modules/Room/AllChatsOnboarding/AllChatsOnboardingViewModelProtocol.swift index a0cc2137d..dd963c407 100644 --- a/RiotSwiftUI/Modules/Room/AllChatsOnboarding/AllChatsOnboardingViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Room/AllChatsOnboarding/AllChatsOnboardingViewModelProtocol.swift @@ -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 AllChatsOnboardingViewModelProtocol { - var completion: ((AllChatsOnboardingViewModelResult) -> Void)? { get set } static func makeAllChatsOnboardingViewModel() -> AllChatsOnboardingViewModelProtocol var context: AllChatsOnboardingViewModelType.Context { get } diff --git a/RiotSwiftUI/Modules/Room/AllChatsOnboarding/Coordinator/AllChatsOnboardingCoordinator.swift b/RiotSwiftUI/Modules/Room/AllChatsOnboarding/Coordinator/AllChatsOnboardingCoordinator.swift index de793e30e..df189c144 100644 --- a/RiotSwiftUI/Modules/Room/AllChatsOnboarding/Coordinator/AllChatsOnboardingCoordinator.swift +++ b/RiotSwiftUI/Modules/Room/AllChatsOnboarding/Coordinator/AllChatsOnboardingCoordinator.swift @@ -14,12 +14,11 @@ // limitations under the License. // -import SwiftUI import CommonKit +import SwiftUI /// All Chats onboarding screen final class AllChatsOnboardingCoordinator: NSObject, Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -42,8 +41,8 @@ final class AllChatsOnboardingCoordinator: NSObject, Coordinator, Presentable { let viewModel = AllChatsOnboardingViewModel.makeAllChatsOnboardingViewModel() let view = AllChatsOnboarding(viewModel: viewModel.context) self.viewModel = viewModel - self.hostingController = VectorHostingController(rootView: view) - self.indicatorPresenter = UserIndicatorTypePresenter(presentingViewController: hostingController) + hostingController = VectorHostingController(rootView: view) + indicatorPresenter = UserIndicatorTypePresenter(presentingViewController: hostingController) super.init() @@ -65,7 +64,7 @@ final class AllChatsOnboardingCoordinator: NSObject, Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.hostingController + hostingController } // MARK: - Private @@ -87,9 +86,7 @@ final class AllChatsOnboardingCoordinator: NSObject, Coordinator, Presentable { // MARK: - UIAdaptivePresentationControllerDelegate extension AllChatsOnboardingCoordinator: UIAdaptivePresentationControllerDelegate { - func presentationControllerDidDismiss(_ presentationController: UIPresentationController) { completion?() } - } diff --git a/RiotSwiftUI/Modules/Room/AllChatsOnboarding/Coordinator/AllChatsOnboardingCoordinatorBridgePresenter.swift b/RiotSwiftUI/Modules/Room/AllChatsOnboarding/Coordinator/AllChatsOnboardingCoordinatorBridgePresenter.swift index b367175ef..75977054d 100644 --- a/RiotSwiftUI/Modules/Room/AllChatsOnboarding/Coordinator/AllChatsOnboardingCoordinatorBridgePresenter.swift +++ b/RiotSwiftUI/Modules/Room/AllChatsOnboarding/Coordinator/AllChatsOnboardingCoordinatorBridgePresenter.swift @@ -26,7 +26,6 @@ import Foundation /// Each bridge should be removed once the underlying Coordinator has been integrated by another Coordinator. @objcMembers final class AllChatsOnboardingCoordinatorBridgePresenter: NSObject { - // MARK: - Properties // MARK: Private @@ -53,7 +52,7 @@ final class AllChatsOnboardingCoordinatorBridgePresenter: NSObject { } func dismiss(animated: Bool, completion: (() -> Void)?) { - guard let coordinator = self.coordinator else { + guard let coordinator = coordinator else { return } coordinator.toPresentable().dismiss(animated: animated) { @@ -62,4 +61,3 @@ final class AllChatsOnboardingCoordinatorBridgePresenter: NSObject { } } } - diff --git a/RiotSwiftUI/Modules/Room/AllChatsOnboarding/View/AllChatsOnboarding.swift b/RiotSwiftUI/Modules/Room/AllChatsOnboarding/View/AllChatsOnboarding.swift index b13f9a287..513cc55a3 100644 --- a/RiotSwiftUI/Modules/Room/AllChatsOnboarding/View/AllChatsOnboarding.swift +++ b/RiotSwiftUI/Modules/Room/AllChatsOnboarding/View/AllChatsOnboarding.swift @@ -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 AllChatsOnboarding: View { - // MARK: - Properties // MARK: Private @@ -36,12 +35,12 @@ struct AllChatsOnboarding: View { .foregroundColor(theme.colors.primaryContent) .padding() TabView(selection: $selectedTab) { - ForEach(viewModel.viewState.pages.indices) { index in + ForEach(viewModel.viewState.pages.indices, id: \.self) { index in let page = viewModel.viewState.pages[index] AllChatsOnboardingPage(image: page.image, title: page.title, message: page.message) - .tag(index) + .tag(index) } } .tabViewStyle(PageTabViewStyle(indexDisplayMode: .automatic)) @@ -61,7 +60,7 @@ struct AllChatsOnboarding: View { // MARK: - Private private func onCallToAction() { - if (selectedTab == viewModel.viewState.pages.count - 1) { + if selectedTab == viewModel.viewState.pages.count - 1 { viewModel.send(viewAction: .cancel) } else { withAnimation { diff --git a/RiotSwiftUI/Modules/Room/AllChatsOnboarding/View/AllChatsOnboardingPage.swift b/RiotSwiftUI/Modules/Room/AllChatsOnboarding/View/AllChatsOnboardingPage.swift index 04725ccae..c6a5f06fa 100644 --- a/RiotSwiftUI/Modules/Room/AllChatsOnboarding/View/AllChatsOnboardingPage.swift +++ b/RiotSwiftUI/Modules/Room/AllChatsOnboarding/View/AllChatsOnboardingPage.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ import SwiftUI struct AllChatsOnboardingPage: View { - // MARK: - Properties let image: UIImage @@ -55,7 +54,7 @@ struct AllChatsOnboardingPage_Previews: PreviewProvider { preview.theme(.dark).preferredColorScheme(.dark) } - static private var preview: some View { + private static var preview: some View { AllChatsOnboardingPage(image: Asset.Images.allChatsOnboarding1.image, title: VectorL10n.allChatsOnboardingPageTitle1, message: VectorL10n.allChatsOnboardingPageMessage1) diff --git a/RiotSwiftUI/Modules/Room/NotificationSettings/Coordinator/RoomNotificationSettingsBridgePresenter.swift b/RiotSwiftUI/Modules/Room/NotificationSettings/Coordinator/RoomNotificationSettingsBridgePresenter.swift index 0be2f18a1..be7571107 100644 --- a/RiotSwiftUI/Modules/Room/NotificationSettings/Coordinator/RoomNotificationSettingsBridgePresenter.swift +++ b/RiotSwiftUI/Modules/Room/NotificationSettings/Coordinator/RoomNotificationSettingsBridgePresenter.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,7 +25,6 @@ import Foundation /// Each bridge should be removed once the underlying Coordinator has been integrated by another Coordinator. @objcMembers final class RoomNotificationSettingsCoordinatorBridgePresenter: NSObject { - // MARK: - Properties // MARK: Private @@ -61,11 +60,11 @@ final class RoomNotificationSettingsCoordinatorBridgePresenter: NSObject { viewController.present(navigationController, animated: animated, completion: nil) roomNotificationSettingsCoordinator.start() - self.coordinator = roomNotificationSettingsCoordinator + coordinator = roomNotificationSettingsCoordinator } func dismiss(animated: Bool, completion: (() -> Void)?) { - guard let coordinator = self.coordinator else { + guard let coordinator = coordinator else { return } coordinator.toPresentable().dismiss(animated: animated) { @@ -79,22 +78,21 @@ final class RoomNotificationSettingsCoordinatorBridgePresenter: NSObject { } // MARK: - RoomNotificationSettingsCoordinatorDelegate + extension RoomNotificationSettingsCoordinatorBridgePresenter: RoomNotificationSettingsCoordinatorDelegate { func roomNotificationSettingsCoordinatorDidCancel(_ coordinator: RoomNotificationSettingsCoordinatorType) { - self.delegate?.roomNotificationSettingsCoordinatorBridgePresenterDelegateDidComplete(self) + delegate?.roomNotificationSettingsCoordinatorBridgePresenterDelegateDidComplete(self) } func roomNotificationSettingsCoordinatorDidComplete(_ coordinator: RoomNotificationSettingsCoordinatorType) { - self.delegate?.roomNotificationSettingsCoordinatorBridgePresenterDelegateDidComplete(self) + delegate?.roomNotificationSettingsCoordinatorBridgePresenterDelegateDidComplete(self) } } // MARK: - UIAdaptivePresentationControllerDelegate extension RoomNotificationSettingsCoordinatorBridgePresenter: UIAdaptivePresentationControllerDelegate { - func roomNotificationSettingsCoordinatorDidComplete(_ presentationController: UIPresentationController) { - self.delegate?.roomNotificationSettingsCoordinatorBridgePresenterDelegateDidComplete(self) + delegate?.roomNotificationSettingsCoordinatorBridgePresenterDelegateDidComplete(self) } - } diff --git a/RiotSwiftUI/Modules/Room/NotificationSettings/Coordinator/RoomNotificationSettingsCoordinator.swift b/RiotSwiftUI/Modules/Room/NotificationSettings/Coordinator/RoomNotificationSettingsCoordinator.swift index fef123281..e0d909898 100644 --- a/RiotSwiftUI/Modules/Room/NotificationSettings/Coordinator/RoomNotificationSettingsCoordinator.swift +++ b/RiotSwiftUI/Modules/Room/NotificationSettings/Coordinator/RoomNotificationSettingsCoordinator.swift @@ -15,14 +15,14 @@ // import Foundation -import UIKit import SwiftUI +import UIKit final class RoomNotificationSettingsCoordinator: RoomNotificationSettingsCoordinatorType { - // MARK: - Properties // MARK: Private + private var roomNotificationSettingsViewModel: RoomNotificationSettingsViewModelType private let roomNotificationSettingsViewController: UIViewController @@ -47,34 +47,35 @@ final class RoomNotificationSettingsCoordinator: RoomNotificationSettingsCoordin roomNotificationService: roomNotificationService, avatarData: avatarData, displayName: room.summary.displayname, - roomEncrypted: room.summary.isEncrypted) + roomEncrypted: room.summary.isEncrypted + ) let avatarService: AvatarServiceProtocol = AvatarService(mediaManager: room.mxSession.mediaManager) let view = RoomNotificationSettings(viewModel: viewModel, presentedModally: presentedModally) .addDependency(avatarService) let viewController = VectorHostingController(rootView: view) - self.roomNotificationSettingsViewModel = viewModel - self.roomNotificationSettingsViewController = viewController + roomNotificationSettingsViewModel = viewModel + roomNotificationSettingsViewController = viewController } // MARK: - Public methods - func start() { - self.roomNotificationSettingsViewModel.coordinatorDelegate = self + func start() { + roomNotificationSettingsViewModel.coordinatorDelegate = self } func toPresentable() -> UIViewController { - return self.roomNotificationSettingsViewController + roomNotificationSettingsViewController } } // MARK: - RoomNotificationSettingsViewModelCoordinatorDelegate + extension RoomNotificationSettingsCoordinator: RoomNotificationSettingsViewModelCoordinatorDelegate { - func roomNotificationSettingsViewModelDidComplete(_ viewModel: RoomNotificationSettingsViewModelType) { - self.delegate?.roomNotificationSettingsCoordinatorDidComplete(self) + delegate?.roomNotificationSettingsCoordinatorDidComplete(self) } func roomNotificationSettingsViewModelDidCancel(_ viewModel: RoomNotificationSettingsViewModelType) { - self.delegate?.roomNotificationSettingsCoordinatorDidCancel(self) + delegate?.roomNotificationSettingsCoordinatorDidCancel(self) } } diff --git a/RiotSwiftUI/Modules/Room/NotificationSettings/Model/RoomNotificationSettingsViewState.swift b/RiotSwiftUI/Modules/Room/NotificationSettings/Model/RoomNotificationSettingsViewState.swift index ba8e92916..96773de68 100644 --- a/RiotSwiftUI/Modules/Room/NotificationSettings/Model/RoomNotificationSettingsViewState.swift +++ b/RiotSwiftUI/Modules/Room/NotificationSettings/Model/RoomNotificationSettingsViewState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -40,4 +40,3 @@ extension RoomNotificationSettingsViewState { roomEncrypted ? VectorL10n.roomNotifsSettingsEncryptedRoomNotice : "" } } - diff --git a/RiotSwiftUI/Modules/Room/NotificationSettings/Model/RoomNotificationSettingsViewStateType.swift b/RiotSwiftUI/Modules/Room/NotificationSettings/Model/RoomNotificationSettingsViewStateType.swift index 0b9c7e0b6..d17fcc3dc 100644 --- a/RiotSwiftUI/Modules/Room/NotificationSettings/Model/RoomNotificationSettingsViewStateType.swift +++ b/RiotSwiftUI/Modules/Room/NotificationSettings/Model/RoomNotificationSettingsViewStateType.swift @@ -26,4 +26,3 @@ protocol RoomNotificationSettingsViewStateType { var avatarData: AvatarProtocol? { get } var displayName: String? { get } } - diff --git a/RiotSwiftUI/Modules/Room/NotificationSettings/Model/RoomNotificationState.swift b/RiotSwiftUI/Modules/Room/NotificationSettings/Model/RoomNotificationState.swift index 00c51d6fc..e34bb5faa 100644 --- a/RiotSwiftUI/Modules/Room/NotificationSettings/Model/RoomNotificationState.swift +++ b/RiotSwiftUI/Modules/Room/NotificationSettings/Model/RoomNotificationState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,7 +25,7 @@ enum RoomNotificationState: Int { extension RoomNotificationState: CaseIterable { } extension RoomNotificationState: Identifiable { - var id: Int { self.rawValue } + var id: Int { rawValue } } extension RoomNotificationState { diff --git a/RiotSwiftUI/Modules/Room/NotificationSettings/Service/MatrixSDK/MXRoomNotificationSettingsService.swift b/RiotSwiftUI/Modules/Room/NotificationSettings/Service/MatrixSDK/MXRoomNotificationSettingsService.swift index 03b868a83..e9d192b49 100644 --- a/RiotSwiftUI/Modules/Room/NotificationSettings/Service/MatrixSDK/MXRoomNotificationSettingsService.swift +++ b/RiotSwiftUI/Modules/Room/NotificationSettings/Service/MatrixSDK/MXRoomNotificationSettingsService.swift @@ -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 final class MXRoomNotificationSettingsService: RoomNotificationSettingsServiceType { - typealias Completion = () -> Void // MARK: - Properties @@ -50,11 +49,11 @@ final class MXRoomNotificationSettingsService: RoomNotificationSettingsServiceTy // MARK: - Public func observeNotificationState(listener: @escaping RoomNotificationStateCallback) { - let observer = NotificationCenter.default.addObserver( forName: NSNotification.Name(rawValue: kMXNotificationCenterDidUpdateRules), object: nil, - queue: OperationQueue.main) { [weak self] _ in + queue: OperationQueue.main + ) { [weak self] _ in guard let self = self else { return } listener(self.room.notificationState) } @@ -88,7 +87,7 @@ final class MXRoomNotificationSettingsService: RoomNotificationSettingsServiceTy } guard let rule = room.overridePushRule else { - self.addPushRuleToMute(completion: completion) + addPushRuleToMute(completion: completion) return } @@ -96,7 +95,7 @@ final class MXRoomNotificationSettingsService: RoomNotificationSettingsServiceTy MXLog.debug("[RoomNotificationSettingsService] Request in progress: ignore push rule update") completion() return - } + } // if the user defined one, use it if rule.actionsContains(actionType: MXPushRuleActionTypeDontNotify) { @@ -130,7 +129,7 @@ final class MXRoomNotificationSettingsService: RoomNotificationSettingsServiceTy MXLog.debug("[MXRoom+Riot] Request in progress: ignore push rule update") completion() return - } + } // if the user defined one, use it if rule.actionsContains(actionType: MXPushRuleActionTypeDontNotify) { @@ -140,11 +139,10 @@ final class MXRoomNotificationSettingsService: RoomNotificationSettingsServiceTy self.addPushRuleToMentionOnly(completion: completion) } } - } private func allMessages(completion: @escaping Completion) { - if !room.isMentionsOnly && !room.isMuted { + if !room.isMentionsOnly, !room.isMuted { completion() return } @@ -172,7 +170,8 @@ final class MXRoomNotificationSettingsService: RoomNotificationSettingsServiceTy room.roomId, notify: false, sound: false, - highlight: false) + highlight: false + ) } private func addPushRuleToMute(completion: @escaping Completion) { @@ -207,18 +206,19 @@ final class MXRoomNotificationSettingsService: RoomNotificationSettingsServiceTy private func enablePushRule(rule: MXPushRule, completion: @escaping Completion) { handleUpdateCallback(completion) { // No way to check whether this notification concerns the push rule. Consider the change is applied. - return true + true } handleFailureCallback(completion) room.mxSession.notificationCenter.enableRule(rule, isEnabled: true) } - private func handleUpdateCallback(_ completion: @escaping Completion, releaseCheck: @escaping () -> Bool) { + private func handleUpdateCallback(_ completion: @escaping Completion, releaseCheck: @escaping () -> Bool) { notificationCenterDidUpdateObserver = NotificationCenter.default.addObserver( forName: NSNotification.Name(rawValue: kMXNotificationCenterDidUpdateRules), object: nil, - queue: OperationQueue.main) { [weak self] _ in + queue: OperationQueue.main + ) { [weak self] _ in guard let self = self else { return } if releaseCheck() { self.removeObservers() @@ -231,7 +231,8 @@ final class MXRoomNotificationSettingsService: RoomNotificationSettingsServiceTy notificationCenterDidFailObserver = NotificationCenter.default.addObserver( forName: NSNotification.Name(rawValue: kMXNotificationCenterDidFailRulesUpdate), object: nil, - queue: OperationQueue.main) { [weak self] _ in + queue: OperationQueue.main + ) { [weak self] _ in guard let self = self else { return } self.removeObservers() completion() @@ -239,23 +240,23 @@ final class MXRoomNotificationSettingsService: RoomNotificationSettingsServiceTy } func removeObservers() { - if let observer = self.notificationCenterDidUpdateObserver { + if let observer = notificationCenterDidUpdateObserver { NotificationCenter.default.removeObserver(observer) - self.notificationCenterDidUpdateObserver = nil + notificationCenterDidUpdateObserver = nil } - if let observer = self.notificationCenterDidFailObserver { + if let observer = notificationCenterDidFailObserver { NotificationCenter.default.removeObserver(observer) - self.notificationCenterDidFailObserver = nil + notificationCenterDidFailObserver = nil } } } -extension MXRoom { - public var isMuted: Bool { +public extension MXRoom { + var isMuted: Bool { // Check whether an override rule has been defined with the roomm id as rule id. // This kind of rule is created to mute the room - guard let rule = self.overridePushRule, + guard let rule = overridePushRule, rule.actionsContains(actionType: MXPushRuleActionTypeDontNotify), rule.conditionIsEnabled(kind: .eventMatch, for: roomId) else { return false @@ -263,7 +264,7 @@ extension MXRoom { return rule.enabled } - public var isMentionsOnly: Bool { + var isMentionsOnly: Bool { // Check push rules at room level guard let rule = roomPushRule else { return false } return rule.enabled && rule.actionsContains(actionType: MXPushRuleActionTypeDontNotify) @@ -271,8 +272,7 @@ extension MXRoom { } // We could move these to their own file and make available in global namespace or move to sdk but they are only used here at the moment -fileprivate extension MXRoom { - +private extension MXRoom { typealias Completion = () -> Void func getRoomRule(from rules: [Any]) -> MXPushRule? { guard let pushRules = rules as? [MXPushRule] else { @@ -285,19 +285,18 @@ fileprivate extension MXRoom { var overridePushRule: MXPushRule? { guard let overrideRules = mxSession.notificationCenter.rules.global.override else { return nil - } + } return getRoomRule(from: overrideRules) } var roomPushRule: MXPushRule? { guard let roomRules = mxSession.notificationCenter.rules.global.room else { return nil - } + } return getRoomRule(from: roomRules) } var notificationState: RoomNotificationState { - if isMuted { return .mute } @@ -306,10 +305,9 @@ fileprivate extension MXRoom { } return .all } - } -fileprivate extension MXPushRule { +private extension MXPushRule { func actionsContains(actionType: MXPushRuleActionType) -> Bool { guard let actions = actions as? [MXPushRuleAction] else { return false @@ -323,8 +321,8 @@ fileprivate extension MXPushRule { } let ruleContainsCondition = conditions.contains { condition in guard case kind = MXPushRuleConditionType(identifier: condition.kind), - let key = condition.parameters["key"] as? String, - let pattern = condition.parameters["pattern"] as? String + let key = condition.parameters["key"] as? String, + let pattern = condition.parameters["pattern"] as? String else { return false } return key == "room_id" && pattern == roomId } diff --git a/RiotSwiftUI/Modules/Room/NotificationSettings/Service/Mock/MockRoomNotificationSettingsService.swift b/RiotSwiftUI/Modules/Room/NotificationSettings/Service/Mock/MockRoomNotificationSettingsService.swift index 2330d07a5..9e04706de 100644 --- a/RiotSwiftUI/Modules/Room/NotificationSettings/Service/Mock/MockRoomNotificationSettingsService.swift +++ b/RiotSwiftUI/Modules/Room/NotificationSettings/Service/Mock/MockRoomNotificationSettingsService.swift @@ -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 class MockRoomNotificationSettingsService: RoomNotificationSettingsServiceType { - static let example = MockRoomNotificationSettingsService(initialState: .all) var listener: RoomNotificationStateCallback? @@ -32,7 +31,7 @@ class MockRoomNotificationSettingsService: RoomNotificationSettingsServiceType { } func update(state: RoomNotificationState, completion: @escaping UpdateRoomNotificationStateCompletion) { - self.notificationState = state + notificationState = state completion() listener?(state) } diff --git a/RiotSwiftUI/Modules/Room/NotificationSettings/Service/RoomNotificationSettingsServiceType.swift b/RiotSwiftUI/Modules/Room/NotificationSettings/Service/RoomNotificationSettingsServiceType.swift index 22961ad03..87443ceed 100644 --- a/RiotSwiftUI/Modules/Room/NotificationSettings/Service/RoomNotificationSettingsServiceType.swift +++ b/RiotSwiftUI/Modules/Room/NotificationSettings/Service/RoomNotificationSettingsServiceType.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,7 +20,6 @@ typealias UpdateRoomNotificationStateCompletion = () -> Void typealias RoomNotificationStateCallback = (RoomNotificationState) -> Void protocol RoomNotificationSettingsServiceType { - func observeNotificationState(listener: @escaping RoomNotificationStateCallback) func update(state: RoomNotificationState, completion: @escaping UpdateRoomNotificationStateCompletion) var notificationState: RoomNotificationState { get } diff --git a/RiotSwiftUI/Modules/Room/NotificationSettings/View/FormItemButtonStyle.swift b/RiotSwiftUI/Modules/Room/NotificationSettings/View/FormItemButtonStyle.swift index 385aacff0..c3b0a61ff 100644 --- a/RiotSwiftUI/Modules/Room/NotificationSettings/View/FormItemButtonStyle.swift +++ b/RiotSwiftUI/Modules/Room/NotificationSettings/View/FormItemButtonStyle.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Room/NotificationSettings/View/FormPickerItem.swift b/RiotSwiftUI/Modules/Room/NotificationSettings/View/FormPickerItem.swift index 43aee6da8..05a3b161f 100644 --- a/RiotSwiftUI/Modules/Room/NotificationSettings/View/FormPickerItem.swift +++ b/RiotSwiftUI/Modules/Room/NotificationSettings/View/FormPickerItem.swift @@ -17,7 +17,6 @@ import SwiftUI struct FormPickerItem: View { - typealias TapCallback = () -> Void @Environment(\.theme) var theme: ThemeSwiftUI @@ -53,7 +52,6 @@ struct FormPickerItem: View { } struct FormPickerItem_Previews: PreviewProvider { - static let items = ["Item 1", "Item 2", "Item 3"] static var selected: String = items[0] static var previews: some View { diff --git a/RiotSwiftUI/Modules/Room/NotificationSettings/View/FormSectionFooter.swift b/RiotSwiftUI/Modules/Room/NotificationSettings/View/FormSectionFooter.swift index 3465c40c9..4fc9e6211 100644 --- a/RiotSwiftUI/Modules/Room/NotificationSettings/View/FormSectionFooter.swift +++ b/RiotSwiftUI/Modules/Room/NotificationSettings/View/FormSectionFooter.swift @@ -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 FormSectionFooter: View { - @Environment(\.theme) var theme: ThemeSwiftUI var text: String diff --git a/RiotSwiftUI/Modules/Room/NotificationSettings/View/FormSectionHeader.swift b/RiotSwiftUI/Modules/Room/NotificationSettings/View/FormSectionHeader.swift index 0ca745ef4..483be9164 100644 --- a/RiotSwiftUI/Modules/Room/NotificationSettings/View/FormSectionHeader.swift +++ b/RiotSwiftUI/Modules/Room/NotificationSettings/View/FormSectionHeader.swift @@ -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 FormSectionHeader: View { - @Environment(\.theme) var theme: ThemeSwiftUI var text: String diff --git a/RiotSwiftUI/Modules/Room/NotificationSettings/View/RoomNotificationSettings.swift b/RiotSwiftUI/Modules/Room/NotificationSettings/View/RoomNotificationSettings.swift index 864482e4b..3034f50db 100644 --- a/RiotSwiftUI/Modules/Room/NotificationSettings/View/RoomNotificationSettings.swift +++ b/RiotSwiftUI/Modules/Room/NotificationSettings/View/RoomNotificationSettings.swift @@ -17,7 +17,6 @@ import SwiftUI struct RoomNotificationSettings: View { - @Environment(\.theme) var theme: ThemeSwiftUI @ObservedObject var viewModel: RoomNotificationSettingsSwiftUIViewModel @@ -42,7 +41,7 @@ struct RoomNotificationSettings: View { var body: some View { VectorForm { - if let avatarData = viewModel.viewState.avatarData as? AvatarInputProtocol { + if let avatarData = viewModel.viewState.avatarData as? AvatarInputProtocol { RoomNotificationSettingsHeader( avatarData: avatarData, displayName: viewModel.viewState.displayName @@ -74,7 +73,6 @@ struct RoomNotificationSettings: View { } struct RoomNotificationSettings_Previews: PreviewProvider { - static let mockViewModel = RoomNotificationSettingsSwiftUIViewModel( roomNotificationService: MockRoomNotificationSettingsService.example, avatarData: MockAvatarInput.example, diff --git a/RiotSwiftUI/Modules/Room/NotificationSettings/View/RoomNotificationSettingsHeader.swift b/RiotSwiftUI/Modules/Room/NotificationSettings/View/RoomNotificationSettingsHeader.swift index a0b602fd8..20066b961 100644 --- a/RiotSwiftUI/Modules/Room/NotificationSettings/View/RoomNotificationSettingsHeader.swift +++ b/RiotSwiftUI/Modules/Room/NotificationSettings/View/RoomNotificationSettingsHeader.swift @@ -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 RoomNotificationSettingsHeader: View { - @Environment(\.theme) var theme: ThemeSwiftUI var avatarData: AvatarInputProtocol var displayName: String? diff --git a/RiotSwiftUI/Modules/Room/NotificationSettings/View/VectorForm.swift b/RiotSwiftUI/Modules/Room/NotificationSettings/View/VectorForm.swift index 1ca9933ec..f7e4b3dbc 100644 --- a/RiotSwiftUI/Modules/Room/NotificationSettings/View/VectorForm.swift +++ b/RiotSwiftUI/Modules/Room/NotificationSettings/View/VectorForm.swift @@ -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 VectorForm: View { - @Environment(\.theme) var theme: ThemeSwiftUI var content: () -> Content @@ -38,12 +37,10 @@ struct VectorForm: View { ) .background(theme.colors.system) .edgesIgnoringSafeArea(.bottom) - } } struct VectorForm_Previews: PreviewProvider { - static var previews: some View { Group { VectorForm { diff --git a/RiotSwiftUI/Modules/Room/NotificationSettings/ViewModel/RoomNotificationSettingsSwiftUIViewModel.swift b/RiotSwiftUI/Modules/Room/NotificationSettings/ViewModel/RoomNotificationSettingsSwiftUIViewModel.swift index d9b6d9bc8..1697601c2 100644 --- a/RiotSwiftUI/Modules/Room/NotificationSettings/ViewModel/RoomNotificationSettingsSwiftUIViewModel.swift +++ b/RiotSwiftUI/Modules/Room/NotificationSettings/ViewModel/RoomNotificationSettingsSwiftUIViewModel.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,17 +14,16 @@ // limitations under the License. // -import Foundation import Combine +import Foundation class RoomNotificationSettingsSwiftUIViewModel: RoomNotificationSettingsViewModel, ObservableObject { - @Published var viewState: RoomNotificationSettingsViewState lazy var cancellables = Set() override init(roomNotificationService: RoomNotificationSettingsServiceType, initialState: RoomNotificationSettingsViewState) { - self.viewState = initialState + viewState = initialState super.init(roomNotificationService: roomNotificationService, initialState: initialState) } diff --git a/RiotSwiftUI/Modules/Room/NotificationSettings/ViewModel/RoomNotificationSettingsViewModel.swift b/RiotSwiftUI/Modules/Room/NotificationSettings/ViewModel/RoomNotificationSettingsViewModel.swift index 6b09b81d6..977945f8c 100644 --- a/RiotSwiftUI/Modules/Room/NotificationSettings/ViewModel/RoomNotificationSettingsViewModel.swift +++ b/RiotSwiftUI/Modules/Room/NotificationSettings/ViewModel/RoomNotificationSettingsViewModel.swift @@ -16,11 +16,10 @@ limitations under the License. */ -import Foundation import Combine +import Foundation class RoomNotificationSettingsViewModel: RoomNotificationSettingsViewModelType { - // MARK: - Properties // MARK: Private @@ -40,12 +39,10 @@ class RoomNotificationSettingsViewModel: RoomNotificationSettingsViewModelType { // MARK: - Setup - init( - roomNotificationService: RoomNotificationSettingsServiceType, - initialState: RoomNotificationSettingsViewState - ) { + init(roomNotificationService: RoomNotificationSettingsServiceType, + initialState: RoomNotificationSettingsViewState) { self.roomNotificationService = roomNotificationService - self.state = initialState + state = initialState self.roomNotificationService.observeNotificationState { [weak self] state in guard let self = self else { return } @@ -53,12 +50,10 @@ class RoomNotificationSettingsViewModel: RoomNotificationSettingsViewModelType { } } - convenience init( - roomNotificationService: RoomNotificationSettingsServiceType, - avatarData: AvatarProtocol?, - displayName: String?, - roomEncrypted: Bool - ) { + convenience init(roomNotificationService: RoomNotificationSettingsServiceType, + avatarData: AvatarProtocol?, + displayName: String?, + roomEncrypted: Bool) { let notificationState = Self.mapNotificationStateOnRead(encrypted: roomEncrypted, state: roomNotificationService.notificationState) let initialState = RoomNotificationSettingsViewState( @@ -71,16 +66,16 @@ class RoomNotificationSettingsViewModel: RoomNotificationSettingsViewModelType { self.init(roomNotificationService: roomNotificationService, initialState: initialState) } - // MARK: - Public + // MARK: - Public func process(viewAction: RoomNotificationSettingsViewAction) { switch viewAction { case .load: - update(viewState: self.state) + update(viewState: state) case .selectNotificationState(let state): self.state.notificationState = state case .save: - self.state.saving = true + state.saving = true roomNotificationService.update(state: state.notificationState) { [weak self] in guard let self = self else { return } self.state.saving = false @@ -103,6 +98,6 @@ class RoomNotificationSettingsViewModel: RoomNotificationSettingsViewModelType { } func update(viewState: RoomNotificationSettingsViewState) { - self.viewDelegate?.roomNotificationSettingsViewModel(self, didUpdateViewState: viewState) + viewDelegate?.roomNotificationSettingsViewModel(self, didUpdateViewState: viewState) } } diff --git a/RiotSwiftUI/Modules/Room/NotificationSettings/ViewModel/RoomNotificationSettingsViewModelType.swift b/RiotSwiftUI/Modules/Room/NotificationSettings/ViewModel/RoomNotificationSettingsViewModelType.swift index e2fe135d4..5df765f25 100644 --- a/RiotSwiftUI/Modules/Room/NotificationSettings/ViewModel/RoomNotificationSettingsViewModelType.swift +++ b/RiotSwiftUI/Modules/Room/NotificationSettings/ViewModel/RoomNotificationSettingsViewModelType.swift @@ -28,8 +28,7 @@ protocol RoomNotificationSettingsViewModelCoordinatorDelegate: AnyObject { } /// Protocol describing the view model used by `RoomNotificationSettingsViewController` -protocol RoomNotificationSettingsViewModelType { - +protocol RoomNotificationSettingsViewModelType { var viewDelegate: RoomNotificationSettingsViewModelViewDelegate? { get set } var coordinatorDelegate: RoomNotificationSettingsViewModelCoordinatorDelegate? { get set } diff --git a/RiotSwiftUI/Modules/Room/PollEditForm/Coordinator/PollEditFormCoordinator.swift b/RiotSwiftUI/Modules/Room/PollEditForm/Coordinator/PollEditFormCoordinator.swift index 14ed174de..dcda5b5ab 100644 --- a/RiotSwiftUI/Modules/Room/PollEditForm/Coordinator/PollEditFormCoordinator.swift +++ b/RiotSwiftUI/Modules/Room/PollEditForm/Coordinator/PollEditFormCoordinator.swift @@ -15,8 +15,8 @@ // import Foundation -import UIKit import SwiftUI +import UIKit struct PollEditFormCoordinatorParameters { let room: MXRoom @@ -24,7 +24,6 @@ struct PollEditFormCoordinatorParameters { } final class PollEditFormCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -50,7 +49,7 @@ final class PollEditFormCoordinator: Coordinator, Presentable { viewModel = PollEditFormViewModel(parameters: PollEditFormViewModelParameters(mode: .editing, pollDetails: EditFormPollDetails(type: Self.pollKindKeyToDetailsType(pollContent.kind), question: pollContent.question, - answerOptions: pollContent.answerOptions.map { $0.text }))) + answerOptions: pollContent.answerOptions.map(\.text)))) } else { viewModel = PollEditFormViewModel(parameters: PollEditFormViewModelParameters(mode: .creation, pollDetails: .default)) @@ -63,6 +62,7 @@ final class PollEditFormCoordinator: Coordinator, Presentable { } // MARK: - Public + func start() { pollEditFormViewModel.completion = { [weak self] result in guard let self = self else { return } @@ -75,7 +75,7 @@ final class PollEditFormCoordinator: Coordinator, Presentable { self.pollEditFormViewModel.startLoading() - self.parameters.room.sendPollStart(withContent: pollStartContent, threadId: nil, localEcho: nil) { [weak self] result in + self.parameters.room.sendPollStart(withContent: pollStartContent, threadId: nil, localEcho: nil) { [weak self] _ in guard let self = self else { return } self.pollEditFormViewModel.stopLoading() @@ -103,7 +103,7 @@ final class PollEditFormCoordinator: Coordinator, Presentable { self.parameters.room.sendPollUpdate(for: pollStartEvent, oldContent: oldPollContent, - newContent: newPollContent, localEcho: nil) { [weak self] result in + newContent: newPollContent, localEcho: nil) { [weak self] _ in guard let self = self else { return } self.pollEditFormViewModel.stopLoading() @@ -113,7 +113,7 @@ final class PollEditFormCoordinator: Coordinator, Presentable { MXLog.error("Failed updating poll", context: error) self.pollEditFormViewModel.stopLoading(errorAlertType: .failedUpdatingPoll) - } + } } } } @@ -121,7 +121,7 @@ final class PollEditFormCoordinator: Coordinator, Presentable { // MARK: - Presentable func toPresentable() -> UIViewController { - return pollEditFormHostingController + pollEditFormHostingController } // MARK: - Private @@ -136,21 +136,20 @@ final class PollEditFormCoordinator: Coordinator, Presentable { kind: Self.pollDetailsTypeToKindKey(details.type), maxSelections: NSNumber(value: details.maxSelections), answerOptions: options) - } private static func pollDetailsTypeToKindKey(_ type: EditFormPollType) -> String { - let mapping = [EditFormPollType.disclosed : kMXMessageContentKeyExtensiblePollKindDisclosedMSC3381, - EditFormPollType.undisclosed : kMXMessageContentKeyExtensiblePollKindUndisclosedMSC3381] + let mapping = [EditFormPollType.disclosed: kMXMessageContentKeyExtensiblePollKindDisclosedMSC3381, + EditFormPollType.undisclosed: kMXMessageContentKeyExtensiblePollKindUndisclosedMSC3381] return mapping[type] ?? kMXMessageContentKeyExtensiblePollKindDisclosedMSC3381 } private static func pollKindKeyToDetailsType(_ key: String) -> EditFormPollType { - let mapping = [kMXMessageContentKeyExtensiblePollKindDisclosed : EditFormPollType.disclosed, - kMXMessageContentKeyExtensiblePollKindDisclosedMSC3381 : EditFormPollType.disclosed, - kMXMessageContentKeyExtensiblePollKindUndisclosed : EditFormPollType.undisclosed, - kMXMessageContentKeyExtensiblePollKindUndisclosedMSC3381 : EditFormPollType.undisclosed] + let mapping = [kMXMessageContentKeyExtensiblePollKindDisclosed: EditFormPollType.disclosed, + kMXMessageContentKeyExtensiblePollKindDisclosedMSC3381: EditFormPollType.disclosed, + kMXMessageContentKeyExtensiblePollKindUndisclosed: EditFormPollType.undisclosed, + kMXMessageContentKeyExtensiblePollKindUndisclosedMSC3381: EditFormPollType.undisclosed] return mapping[key] ?? EditFormPollType.disclosed } diff --git a/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormModels.swift b/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormModels.swift index 75fbf84ab..9e2171bf7 100644 --- a/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormModels.swift +++ b/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -82,14 +82,14 @@ struct PollEditFormViewState: BindableState { var confirmationButtonEnabled: Bool { !bindings.question.text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty && - bindings.answerOptions.filter({ !$0.text.isEmpty }).count >= minAnswerOptionsCount + bindings.answerOptions.filter { !$0.text.isEmpty }.count >= minAnswerOptionsCount } var addAnswerOptionButtonEnabled: Bool { bindings.answerOptions.count < maxAnswerOptionsCount } - var showLoadingIndicator: Bool = false + var showLoadingIndicator = false } struct PollEditFormViewStateBindings { diff --git a/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormScreenState.swift b/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormScreenState.swift index 3d15e3be4..d4982b357 100644 --- a/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormScreenState.swift +++ b/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,7 +24,7 @@ enum MockPollEditFormScreenState: MockScreenState, CaseIterable { PollEditForm.self } - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let viewModel = PollEditFormViewModel(parameters: PollEditFormViewModelParameters(mode: .creation, pollDetails: .default)) return ([viewModel], AnyView(PollEditForm(viewModel: viewModel.context))) } diff --git a/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormViewModel.swift b/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormViewModel.swift index 6b22edc50..0c9de40a7 100644 --- a/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormViewModel.swift +++ b/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormViewModel.swift @@ -14,20 +14,19 @@ // limitations under the License. // -import SwiftUI import Combine +import SwiftUI struct PollEditFormViewModelParameters { let mode: PollEditFormMode let pollDetails: EditFormPollDetails } -typealias PollEditFormViewModelType = StateStoreViewModel +typealias PollEditFormViewModelType = StateStoreViewModel class PollEditFormViewModel: PollEditFormViewModelType, PollEditFormViewModelProtocol { - - private struct Constants { + private enum Constants { static let minAnswerOptionsCount = 2 static let maxAnswerOptionsCount = 20 static let maxQuestionLength = 340 @@ -102,11 +101,11 @@ class PollEditFormViewModel: PollEditFormViewModelType, PollEditFormViewModelPro // MARK: - Private private func buildPollDetails() -> EditFormPollDetails { - return EditFormPollDetails(type: state.bindings.type, - question: state.bindings.question.text.trimmingCharacters(in: .whitespacesAndNewlines), - answerOptions: state.bindings.answerOptions.compactMap({ answerOption in - let text = answerOption.text.trimmingCharacters(in: .whitespacesAndNewlines) - return text.isEmpty ? nil : text - })) + EditFormPollDetails(type: state.bindings.type, + question: state.bindings.question.text.trimmingCharacters(in: .whitespacesAndNewlines), + answerOptions: state.bindings.answerOptions.compactMap { answerOption in + let text = answerOption.text.trimmingCharacters(in: .whitespacesAndNewlines) + return text.isEmpty ? nil : text + }) } } diff --git a/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormViewModelProtocol.swift b/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormViewModelProtocol.swift index da2824270..ce87af060 100644 --- a/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormViewModelProtocol.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Room/PollEditForm/Test/UI/PollEditFormUITests.swift b/RiotSwiftUI/Modules/Room/PollEditForm/Test/UI/PollEditFormUITests.swift index d56c88391..0742cf7bb 100644 --- a/RiotSwiftUI/Modules/Room/PollEditForm/Test/UI/PollEditFormUITests.swift +++ b/RiotSwiftUI/Modules/Room/PollEditForm/Test/UI/PollEditFormUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class PollEditFormUITests: MockScreenTestCase { func testInitialStateComponents() { diff --git a/RiotSwiftUI/Modules/Room/PollEditForm/Test/Unit/PollEditFormViewModelTests.swift b/RiotSwiftUI/Modules/Room/PollEditForm/Test/Unit/PollEditFormViewModelTests.swift index 4f587a519..571cfd736 100644 --- a/RiotSwiftUI/Modules/Room/PollEditForm/Test/Unit/PollEditFormViewModelTests.swift +++ b/RiotSwiftUI/Modules/Room/PollEditForm/Test/Unit/PollEditFormViewModelTests.swift @@ -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 diff --git a/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditForm.swift b/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditForm.swift index 6f8419f28..12d8807d5 100644 --- a/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditForm.swift +++ b/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditForm.swift @@ -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 PollEditForm: View { - // MARK: - Properties // MARK: Private @@ -33,7 +32,6 @@ struct PollEditForm: View { GeometryReader { proxy in ScrollView { VStack(alignment: .leading, spacing: 32.0) { - PollEditFormTypePicker(selectedType: $viewModel.type) VStack(alignment: .leading, spacing: 16.0) { diff --git a/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditFormAnswerOptionView.swift b/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditFormAnswerOptionView.swift index ccae185aa..325ae540b 100644 --- a/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditFormAnswerOptionView.swift +++ b/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditFormAnswerOptionView.swift @@ -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 PollEditFormAnswerOptionView: View { - @Environment(\.theme) private var theme: ThemeSwiftUI @State private var focused = false @@ -39,7 +38,7 @@ struct PollEditFormAnswerOptionView: View { }) .textFieldStyle(BorderedInputFieldStyle(isEditing: focused)) Button(action: onDelete) { - Image(uiImage:Asset.Images.pollDeleteOptionIcon.image) + Image(uiImage: Asset.Images.pollDeleteOptionIcon.image) } .accessibilityIdentifier("Delete answer option") } @@ -50,12 +49,8 @@ struct PollEditFormAnswerOptionView: View { struct PollEditFormAnswerOptionView_Previews: PreviewProvider { static var previews: some View { VStack(spacing: 32.0) { - PollEditFormAnswerOptionView(text: Binding.constant(""), index: 0) { - - } - PollEditFormAnswerOptionView(text: Binding.constant("Test"), index: 5) { - - } + PollEditFormAnswerOptionView(text: Binding.constant(""), index: 0) { } + PollEditFormAnswerOptionView(text: Binding.constant("Test"), index: 5) { } } } } diff --git a/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditFormTypePicker.swift b/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditFormTypePicker.swift index aa8f54289..9a2b48145 100644 --- a/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditFormTypePicker.swift +++ b/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditFormTypePicker.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -43,7 +43,6 @@ private struct PollEditFormTypeButton: View { selectedType = type } label: { HStack(alignment: .top, spacing: 8.0) { - Image(uiImage: selectionImage) VStack(alignment: .leading, spacing: 2) { diff --git a/RiotSwiftUI/Modules/Room/RoomAccess/Coordinator/RoomAccessCoordinator.swift b/RiotSwiftUI/Modules/Room/RoomAccess/Coordinator/RoomAccessCoordinator.swift index 5ca4563dc..0d109ecdc 100644 --- a/RiotSwiftUI/Modules/Room/RoomAccess/Coordinator/RoomAccessCoordinator.swift +++ b/RiotSwiftUI/Modules/Room/RoomAccess/Coordinator/RoomAccessCoordinator.swift @@ -26,7 +26,6 @@ enum RoomAccessCoordinatorCoordinatorAction { @objcMembers final class RoomAccessCoordinator: Coordinator { - // MARK: - Properties // MARK: Private @@ -35,7 +34,7 @@ final class RoomAccessCoordinator: Coordinator { private var upgradedRoomId: String? private var navigationRouter: NavigationRouterType { - return self.parameters.navigationRouter + parameters.navigationRouter } // MARK: Public @@ -58,32 +57,31 @@ final class RoomAccessCoordinator: Coordinator { init(parameters: RoomAccessCoordinatorParameters) { self.parameters = parameters - } + } // MARK: - Public - func start() { MXLog.debug("[RoomAccessCoordinator] did start.") - let rootCoordinator = self.createRoomAccessTypeCoordinator() + let rootCoordinator = createRoomAccessTypeCoordinator() rootCoordinator.start() - self.add(childCoordinator: rootCoordinator) - self.accessCoordinator = rootCoordinator + add(childCoordinator: rootCoordinator) + accessCoordinator = 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 @@ -91,7 +89,7 @@ final class RoomAccessCoordinator: 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) }) @@ -103,13 +101,13 @@ final class RoomAccessCoordinator: Coordinator { coordinator.toPresentable().modalPresentationStyle = .overFullScreen coordinator.toPresentable().modalTransitionStyle = .crossDissolve - self.navigationRouter.present(coordinator, animated: true) + navigationRouter.present(coordinator, animated: true) coordinator.start() } private func createRoomAccessTypeCoordinator() -> RoomAccessTypeChooserCoordinator { - let coordinator: RoomAccessTypeChooserCoordinator = RoomAccessTypeChooserCoordinator(parameters: RoomAccessTypeChooserCoordinatorParameters(roomId: parameters.room.roomId, allowsRoomUpgrade: parameters.allowsRoomUpgrade, session: parameters.room.mxSession)) + let coordinator = RoomAccessTypeChooserCoordinator(parameters: RoomAccessTypeChooserCoordinatorParameters(roomId: parameters.room.roomId, allowsRoomUpgrade: parameters.allowsRoomUpgrade, session: parameters.room.mxSession)) coordinator.callback = { [weak self] result in guard let self = self else { return } @@ -132,7 +130,8 @@ final class RoomAccessCoordinator: Coordinator { let paramaters = MatrixItemChooserCoordinatorParameters( session: parameters.room.mxSession, viewProvider: RoomRestrictedAccessSpaceChooserViewProvider(navTitle: VectorL10n.roomAccessSettingsScreenNavTitle), - itemsProcessor: RoomRestrictedAccessSpaceChooserItemsProcessor(roomId: roomId, session: parameters.room.mxSession)) + itemsProcessor: RoomRestrictedAccessSpaceChooserItemsProcessor(roomId: roomId, session: parameters.room.mxSession) + ) let coordinator = MatrixItemChooserCoordinator(parameters: paramaters) coordinator.completion = { [weak self] result in guard let self = self else { return } @@ -154,7 +153,8 @@ final class RoomAccessCoordinator: Coordinator { session: parameters.room.mxSession, roomId: roomId, parentSpaceId: parameters.parentSpaceId, - versionOverride: versionOverride) + versionOverride: versionOverride + ) let coordinator = RoomUpgradeCoordinator(parameters: paramaters) coordinator.completion = { [weak self] result in diff --git a/RiotSwiftUI/Modules/Room/RoomAccess/Coordinator/RoomAccessCoordinatorBridgePresenter.swift b/RiotSwiftUI/Modules/Room/RoomAccess/Coordinator/RoomAccessCoordinatorBridgePresenter.swift index 78a3215ba..623100b3b 100644 --- a/RiotSwiftUI/Modules/Room/RoomAccess/Coordinator/RoomAccessCoordinatorBridgePresenter.swift +++ b/RiotSwiftUI/Modules/Room/RoomAccess/Coordinator/RoomAccessCoordinatorBridgePresenter.swift @@ -1,4 +1,5 @@ // +import MatrixSDK // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,7 +15,6 @@ // limitations under the License. // import UIKit -import MatrixSDK @objc protocol RoomAccessCoordinatorBridgePresenterDelegate { func roomAccessCoordinatorBridgePresenterDelegate(_ coordinatorBridgePresenter: RoomAccessCoordinatorBridgePresenter, didCancelRoomWithId roomId: String) @@ -27,7 +27,6 @@ import MatrixSDK /// Each bridge should be removed once the underlying Coordinator has been integrated by another Coordinator. @objcMembers final class RoomAccessCoordinatorBridgePresenter: NSObject { - // MARK: - Properties // MARK: Private @@ -82,7 +81,7 @@ final class RoomAccessCoordinatorBridgePresenter: NSObject { } func dismiss(animated: Bool, completion: (() -> Void)?) { - guard let coordinator = self.coordinator else { + guard let coordinator = coordinator else { return } coordinator.toPresentable().dismiss(animated: animated) { @@ -98,13 +97,11 @@ final class RoomAccessCoordinatorBridgePresenter: NSObject { // MARK: - UIAdaptivePresentationControllerDelegate extension RoomAccessCoordinatorBridgePresenter: UIAdaptivePresentationControllerDelegate { - func roomNotificationSettingsCoordinatorDidComplete(_ presentationController: UIPresentationController) { - if let roomId = self.coordinator?.currentRoomId { - self.delegate?.roomAccessCoordinatorBridgePresenterDelegate(self, didCancelRoomWithId: roomId) + if let roomId = coordinator?.currentRoomId { + delegate?.roomAccessCoordinatorBridgePresenterDelegate(self, didCancelRoomWithId: roomId) } else { - self.delegate?.roomAccessCoordinatorBridgePresenterDelegate(self, didCancelRoomWithId: self.room.roomId) + delegate?.roomAccessCoordinatorBridgePresenterDelegate(self, didCancelRoomWithId: room.roomId) } } - } diff --git a/RiotSwiftUI/Modules/Room/RoomAccess/Coordinator/RoomAccessCoordinatorParameters.swift b/RiotSwiftUI/Modules/Room/RoomAccess/Coordinator/RoomAccessCoordinatorParameters.swift index a4459ea0a..50e128407 100644 --- a/RiotSwiftUI/Modules/Room/RoomAccess/Coordinator/RoomAccessCoordinatorParameters.swift +++ b/RiotSwiftUI/Modules/Room/RoomAccess/Coordinator/RoomAccessCoordinatorParameters.swift @@ -20,7 +20,6 @@ import Foundation /// RoomAccessCoordinator input parameters struct RoomAccessCoordinatorParameters { - /// The Matrix room let room: MXRoom diff --git a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Coordinator/RoomAccessTypeChooserCoordinator.swift b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Coordinator/RoomAccessTypeChooserCoordinator.swift index a46542a42..a6e6d2280 100644 --- a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Coordinator/RoomAccessTypeChooserCoordinator.swift +++ b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Coordinator/RoomAccessTypeChooserCoordinator.swift @@ -23,7 +23,6 @@ struct RoomAccessTypeChooserCoordinatorParameters { } final class RoomAccessTypeChooserCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -70,10 +69,10 @@ final class RoomAccessTypeChooserCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.roomAccessTypeChooserHostingController + roomAccessTypeChooserHostingController } func handleRoomUpgradeResult(_ result: RoomUpgradeCoordinatorResult) { - self.roomAccessTypeChooserViewModel.handleRoomUpgradeResult(result) + roomAccessTypeChooserViewModel.handleRoomUpgradeResult(result) } } diff --git a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/MockRoomAccessTypeChooserScreenState.swift b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/MockRoomAccessTypeChooserScreenState.swift index 47037d07f..fd8e74103 100644 --- a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/MockRoomAccessTypeChooserScreenState.swift +++ b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/MockRoomAccessTypeChooserScreenState.swift @@ -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 import SwiftUI - /// Using an enum for the screen allows you define the different state cases with /// the relevant associated data for each case. enum MockRoomAccessTypeChooserScreenState: MockScreenState, CaseIterable { @@ -42,7 +41,7 @@ enum MockRoomAccessTypeChooserScreenState: MockScreenState, CaseIterable { service = MockRoomAccessTypeChooserService(accessItems: [ RoomAccessTypeChooserAccessItem(id: .private, isSelected: true, title: VectorL10n.private, detail: VectorL10n.roomAccessSettingsScreenPrivateMessage, badgeText: nil), RoomAccessTypeChooserAccessItem(id: .restricted, isSelected: false, title: VectorL10n.createRoomTypeRestricted, detail: VectorL10n.roomAccessSettingsScreenRestrictedMessage, badgeText: VectorL10n.roomAccessSettingsScreenUpgradeRequired), - RoomAccessTypeChooserAccessItem(id: .public, isSelected: false, title: VectorL10n.public, detail: VectorL10n.roomAccessSettingsScreenPublicMessage, badgeText: nil), + RoomAccessTypeChooserAccessItem(id: .public, isSelected: false, title: VectorL10n.public, detail: VectorL10n.roomAccessSettingsScreenPublicMessage, badgeText: nil) ]) } let viewModel = RoomAccessTypeChooserViewModel(roomAccessTypeChooserService: service) diff --git a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/RoomAccessTypeChooserModels.swift b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/RoomAccessTypeChooserModels.swift index 2797adab9..4ebad9737 100644 --- a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/RoomAccessTypeChooserModels.swift +++ b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/RoomAccessTypeChooserModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/RoomAccessTypeChooserViewModel.swift b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/RoomAccessTypeChooserViewModel.swift index 7b97bd753..c05ff9ac5 100644 --- a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/RoomAccessTypeChooserViewModel.swift +++ b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/RoomAccessTypeChooserViewModel.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,14 +14,13 @@ // limitations under the License. // -import SwiftUI import Combine +import SwiftUI typealias RoomAccessTypeChooserViewModelType = StateStoreViewModel + RoomAccessTypeChooserStateAction, + RoomAccessTypeChooserViewAction> class RoomAccessTypeChooserViewModel: RoomAccessTypeChooserViewModelType, RoomAccessTypeChooserViewModelProtocol { - // MARK: - Properties // MARK: Private @@ -43,7 +42,8 @@ class RoomAccessTypeChooserViewModel: RoomAccessTypeChooserViewModelType, RoomAc private static func defaultState(roomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol) -> RoomAccessTypeChooserViewState { let bindings = RoomAccessTypeChooserViewModelBindings( showUpgradeRoomAlert: roomAccessTypeChooserService.roomUpgradeRequiredSubject.value, - waitingMessage: roomAccessTypeChooserService.waitingMessageSubject.value, isLoading: roomAccessTypeChooserService.waitingMessageSubject.value != nil) + waitingMessage: roomAccessTypeChooserService.waitingMessageSubject.value, isLoading: roomAccessTypeChooserService.waitingMessageSubject.value != nil + ) return RoomAccessTypeChooserViewState(accessItems: roomAccessTypeChooserService.accessItemsSubject.value, bindings: bindings) } @@ -130,7 +130,7 @@ class RoomAccessTypeChooserViewModel: RoomAccessTypeChooserViewModelType, RoomAc private func didSelect(accessType: RoomAccessTypeChooserAccessType) { roomAccessTypeChooserService.updateSelection(with: accessType) - if accessType == .restricted && !roomAccessTypeChooserService.roomUpgradeRequiredSubject.value { + if accessType == .restricted, !roomAccessTypeChooserService.roomUpgradeRequiredSubject.value { callback?(.spaceSelection(roomAccessTypeChooserService.currentRoomId, .restricted)) } } diff --git a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/RoomAccessTypeChooserViewModelProtocol.swift b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/RoomAccessTypeChooserViewModelProtocol.swift index 92b0b430a..8fdbc6f11 100644 --- a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/RoomAccessTypeChooserViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/RoomAccessTypeChooserViewModelProtocol.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Service/MatrixSDK/RoomAccessTypeChooserService.swift b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Service/MatrixSDK/RoomAccessTypeChooserService.swift index 1058f6b3b..ec307ca7f 100644 --- a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Service/MatrixSDK/RoomAccessTypeChooserService.swift +++ b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Service/MatrixSDK/RoomAccessTypeChooserService.swift @@ -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 RoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol { - // MARK: - Properties // MARK: Private @@ -40,6 +39,7 @@ class RoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol { accessItemsSubject.send(accessItems) } } + private(set) var selectedType: RoomAccessTypeChooserAccessType = .private { didSet { for (index, item) in accessItems.enumerated() { @@ -48,6 +48,7 @@ class RoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol { accessItemsSubject.send(accessItems) } } + private var roomJoinRule: MXRoomJoinRule = .private private var currentOperation: MXHTTPOperation? @@ -67,8 +68,8 @@ class RoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol { self.roomId = roomId self.allowsRoomUpgrade = allowsRoomUpgrade self.session = session - self.currentRoomId = roomId - self.versionOverride = session.homeserverCapabilitiesService.versionOverrideForFeature(.restricted) + currentRoomId = roomId + versionOverride = session.homeserverCapabilitiesService.versionOverrideForFeature(.restricted) roomUpgradeRequiredSubject = CurrentValueSubject(false) waitingMessageSubject = CurrentValueSubject(nil) @@ -92,7 +93,7 @@ class RoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol { self.selectedType = selectedType if selectedType == .restricted { - if roomUpgradeRequired && roomUpgradeRequiredSubject.value == false { + if roomUpgradeRequired, roomUpgradeRequiredSubject.value == false { roomUpgradeRequiredSubject.send(true) } } @@ -108,14 +109,14 @@ class RoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol { let _joinRule: MXRoomJoinRule? - switch self.selectedType { + switch selectedType { case .private: _joinRule = .invite case .public: _joinRule = .public case .restricted: _joinRule = nil - if roomUpgradeRequired && roomUpgradeRequiredSubject.value == false { + if roomUpgradeRequired, roomUpgradeRequiredSubject.value == false { roomUpgradeRequiredSubject.send(true) } else { completion() @@ -123,7 +124,7 @@ class RoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol { } if let joinRule = _joinRule { - self.waitingMessageSubject.send(VectorL10n.roomAccessSettingsScreenSettingRoomAccess) + waitingMessageSubject.send(VectorL10n.roomAccessSettingsScreenSettingRoomAccess) room.setJoinRule(joinRule) { [weak self] response in guard let self = self else { return } @@ -140,7 +141,7 @@ class RoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol { } func updateRoomId(with roomId: String) { - self.currentRoomId = roomId + currentRoomId = roomId readRoomState() } @@ -148,17 +149,17 @@ class RoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol { private func setupAccessItems() { guard let spaceService = session.spaceService, let ancestors = spaceService.ancestorsPerRoomId[currentRoomId], !ancestors.isEmpty, allowsRoomUpgrade || !roomUpgradeRequired else { - self.accessItems = [ + accessItems = [ RoomAccessTypeChooserAccessItem(id: .private, isSelected: false, title: VectorL10n.private, detail: VectorL10n.roomAccessSettingsScreenPrivateMessage, badgeText: nil), - RoomAccessTypeChooserAccessItem(id: .public, isSelected: false, title: VectorL10n.public, detail: VectorL10n.roomAccessSettingsScreenPublicMessage, badgeText: nil), + RoomAccessTypeChooserAccessItem(id: .public, isSelected: false, title: VectorL10n.public, detail: VectorL10n.roomAccessSettingsScreenPublicMessage, badgeText: nil) ] return } - self.accessItems = [ + accessItems = [ RoomAccessTypeChooserAccessItem(id: .private, isSelected: false, title: VectorL10n.private, detail: VectorL10n.roomAccessSettingsScreenPrivateMessage, badgeText: nil), RoomAccessTypeChooserAccessItem(id: .restricted, isSelected: false, title: VectorL10n.createRoomTypeRestricted, detail: VectorL10n.roomAccessSettingsScreenRestrictedMessage, badgeText: roomUpgradeRequired ? VectorL10n.roomAccessSettingsScreenUpgradeRequired : VectorL10n.roomAccessSettingsScreenEditSpaces), - RoomAccessTypeChooserAccessItem(id: .public, isSelected: false, title: VectorL10n.public, detail: VectorL10n.roomAccessSettingsScreenPublicMessage, badgeText: nil), + RoomAccessTypeChooserAccessItem(id: .public, isSelected: false, title: VectorL10n.public, detail: VectorL10n.roomAccessSettingsScreenPublicMessage, badgeText: nil) ] accessItemsSubject.send(accessItems) diff --git a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Service/Mock/MockRoomAccessTypeChooserService.swift b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Service/Mock/MockRoomAccessTypeChooserService.swift index 5bd115685..f0e4a3b11 100644 --- a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Service/Mock/MockRoomAccessTypeChooserService.swift +++ b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Service/Mock/MockRoomAccessTypeChooserService.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,15 +14,14 @@ // limitations under the License. // -import Foundation import Combine +import Foundation class MockRoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol { - static let mockAccessItems: [RoomAccessTypeChooserAccessItem] = [ RoomAccessTypeChooserAccessItem(id: .private, isSelected: true, title: VectorL10n.private, detail: VectorL10n.roomAccessSettingsScreenPrivateMessage, badgeText: nil), RoomAccessTypeChooserAccessItem(id: .restricted, isSelected: false, title: VectorL10n.createRoomTypeRestricted, detail: VectorL10n.roomAccessSettingsScreenRestrictedMessage, badgeText: VectorL10n.roomAccessSettingsScreenUpgradeRequired), - RoomAccessTypeChooserAccessItem(id: .public, isSelected: false, title: VectorL10n.public, detail: VectorL10n.roomAccessSettingsScreenPublicMessage, badgeText: nil), + RoomAccessTypeChooserAccessItem(id: .public, isSelected: false, title: VectorL10n.public, detail: VectorL10n.roomAccessSettingsScreenPublicMessage, badgeText: nil) ] private(set) var accessItemsSubject: CurrentValueSubject<[RoomAccessTypeChooserAccessItem], Never> @@ -31,9 +30,9 @@ class MockRoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol { private(set) var errorSubject: CurrentValueSubject private(set) var selectedType: RoomAccessTypeChooserAccessType = .private - var currentRoomId: String = "!aaabaa:matrix.org" + var currentRoomId = "!aaabaa:matrix.org" var versionOverride: String? { - return "9" + "9" } init(accessItems: [RoomAccessTypeChooserAccessItem] = mockAccessItems) { @@ -44,18 +43,14 @@ class MockRoomAccessTypeChooserService: RoomAccessTypeChooserServiceProtocol { } func simulateUpdate(accessItems: [RoomAccessTypeChooserAccessItem]) { - self.accessItemsSubject.send(accessItems) + accessItemsSubject.send(accessItems) } - func updateSelection(with selectedType: RoomAccessTypeChooserAccessType) { - - } + func updateSelection(with selectedType: RoomAccessTypeChooserAccessType) { } func updateRoomId(with roomId: String) { currentRoomId = roomId } - func applySelection(completion: @escaping () -> Void) { - - } + func applySelection(completion: @escaping () -> Void) { } } diff --git a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Service/RoomAccessTypeChooserServiceProtocol.swift b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Service/RoomAccessTypeChooserServiceProtocol.swift index b96bb2ad0..3f4935e6d 100644 --- a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Service/RoomAccessTypeChooserServiceProtocol.swift +++ b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Service/RoomAccessTypeChooserServiceProtocol.swift @@ -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 protocol RoomAccessTypeChooserServiceProtocol { var accessItemsSubject: CurrentValueSubject<[RoomAccessTypeChooserAccessItem], Never> { get } diff --git a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Test/UI/RoomAccessTypeChooserUITests.swift b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Test/UI/RoomAccessTypeChooserUITests.swift index d6f5b3dbb..d7203387b 100644 --- a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Test/UI/RoomAccessTypeChooserUITests.swift +++ b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Test/UI/RoomAccessTypeChooserUITests.swift @@ -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 RiotSwiftUI +import XCTest class RoomAccessTypeChooserUITests: MockScreenTestCase { // Tests to be implemented. diff --git a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Test/Unit/RoomAccessTypeChooserViewModelTests.swift b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Test/Unit/RoomAccessTypeChooserViewModelTests.swift index 7eda5de05..f7522b442 100644 --- a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Test/Unit/RoomAccessTypeChooserViewModelTests.swift +++ b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/Test/Unit/RoomAccessTypeChooserViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,11 +14,9 @@ // limitations under the License. // -import XCTest import Combine +import XCTest @testable import RiotSwiftUI -class RoomAccessTypeChooserViewModelTests: XCTestCase { - -} +class RoomAccessTypeChooserViewModelTests: XCTestCase { } diff --git a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/View/RoomAccessTypeChooser.swift b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/View/RoomAccessTypeChooser.swift index 9786273d3..f7d076d6d 100644 --- a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/View/RoomAccessTypeChooser.swift +++ b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/View/RoomAccessTypeChooser.swift @@ -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 RoomAccessTypeChooser: View { - // MARK: - Properties // MARK: Private @@ -55,7 +54,7 @@ struct RoomAccessTypeChooser: View { @ViewBuilder private var listContent: some View { - ScrollView{ + ScrollView { VStack(alignment: .leading) { Text(VectorL10n.roomAccessSettingsScreenTitle) .foregroundColor(theme.colors.primaryContent) @@ -84,7 +83,6 @@ struct RoomAccessTypeChooser: View { // MARK: - Previews struct RoomAccessTypeChooser_Previews: PreviewProvider { - static let stateRenderer = MockRoomAccessTypeChooserScreenState.stateRenderer static var previews: some View { stateRenderer.screenGroup(addNavigation: true) diff --git a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/View/RoomAccessTypeChooserRow.swift b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/View/RoomAccessTypeChooserRow.swift index a38cd0efe..b5b3776c1 100644 --- a/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/View/RoomAccessTypeChooserRow.swift +++ b/RiotSwiftUI/Modules/Room/RoomAccess/RoomAccessTypeChooser/View/RoomAccessTypeChooserRow.swift @@ -17,7 +17,6 @@ import SwiftUI struct RoomAccessTypeChooserRow: View { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Room/RoomAccess/RoomRestrictedAccessSpaceChooser/Coordinator/RoomRestrictedAccessSpaceChooserViewProvider.swift b/RiotSwiftUI/Modules/Room/RoomAccess/RoomRestrictedAccessSpaceChooser/Coordinator/RoomRestrictedAccessSpaceChooserViewProvider.swift index 389716a8f..fd1b5c71c 100644 --- a/RiotSwiftUI/Modules/Room/RoomAccess/RoomRestrictedAccessSpaceChooser/Coordinator/RoomRestrictedAccessSpaceChooserViewProvider.swift +++ b/RiotSwiftUI/Modules/Room/RoomAccess/RoomRestrictedAccessSpaceChooser/Coordinator/RoomRestrictedAccessSpaceChooserViewProvider.swift @@ -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 class RoomRestrictedAccessSpaceChooserViewProvider: MatrixItemChooserCoordinatorViewProvider { - private let navTitle: String? init(navTitle: String?) { @@ -25,6 +24,6 @@ class RoomRestrictedAccessSpaceChooserViewProvider: MatrixItemChooserCoordinator } func view(with viewModel: MatrixItemChooserViewModelType.Context) -> AnyView { - return AnyView(RoomRestrictedAccessSpaceChooserSelector(viewModel: viewModel, navTitle: navTitle)) + AnyView(RoomRestrictedAccessSpaceChooserSelector(viewModel: viewModel, navTitle: navTitle)) } } diff --git a/RiotSwiftUI/Modules/Room/RoomAccess/RoomRestrictedAccessSpaceChooser/Service/MatrixSDK/RoomRestrictedAccessSpaceChooserItemsProcessor.swift b/RiotSwiftUI/Modules/Room/RoomAccess/RoomRestrictedAccessSpaceChooser/Service/MatrixSDK/RoomRestrictedAccessSpaceChooserItemsProcessor.swift index 15d334091..679d41016 100644 --- a/RiotSwiftUI/Modules/Room/RoomAccess/RoomRestrictedAccessSpaceChooser/Service/MatrixSDK/RoomRestrictedAccessSpaceChooserItemsProcessor.swift +++ b/RiotSwiftUI/Modules/Room/RoomAccess/RoomRestrictedAccessSpaceChooser/Service/MatrixSDK/RoomRestrictedAccessSpaceChooserItemsProcessor.swift @@ -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 class RoomRestrictedAccessSpaceChooserItemsProcessor: MatrixItemChooserProcessorProtocol { - // MARK: Private private let roomId: String @@ -28,7 +27,7 @@ class RoomRestrictedAccessSpaceChooserItemsProcessor: MatrixItemChooserProcessor init(roomId: String, session: MXSession) { self.roomId = roomId self.session = session - self.dataSource = MatrixItemChooserRoomRestrictedAllowedParentsDataSource(roomId: roomId) + dataSource = MatrixItemChooserRoomRestrictedAllowedParentsDataSource(roomId: roomId) } // MARK: MatrixItemChooserSelectionProcessorProtocol @@ -50,7 +49,7 @@ class RoomRestrictedAccessSpaceChooserItemsProcessor: MatrixItemChooserProcessor } } - func isItemIncluded(_ item: (MatrixListItemData)) -> Bool { - return true + func isItemIncluded(_ item: MatrixListItemData) -> Bool { + true } } diff --git a/RiotSwiftUI/Modules/Room/RoomAccess/RoomRestrictedAccessSpaceChooser/View/RoomRestrictedAccessSpaceChooserSelector.swift b/RiotSwiftUI/Modules/Room/RoomAccess/RoomRestrictedAccessSpaceChooser/View/RoomRestrictedAccessSpaceChooserSelector.swift index 3b52c9e41..25019eb15 100644 --- a/RiotSwiftUI/Modules/Room/RoomAccess/RoomRestrictedAccessSpaceChooser/View/RoomRestrictedAccessSpaceChooserSelector.swift +++ b/RiotSwiftUI/Modules/Room/RoomAccess/RoomRestrictedAccessSpaceChooser/View/RoomRestrictedAccessSpaceChooserSelector.swift @@ -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 RoomRestrictedAccessSpaceChooserSelector: View { - // MARK: Properties @ObservedObject var viewModel: MatrixItemChooserViewModel.Context @@ -51,5 +50,4 @@ struct RoomRestrictedAccessSpaceChooserSelector: View { } } } - } diff --git a/RiotSwiftUI/Modules/Room/RoomSuggestion/Coordinator/RoomSuggestionCoordinator.swift b/RiotSwiftUI/Modules/Room/RoomSuggestion/Coordinator/RoomSuggestionCoordinator.swift index ffdfc5e3f..e18ca2bdf 100644 --- a/RiotSwiftUI/Modules/Room/RoomSuggestion/Coordinator/RoomSuggestionCoordinator.swift +++ b/RiotSwiftUI/Modules/Room/RoomSuggestion/Coordinator/RoomSuggestionCoordinator.swift @@ -24,7 +24,6 @@ enum RoomSuggestionCoordinatorCoordinatorAction { @objcMembers final class RoomSuggestionCoordinator: Coordinator { - // MARK: - Properties // MARK: Private @@ -32,7 +31,7 @@ final class RoomSuggestionCoordinator: Coordinator { private let parameters: RoomSuggestionCoordinatorParameters private var navigationRouter: NavigationRouterType { - return self.parameters.navigationRouter + parameters.navigationRouter } // MARK: Public @@ -46,31 +45,30 @@ final class RoomSuggestionCoordinator: Coordinator { init(parameters: RoomSuggestionCoordinatorParameters) { self.parameters = parameters - } + } // MARK: - Public - func start() { MXLog.debug("[RoomSuggestionCoordinator] did start.") - let rootCoordinator = self.createRoomSuggestionSpaceChooser() + let rootCoordinator = createRoomSuggestionSpaceChooser() 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 @@ -78,7 +76,7 @@ final class RoomSuggestionCoordinator: 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) }) @@ -91,7 +89,8 @@ final class RoomSuggestionCoordinator: Coordinator { title: VectorL10n.roomSuggestionSettingsScreenTitle, detail: VectorL10n.roomSuggestionSettingsScreenMessage, viewProvider: RoomSuggestionSpaceChooserViewProvider(navTitle: VectorL10n.roomAccessSettingsScreenNavTitle), - itemsProcessor: RoomSuggestionSpaceChooserItemsProcessor(roomId: parameters.room.roomId, session: parameters.room.mxSession)) + itemsProcessor: RoomSuggestionSpaceChooserItemsProcessor(roomId: parameters.room.roomId, session: parameters.room.mxSession) + ) let coordinator = MatrixItemChooserCoordinator(parameters: paramaters) coordinator.completion = { [weak self] result in guard let self = self else { return } @@ -107,5 +106,4 @@ final class RoomSuggestionCoordinator: Coordinator { } return coordinator } - } diff --git a/RiotSwiftUI/Modules/Room/RoomSuggestion/Coordinator/RoomSuggestionCoordinatorBridgePresenter.swift b/RiotSwiftUI/Modules/Room/RoomSuggestion/Coordinator/RoomSuggestionCoordinatorBridgePresenter.swift index a6bfa2ee5..7c1e71c02 100644 --- a/RiotSwiftUI/Modules/Room/RoomSuggestion/Coordinator/RoomSuggestionCoordinatorBridgePresenter.swift +++ b/RiotSwiftUI/Modules/Room/RoomSuggestion/Coordinator/RoomSuggestionCoordinatorBridgePresenter.swift @@ -26,7 +26,6 @@ import UIKit /// Each bridge should be removed once the underlying Coordinator has been integrated by another Coordinator. @objcMembers final class RoomSuggestionCoordinatorBridgePresenter: NSObject { - // MARK: - Properties // MARK: Private @@ -70,7 +69,7 @@ final class RoomSuggestionCoordinatorBridgePresenter: NSObject { } func dismiss(animated: Bool, completion: (() -> Void)?) { - guard let coordinator = self.coordinator else { + guard let coordinator = coordinator else { return } coordinator.toPresentable().dismiss(animated: animated) { @@ -86,9 +85,7 @@ final class RoomSuggestionCoordinatorBridgePresenter: NSObject { // MARK: - UIAdaptivePresentationControllerDelegate extension RoomSuggestionCoordinatorBridgePresenter: UIAdaptivePresentationControllerDelegate { - func roomNotificationSettingsCoordinatorDidComplete(_ presentationController: UIPresentationController) { - self.delegate?.roomSuggestionCoordinatorBridgePresenterDelegateDidCancel(self) + delegate?.roomSuggestionCoordinatorBridgePresenterDelegateDidCancel(self) } - } diff --git a/RiotSwiftUI/Modules/Room/RoomSuggestion/Coordinator/RoomSuggestionCoordinatorParameters.swift b/RiotSwiftUI/Modules/Room/RoomSuggestion/Coordinator/RoomSuggestionCoordinatorParameters.swift index 1ac2ce0eb..f3bc5580f 100644 --- a/RiotSwiftUI/Modules/Room/RoomSuggestion/Coordinator/RoomSuggestionCoordinatorParameters.swift +++ b/RiotSwiftUI/Modules/Room/RoomSuggestion/Coordinator/RoomSuggestionCoordinatorParameters.swift @@ -18,7 +18,6 @@ import Foundation /// RoomSuggestionCoordinator input parameters struct RoomSuggestionCoordinatorParameters { - /// The Matrix room let room: MXRoom diff --git a/RiotSwiftUI/Modules/Room/RoomSuggestion/RoomSuggestionSpaceChooser/Coordinator/RoomSuggestionSpaceChooserViewProvider.swift b/RiotSwiftUI/Modules/Room/RoomSuggestion/RoomSuggestionSpaceChooser/Coordinator/RoomSuggestionSpaceChooserViewProvider.swift index a5b261fd0..7c04225ee 100644 --- a/RiotSwiftUI/Modules/Room/RoomSuggestion/RoomSuggestionSpaceChooser/Coordinator/RoomSuggestionSpaceChooserViewProvider.swift +++ b/RiotSwiftUI/Modules/Room/RoomSuggestion/RoomSuggestionSpaceChooser/Coordinator/RoomSuggestionSpaceChooserViewProvider.swift @@ -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 class RoomSuggestionSpaceChooserViewProvider: MatrixItemChooserCoordinatorViewProvider { - private let navTitle: String? init(navTitle: String?) { @@ -25,6 +24,6 @@ class RoomSuggestionSpaceChooserViewProvider: MatrixItemChooserCoordinatorViewPr } func view(with viewModel: MatrixItemChooserViewModelType.Context) -> AnyView { - return AnyView(RoomSuggestionSpaceChooserSelector(viewModel: viewModel, navTitle: navTitle)) + AnyView(RoomSuggestionSpaceChooserSelector(viewModel: viewModel, navTitle: navTitle)) } } diff --git a/RiotSwiftUI/Modules/Room/RoomSuggestion/RoomSuggestionSpaceChooser/Service/MatrixSDK/RoomSuggestionSpaceChooserItemsProcessor.swift b/RiotSwiftUI/Modules/Room/RoomSuggestion/RoomSuggestionSpaceChooser/Service/MatrixSDK/RoomSuggestionSpaceChooserItemsProcessor.swift index 016e17dd1..6a8d664fc 100644 --- a/RiotSwiftUI/Modules/Room/RoomSuggestion/RoomSuggestionSpaceChooser/Service/MatrixSDK/RoomSuggestionSpaceChooserItemsProcessor.swift +++ b/RiotSwiftUI/Modules/Room/RoomSuggestion/RoomSuggestionSpaceChooser/Service/MatrixSDK/RoomSuggestionSpaceChooserItemsProcessor.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,7 +22,6 @@ public enum RoomSuggestionSpaceChooserItemsProcessorError: Int, Error { } class RoomSuggestionSpaceChooserItemsProcessor: MatrixItemChooserProcessorProtocol { - // MARK: Private private let roomId: String @@ -35,7 +34,7 @@ class RoomSuggestionSpaceChooserItemsProcessor: MatrixItemChooserProcessorProtoc init(roomId: String, session: MXSession) { self.roomId = roomId self.session = session - self.dataSource = MatrixItemChooserRoomDirectParentsDataSource(roomId: roomId, preselectionMode: .suggestedRoom) + dataSource = MatrixItemChooserRoomDirectParentsDataSource(roomId: roomId, preselectionMode: .suggestedRoom) } deinit { @@ -43,6 +42,7 @@ class RoomSuggestionSpaceChooserItemsProcessor: MatrixItemChooserProcessorProtoc NotificationCenter.default.removeObserver(observer) } } + // MARK: MatrixItemChooserSelectionProcessorProtocol private(set) var dataSource: MatrixItemChooserDataSource @@ -53,11 +53,11 @@ class RoomSuggestionSpaceChooserItemsProcessor: MatrixItemChooserProcessorProtoc let unselectedItems: [String] let selectedItems: [String] if let preselectedItems = dataSource.preselectedItemIds { - unselectedItems = preselectedItems.compactMap({ itemId in - return !itemsIds.contains(itemId) ? itemId : nil - }) + unselectedItems = preselectedItems.compactMap { itemId in + !itemsIds.contains(itemId) ? itemId : nil + } selectedItems = itemsIds.compactMap { itemId in - return !preselectedItems.contains(itemId) ? itemId : nil + !preselectedItems.contains(itemId) ? itemId : nil } } else { unselectedItems = [] @@ -78,7 +78,7 @@ class RoomSuggestionSpaceChooserItemsProcessor: MatrixItemChooserProcessorProtoc if let firstError = self.computationErrorList.first { completion(.failure(firstError)) } else { - self.didBuildSpaceGraphObserver = NotificationCenter.default.addObserver(forName: MXSpaceService.didBuildSpaceGraph, object: nil, queue: OperationQueue.main) { [weak self] notification in + self.didBuildSpaceGraphObserver = NotificationCenter.default.addObserver(forName: MXSpaceService.didBuildSpaceGraph, object: nil, queue: OperationQueue.main) { [weak self] _ in guard let self = self else { return } if let observer = self.didBuildSpaceGraphObserver { @@ -93,8 +93,8 @@ class RoomSuggestionSpaceChooserItemsProcessor: MatrixItemChooserProcessorProtoc } } - func isItemIncluded(_ item: (MatrixListItemData)) -> Bool { - return true + func isItemIncluded(_ item: MatrixListItemData) -> Bool { + true } // MARK: - Private diff --git a/RiotSwiftUI/Modules/Room/RoomSuggestion/RoomSuggestionSpaceChooser/View/RoomSuggestionSpaceChooserSelector.swift b/RiotSwiftUI/Modules/Room/RoomSuggestion/RoomSuggestionSpaceChooser/View/RoomSuggestionSpaceChooserSelector.swift index d0c1e4e28..4b2f5d2bc 100644 --- a/RiotSwiftUI/Modules/Room/RoomSuggestion/RoomSuggestionSpaceChooser/View/RoomSuggestionSpaceChooserSelector.swift +++ b/RiotSwiftUI/Modules/Room/RoomSuggestion/RoomSuggestionSpaceChooser/View/RoomSuggestionSpaceChooserSelector.swift @@ -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 RoomSuggestionSpaceChooserSelector: View { - // MARK: Properties @ObservedObject var viewModel: MatrixItemChooserViewModel.Context @@ -48,5 +47,4 @@ struct RoomSuggestionSpaceChooserSelector: View { } } } - } diff --git a/RiotSwiftUI/Modules/Room/RoomUpgrade/Coordinator/RoomUpgradeCoordinator.swift b/RiotSwiftUI/Modules/Room/RoomUpgrade/Coordinator/RoomUpgradeCoordinator.swift index fec7cd3e0..bc89e53cb 100644 --- a/RiotSwiftUI/Modules/Room/RoomUpgrade/Coordinator/RoomUpgradeCoordinator.swift +++ b/RiotSwiftUI/Modules/Room/RoomUpgrade/Coordinator/RoomUpgradeCoordinator.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import SwiftUI import MatrixSDK +import SwiftUI struct RoomUpgradeCoordinatorParameters { let session: MXSession @@ -25,7 +25,6 @@ struct RoomUpgradeCoordinatorParameters { } final class RoomUpgradeCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -53,6 +52,7 @@ final class RoomUpgradeCoordinator: Coordinator, Presentable { } // MARK: - Public + func start() { MXLog.debug("[RoomUpgradeCoordinator] did start.") roomUpgradeViewModel.completion = { [weak self] result in @@ -68,6 +68,6 @@ final class RoomUpgradeCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.roomUpgradeHostingController + roomUpgradeHostingController } } diff --git a/RiotSwiftUI/Modules/Room/RoomUpgrade/MockRoomUpgradeScreenState.swift b/RiotSwiftUI/Modules/Room/RoomUpgrade/MockRoomUpgradeScreenState.swift index 0052fd05b..bca1f0ea7 100644 --- a/RiotSwiftUI/Modules/Room/RoomUpgrade/MockRoomUpgradeScreenState.swift +++ b/RiotSwiftUI/Modules/Room/RoomUpgrade/MockRoomUpgradeScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,7 +36,7 @@ enum MockRoomUpgradeScreenState: MockScreenState, CaseIterable { } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let service: MockRoomUpgradeService switch self { case .initial: diff --git a/RiotSwiftUI/Modules/Room/RoomUpgrade/RoomUpgradeModels.swift b/RiotSwiftUI/Modules/Room/RoomUpgrade/RoomUpgradeModels.swift index 6d74a7f30..37966272e 100644 --- a/RiotSwiftUI/Modules/Room/RoomUpgrade/RoomUpgradeModels.swift +++ b/RiotSwiftUI/Modules/Room/RoomUpgrade/RoomUpgradeModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Room/RoomUpgrade/RoomUpgradeViewModel.swift b/RiotSwiftUI/Modules/Room/RoomUpgrade/RoomUpgradeViewModel.swift index 4a8b876d2..c61dd0323 100644 --- a/RiotSwiftUI/Modules/Room/RoomUpgrade/RoomUpgradeViewModel.swift +++ b/RiotSwiftUI/Modules/Room/RoomUpgrade/RoomUpgradeViewModel.swift @@ -14,14 +14,13 @@ // limitations under the License. // -import SwiftUI import Combine +import SwiftUI typealias RoomUpgradeViewModelType = StateStoreViewModel + Never, + RoomUpgradeViewAction> class RoomUpgradeViewModel: RoomUpgradeViewModelType, RoomUpgradeViewModelProtocol { - // MARK: - Properties // MARK: Private @@ -35,7 +34,7 @@ class RoomUpgradeViewModel: RoomUpgradeViewModelType, RoomUpgradeViewModelProtoc // MARK: - Setup static func makeRoomUpgradeViewModel(roomUpgradeService: RoomUpgradeServiceProtocol) -> RoomUpgradeViewModelProtocol { - return RoomUpgradeViewModel(roomUpgradeService: roomUpgradeService) + RoomUpgradeViewModel(roomUpgradeService: roomUpgradeService) } private init(roomUpgradeService: RoomUpgradeServiceProtocol) { @@ -45,7 +44,7 @@ class RoomUpgradeViewModel: RoomUpgradeViewModelType, RoomUpgradeViewModelProtoc } private static func defaultState(roomUpgradeService: RoomUpgradeServiceProtocol) -> RoomUpgradeViewState { - return RoomUpgradeViewState(waitingMessage: nil, isLoading: false, parentSpaceName: roomUpgradeService.parentSpaceName) + RoomUpgradeViewState(waitingMessage: nil, isLoading: false, parentSpaceName: roomUpgradeService.parentSpaceName) } private func setupObservers() { @@ -53,7 +52,7 @@ class RoomUpgradeViewModel: RoomUpgradeViewModelType, RoomUpgradeViewModelProtoc .upgradingSubject .sink { [weak self] isUpgrading in self?.state.isLoading = isUpgrading - self?.state.waitingMessage = isUpgrading ? VectorL10n.roomAccessSettingsScreenUpgradeAlertUpgrading: nil + self?.state.waitingMessage = isUpgrading ? VectorL10n.roomAccessSettingsScreenUpgradeAlertUpgrading : nil } .store(in: &cancellables) } @@ -65,7 +64,7 @@ class RoomUpgradeViewModel: RoomUpgradeViewModelType, RoomUpgradeViewModelProtoc case .cancel: completion?(.cancel(roomUpgradeService.currentRoomId)) case .done(let autoInviteUsers): - roomUpgradeService.upgradeRoom(autoInviteUsers: autoInviteUsers) { [weak self] success, roomId in + roomUpgradeService.upgradeRoom(autoInviteUsers: autoInviteUsers) { [weak self] success, _ in guard let self = self else { return } if success { self.completion?(.done(self.roomUpgradeService.currentRoomId)) diff --git a/RiotSwiftUI/Modules/Room/RoomUpgrade/RoomUpgradeViewModelProtocol.swift b/RiotSwiftUI/Modules/Room/RoomUpgrade/RoomUpgradeViewModelProtocol.swift index eb6136d1d..e9dcefdaa 100644 --- a/RiotSwiftUI/Modules/Room/RoomUpgrade/RoomUpgradeViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Room/RoomUpgrade/RoomUpgradeViewModelProtocol.swift @@ -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 RoomUpgradeViewModelProtocol { - var completion: ((RoomUpgradeViewModelResult) -> Void)? { get set } static func makeRoomUpgradeViewModel(roomUpgradeService: RoomUpgradeServiceProtocol) -> RoomUpgradeViewModelProtocol var context: RoomUpgradeViewModelType.Context { get } diff --git a/RiotSwiftUI/Modules/Room/RoomUpgrade/Service/MatrixSDK/RoomUpgradeService.swift b/RiotSwiftUI/Modules/Room/RoomUpgrade/Service/MatrixSDK/RoomUpgradeService.swift index 02d9b5b9f..adc01c5ee 100644 --- a/RiotSwiftUI/Modules/Room/RoomUpgrade/Service/MatrixSDK/RoomUpgradeService.swift +++ b/RiotSwiftUI/Modules/Room/RoomUpgrade/Service/MatrixSDK/RoomUpgradeService.swift @@ -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 RoomUpgradeService: RoomUpgradeServiceProtocol { - // MARK: - Properties // MARK: Private @@ -37,7 +36,7 @@ class RoomUpgradeService: RoomUpgradeServiceProtocol { private(set) var currentRoomId: String var parentSpaceName: String? { - guard let parentId = self.parentSpaceId else { + guard let parentId = parentSpaceId else { return nil } @@ -53,11 +52,11 @@ class RoomUpgradeService: RoomUpgradeServiceProtocol { init(session: MXSession, roomId: String, parentSpaceId: String?, versionOverride: String) { self.session = session - self.currentRoomId = roomId + currentRoomId = roomId self.parentSpaceId = parentSpaceId self.versionOverride = versionOverride - self.upgradingSubject = CurrentValueSubject(false) - self.errorSubject = CurrentValueSubject(nil) + upgradingSubject = CurrentValueSubject(false) + errorSubject = CurrentValueSubject(nil) } deinit { @@ -70,18 +69,18 @@ class RoomUpgradeService: RoomUpgradeServiceProtocol { func upgradeRoom(autoInviteUsers: Bool, completion: @escaping (Bool, String) -> Void) { upgradingSubject.send(true) - if autoInviteUsers, let room = session.room(withRoomId: self.currentRoomId) { - self.currentOperation = room.members { [weak self] response in + if autoInviteUsers, let room = session.room(withRoomId: currentRoomId) { + currentOperation = room.members { [weak self] response in guard let self = self else { return } switch response { case .success(let members): - let memberIds: [String] = members?.members.compactMap({ member in + let memberIds: [String] = members?.members.compactMap { member in guard member.membership == .join, member.userId != self.session.myUserId else { return nil } return member.userId - }) ?? [] + } ?? [] self.upgradeRoom(to: self.versionOverride, inviteUsers: memberIds, completion: completion) case .failure(let error): self.upgradingSubject.send(false) @@ -89,7 +88,7 @@ class RoomUpgradeService: RoomUpgradeServiceProtocol { } } } else { - self.upgradeRoom(to: versionOverride, inviteUsers: [], completion: completion) + upgradeRoom(to: versionOverride, inviteUsers: [], completion: completion) } } @@ -98,7 +97,7 @@ class RoomUpgradeService: RoomUpgradeServiceProtocol { private func upgradeRoom(to versionOverride: String, inviteUsers userIds: [String], completion: @escaping (Bool, String) -> Void) { // Need to disable graph update during this process as a lot of syncs will occure session.spaceService.graphUpdateEnabled = false - currentOperation = session.matrixRestClient.upgradeRoom(withId: self.currentRoomId, to: versionOverride) { [weak self] response in + currentOperation = session.matrixRestClient.upgradeRoom(withId: currentRoomId, to: versionOverride) { [weak self] response in guard let self = self else { return } switch response { @@ -108,7 +107,7 @@ class RoomUpgradeService: RoomUpgradeServiceProtocol { let parentSpaces = self.session.spaceService.directParentIds(ofRoomWithId: oldRoomId) self.moveRoom(from: oldRoomId, to: replacementRoomId, within: Array(parentSpaces), at: 0) { self.session.spaceService.graphUpdateEnabled = true - self.didBuildSpaceGraphObserver = NotificationCenter.default.addObserver(forName: MXSpaceService.didBuildSpaceGraph, object: nil, queue: OperationQueue.main) { [weak self] notification in + self.didBuildSpaceGraphObserver = NotificationCenter.default.addObserver(forName: MXSpaceService.didBuildSpaceGraph, object: nil, queue: OperationQueue.main) { [weak self] _ in guard let self = self else { return } if let observer = self.didBuildSpaceGraphObserver { @@ -144,7 +143,7 @@ class RoomUpgradeService: RoomUpgradeServiceProtocol { } space.moveChild(withRoomId: roomId, to: newRoomId) { [weak self] response in - guard let self = self else { return } + guard let self = self else { return } if let error = response.error { MXLog.warning("[RoomUpgradeService] moveRoom \(roomId) to \(newRoomId) within \(space.spaceId): failed due to error: \(error)") @@ -158,13 +157,13 @@ class RoomUpgradeService: RoomUpgradeServiceProtocol { /// Recurse to the next index once done. private func inviteUser(from userIds: [String], at index: Int, completion: @escaping (Bool, String) -> Void) { guard index < userIds.count else { - self.upgradingSubject.send(false) + upgradingSubject.send(false) completion(true, currentRoomId) return } currentOperation = session.matrixRestClient.invite(.userId(userIds[index]), toRoom: currentRoomId) { [weak self] response in - guard let self = self else { return } + guard let self = self else { return } self.currentOperation = nil if let error = response.error { diff --git a/RiotSwiftUI/Modules/Room/RoomUpgrade/Service/Mock/MockRoomUpgradeService.swift b/RiotSwiftUI/Modules/Room/RoomUpgrade/Service/Mock/MockRoomUpgradeService.swift index a31619875..aed04fc38 100644 --- a/RiotSwiftUI/Modules/Room/RoomUpgrade/Service/Mock/MockRoomUpgradeService.swift +++ b/RiotSwiftUI/Modules/Room/RoomUpgrade/Service/Mock/MockRoomUpgradeService.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,24 +14,22 @@ // limitations under the License. // -import Foundation import Combine +import Foundation class MockRoomUpgradeService: RoomUpgradeServiceProtocol { - var currentRoomId: String = "!sfdlksjdflkfjds:matrix.org" + var currentRoomId = "!sfdlksjdflkfjds:matrix.org" var errorSubject: CurrentValueSubject var upgradingSubject: CurrentValueSubject var parentSpaceName: String? { - return "Parent space name" + "Parent space name" } init() { - self.errorSubject = CurrentValueSubject(nil) - self.upgradingSubject = CurrentValueSubject(false) + errorSubject = CurrentValueSubject(nil) + upgradingSubject = CurrentValueSubject(false) } - func upgradeRoom(autoInviteUsers: Bool, completion: @escaping (Bool, String) -> Void) { - - } + func upgradeRoom(autoInviteUsers: Bool, completion: @escaping (Bool, String) -> Void) { } } diff --git a/RiotSwiftUI/Modules/Room/RoomUpgrade/Service/RoomUpgradeServiceProtocol.swift b/RiotSwiftUI/Modules/Room/RoomUpgrade/Service/RoomUpgradeServiceProtocol.swift index 49cba3100..20a096d7c 100644 --- a/RiotSwiftUI/Modules/Room/RoomUpgrade/Service/RoomUpgradeServiceProtocol.swift +++ b/RiotSwiftUI/Modules/Room/RoomUpgrade/Service/RoomUpgradeServiceProtocol.swift @@ -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 protocol RoomUpgradeServiceProtocol { var currentRoomId: String { get } diff --git a/RiotSwiftUI/Modules/Room/RoomUpgrade/Test/UI/RoomUpgradeUITests.swift b/RiotSwiftUI/Modules/Room/RoomUpgrade/Test/UI/RoomUpgradeUITests.swift index 5b59c1c5d..011e870ce 100644 --- a/RiotSwiftUI/Modules/Room/RoomUpgrade/Test/UI/RoomUpgradeUITests.swift +++ b/RiotSwiftUI/Modules/Room/RoomUpgrade/Test/UI/RoomUpgradeUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class RoomUpgradeUITests: MockScreenTestCase { // Tests to be implemented. diff --git a/RiotSwiftUI/Modules/Room/RoomUpgrade/Test/Unit/RoomUpgradeViewModelTests.swift b/RiotSwiftUI/Modules/Room/RoomUpgrade/Test/Unit/RoomUpgradeViewModelTests.swift index 41cf7f572..19f2cfc72 100644 --- a/RiotSwiftUI/Modules/Room/RoomUpgrade/Test/Unit/RoomUpgradeViewModelTests.swift +++ b/RiotSwiftUI/Modules/Room/RoomUpgrade/Test/Unit/RoomUpgradeViewModelTests.swift @@ -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 @@ -24,7 +24,5 @@ class RoomUpgradeViewModelTests: XCTestCase { var viewModel: RoomUpgradeViewModelProtocol! var context: RoomUpgradeViewModelType.Context! - override func setUpWithError() throws { - } - + override func setUpWithError() throws { } } diff --git a/RiotSwiftUI/Modules/Room/RoomUpgrade/View/RoomUpgrade.swift b/RiotSwiftUI/Modules/Room/RoomUpgrade/View/RoomUpgrade.swift index 83eb51991..76c096531 100644 --- a/RiotSwiftUI/Modules/Room/RoomUpgrade/View/RoomUpgrade.swift +++ b/RiotSwiftUI/Modules/Room/RoomUpgrade/View/RoomUpgrade.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,10 +17,9 @@ import SwiftUI struct RoomUpgrade: View { - // MARK: - Properties - @State var autoInviteUsers: Bool = true + @State var autoInviteUsers = true // MARK: Private @@ -86,13 +85,13 @@ struct RoomUpgrade: View { .padding(.horizontal, 24) .padding(.vertical, 16) } - .background(RoundedRectangle.init(cornerRadius: 8).foregroundColor(theme.colors.background)) + .background(RoundedRectangle(cornerRadius: 8).foregroundColor(theme.colors.background)) .padding(.horizontal, 20) .frame(minWidth: 0, maxWidth: 500) } private func noteText(_ message: String) -> some View { - return Text(message) + Text(message) .multilineTextAlignment(.center) .font(theme.fonts.subheadline) .foregroundColor(theme.colors.secondaryContent) diff --git a/RiotSwiftUI/Modules/Room/TimelinePoll/Coordinator/TimelinePollCoordinator.swift b/RiotSwiftUI/Modules/Room/TimelinePoll/Coordinator/TimelinePollCoordinator.swift index 7bdbcb77d..a587b23d8 100644 --- a/RiotSwiftUI/Modules/Room/TimelinePoll/Coordinator/TimelinePollCoordinator.swift +++ b/RiotSwiftUI/Modules/Room/TimelinePoll/Coordinator/TimelinePollCoordinator.swift @@ -14,9 +14,9 @@ // limitations under the License. // -import SwiftUI -import MatrixSDK import Combine +import MatrixSDK +import SwiftUI struct TimelinePollCoordinatorParameters { let session: MXSession @@ -25,7 +25,6 @@ struct TimelinePollCoordinatorParameters { } final class TimelinePollCoordinator: Coordinator, Presentable, PollAggregatorDelegate { - // MARK: - Properties // MARK: Private @@ -81,25 +80,24 @@ final class TimelinePollCoordinator: Coordinator, Presentable, PollAggregatorDel } // MARK: - Public - func start() { - - } + + func start() { } func toPresentable() -> UIViewController { - return VectorHostingController(rootView: TimelinePollView(viewModel: viewModel.context), - forceZeroSafeAreaInsets: true) + VectorHostingController(rootView: TimelinePollView(viewModel: viewModel.context), + forceZeroSafeAreaInsets: true) } func canEndPoll() -> Bool { - return pollAggregator.poll.isClosed == false + pollAggregator.poll.isClosed == false } func canEditPoll() -> Bool { - return pollAggregator.poll.isClosed == false && pollAggregator.poll.totalAnswerCount == 0 + pollAggregator.poll.isClosed == false && pollAggregator.poll.totalAnswerCount == 0 } func endPoll() { - parameters.room.sendPollEnd(for: parameters.pollStartEvent, threadId: nil, localEcho: nil, success: nil) { [weak self] error in + parameters.room.sendPollEnd(for: parameters.pollStartEvent, threadId: nil, localEcho: nil, success: nil) { [weak self] _ in self?.viewModel.showClosingFailure() } } @@ -110,17 +108,11 @@ final class TimelinePollCoordinator: Coordinator, Presentable, PollAggregatorDel viewModel.updateWithPollDetails(buildTimelinePollFrom(aggregator.poll)) } - func pollAggregatorDidStartLoading(_ aggregator: PollAggregator) { - - } + func pollAggregatorDidStartLoading(_ aggregator: PollAggregator) { } - func pollAggregatorDidEndLoading(_ aggregator: PollAggregator) { - - } + func pollAggregatorDidEndLoading(_ aggregator: PollAggregator) { } - func pollAggregator(_ aggregator: PollAggregator, didFailWithError: Error) { - - } + func pollAggregator(_ aggregator: PollAggregator, didFailWithError: Error) { } // MARK: - Private @@ -129,19 +121,19 @@ final class TimelinePollCoordinator: Coordinator, Presentable, PollAggregatorDel func buildTimelinePollFrom(_ poll: PollProtocol) -> TimelinePollDetails { let answerOptions = poll.answerOptions.map { pollAnswerOption in TimelinePollAnswerOption(id: pollAnswerOption.id, - text: pollAnswerOption.text, - count: pollAnswerOption.count, - winner: pollAnswerOption.isWinner, - selected: pollAnswerOption.isCurrentUserSelection) + text: pollAnswerOption.text, + count: pollAnswerOption.count, + winner: pollAnswerOption.isWinner, + selected: pollAnswerOption.isCurrentUserSelection) } return TimelinePollDetails(question: poll.text, - answerOptions: answerOptions, - closed: poll.isClosed, - totalAnswerCount: poll.totalAnswerCount, - type: pollKindToTimelinePollType(poll.kind), - maxAllowedSelections: poll.maxAllowedSelections, - hasBeenEdited: poll.hasBeenEdited) + answerOptions: answerOptions, + closed: poll.isClosed, + totalAnswerCount: poll.totalAnswerCount, + type: pollKindToTimelinePollType(poll.kind), + maxAllowedSelections: poll.maxAllowedSelections, + hasBeenEdited: poll.hasBeenEdited) } private func pollKindToTimelinePollType(_ kind: PollKind) -> TimelinePollType { diff --git a/RiotSwiftUI/Modules/Room/TimelinePoll/Coordinator/TimelinePollProvider.swift b/RiotSwiftUI/Modules/Room/TimelinePoll/Coordinator/TimelinePollProvider.swift index d40e86757..78b1d8ab7 100644 --- a/RiotSwiftUI/Modules/Room/TimelinePoll/Coordinator/TimelinePollProvider.swift +++ b/RiotSwiftUI/Modules/Room/TimelinePoll/Coordinator/TimelinePollProvider.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,9 +22,7 @@ class TimelinePollProvider { var session: MXSession? var coordinatorsForEventIdentifiers = [String: TimelinePollCoordinator]() - private init() { - - } + private init() { } /// Create or retrieve the poll timeline coordinator for this event and return /// a view to be displayed in the timeline @@ -49,6 +47,6 @@ class TimelinePollProvider { /// Retrieve the poll timeline coordinator for the given event or nil if it hasn't been created yet func timelinePollCoordinatorForEventIdentifier(_ eventIdentifier: String) -> TimelinePollCoordinator? { - return coordinatorsForEventIdentifiers[eventIdentifier] + coordinatorsForEventIdentifiers[eventIdentifier] } } diff --git a/RiotSwiftUI/Modules/Room/TimelinePoll/Test/UI/TimelinePollUITests.swift b/RiotSwiftUI/Modules/Room/TimelinePoll/Test/UI/TimelinePollUITests.swift index 98b520ea7..5e7eaceef 100644 --- a/RiotSwiftUI/Modules/Room/TimelinePoll/Test/UI/TimelinePollUITests.swift +++ b/RiotSwiftUI/Modules/Room/TimelinePoll/Test/UI/TimelinePollUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class TimelinePollUITests: MockScreenTestCase { func testOpenDisclosedPoll() { diff --git a/RiotSwiftUI/Modules/Room/TimelinePoll/Test/Unit/TimelinePollViewModelTests.swift b/RiotSwiftUI/Modules/Room/TimelinePoll/Test/Unit/TimelinePollViewModelTests.swift index 247f35b0d..0e102dc39 100644 --- a/RiotSwiftUI/Modules/Room/TimelinePoll/Test/Unit/TimelinePollViewModelTests.swift +++ b/RiotSwiftUI/Modules/Room/TimelinePoll/Test/Unit/TimelinePollViewModelTests.swift @@ -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 diff --git a/RiotSwiftUI/Modules/Room/TimelinePoll/TimelinePollModels.swift b/RiotSwiftUI/Modules/Room/TimelinePoll/TimelinePollModels.swift index 619088c25..528ad7c17 100644 --- a/RiotSwiftUI/Modules/Room/TimelinePoll/TimelinePollModels.swift +++ b/RiotSwiftUI/Modules/Room/TimelinePoll/TimelinePollModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,7 @@ import Foundation import SwiftUI -typealias TimelinePollViewModelCallback = ((TimelinePollViewModelResult) -> Void) +typealias TimelinePollViewModelCallback = (TimelinePollViewModelResult) -> Void enum TimelinePollViewAction { case selectAnswerOptionWithIdentifier(String) @@ -63,7 +63,7 @@ struct TimelinePollDetails { var totalAnswerCount: UInt var type: TimelinePollType var maxAllowedSelections: UInt - var hasBeenEdited: Bool = true + var hasBeenEdited = true init(question: String, answerOptions: [TimelinePollAnswerOption], closed: Bool, @@ -81,7 +81,7 @@ struct TimelinePollDetails { } var hasCurrentUserVoted: Bool { - answerOptions.filter { $0.selected == true}.count > 0 + answerOptions.filter { $0.selected == true }.count > 0 } var shouldDiscloseResults: Bool { diff --git a/RiotSwiftUI/Modules/Room/TimelinePoll/TimelinePollScreenState.swift b/RiotSwiftUI/Modules/Room/TimelinePoll/TimelinePollScreenState.swift index 0ac107a6e..01fb82c4a 100644 --- a/RiotSwiftUI/Modules/Room/TimelinePoll/TimelinePollScreenState.swift +++ b/RiotSwiftUI/Modules/Room/TimelinePoll/TimelinePollScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,16 +27,16 @@ enum MockTimelinePollScreenState: MockScreenState, CaseIterable { TimelinePollDetails.self } - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let answerOptions = [TimelinePollAnswerOption(id: "1", text: "First", count: 10, winner: false, selected: false), TimelinePollAnswerOption(id: "2", text: "Second", count: 5, winner: false, selected: true), TimelinePollAnswerOption(id: "3", text: "Third", count: 15, winner: true, selected: false)] let poll = TimelinePollDetails(question: "Question", answerOptions: answerOptions, - closed: (self == .closedDisclosed || self == .closedUndisclosed ? true : false), + closed: self == .closedDisclosed || self == .closedUndisclosed ? true : false, totalAnswerCount: 20, - type: (self == .closedDisclosed || self == .openDisclosed ? .disclosed : .undisclosed), + type: self == .closedDisclosed || self == .openDisclosed ? .disclosed : .undisclosed, maxAllowedSelections: 1, hasBeenEdited: false) diff --git a/RiotSwiftUI/Modules/Room/TimelinePoll/TimelinePollViewModel.swift b/RiotSwiftUI/Modules/Room/TimelinePoll/TimelinePollViewModel.swift index 99d15980c..e39ce8cbd 100644 --- a/RiotSwiftUI/Modules/Room/TimelinePoll/TimelinePollViewModel.swift +++ b/RiotSwiftUI/Modules/Room/TimelinePoll/TimelinePollViewModel.swift @@ -14,14 +14,13 @@ // limitations under the License. // -import SwiftUI import Combine +import SwiftUI typealias TimelinePollViewModelType = StateStoreViewModel + Never, + TimelinePollViewAction> class TimelinePollViewModel: TimelinePollViewModelType, TimelinePollViewModelProtocol { - // MARK: - Properties // MARK: Private @@ -40,14 +39,13 @@ class TimelinePollViewModel: TimelinePollViewModelType, TimelinePollViewModelPro override func process(viewAction: TimelinePollViewAction) { switch viewAction { - // Update local state. An update will be pushed from the coordinator once sent. case .selectAnswerOptionWithIdentifier(let identifier): guard !state.poll.closed else { return } - if (state.poll.maxAllowedSelections == 1) { + if state.poll.maxAllowedSelections == 1 { updateSingleSelectPollLocalState(selectedAnswerIdentifier: identifier, callback: completion) } else { updateMultiSelectPollLocalState(&state, selectedAnswerIdentifier: identifier, callback: completion) @@ -98,12 +96,12 @@ class TimelinePollViewModel: TimelinePollViewModelType, TimelinePollViewModelPro let isDeselecting = selectedAnswerOptions.filter { $0.id == selectedAnswerIdentifier }.count > 0 - if !isDeselecting && selectedAnswerOptions.count >= state.poll.maxAllowedSelections { + if !isDeselecting, selectedAnswerOptions.count >= state.poll.maxAllowedSelections { return } state.poll.answerOptions.updateEach { answerOption in - if (answerOption.id != selectedAnswerIdentifier) { + if answerOption.id != selectedAnswerIdentifier { return } diff --git a/RiotSwiftUI/Modules/Room/TimelinePoll/TimelinePollViewModelProtocol.swift b/RiotSwiftUI/Modules/Room/TimelinePoll/TimelinePollViewModelProtocol.swift index 7bd9184eb..492f7f7a3 100644 --- a/RiotSwiftUI/Modules/Room/TimelinePoll/TimelinePollViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Room/TimelinePoll/TimelinePollViewModelProtocol.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Room/TimelinePoll/View/TimelinePollAnswerOptionButton.swift b/RiotSwiftUI/Modules/Room/TimelinePoll/View/TimelinePollAnswerOptionButton.swift index 5a3498aa9..aaaba7c37 100644 --- a/RiotSwiftUI/Modules/Room/TimelinePoll/View/TimelinePollAnswerOptionButton.swift +++ b/RiotSwiftUI/Modules/Room/TimelinePoll/View/TimelinePollAnswerOptionButton.swift @@ -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 TimelinePollAnswerOptionButton: View { - // MARK: - Properties // MARK: Private @@ -47,7 +46,6 @@ struct TimelinePollAnswerOptionButton: View { var answerOptionLabel: some View { VStack(alignment: .leading, spacing: 12.0) { HStack(alignment: .top, spacing: 8.0) { - if !poll.closed { Image(uiImage: answerOption.selected ? Asset.Images.pollCheckboxSelected.image : Asset.Images.pollCheckboxDefault.image) } @@ -56,7 +54,7 @@ struct TimelinePollAnswerOptionButton: View { .font(theme.fonts.body) .foregroundColor(theme.colors.primaryContent) - if poll.closed && answerOption.winner { + if poll.closed, answerOption.winner { Spacer() Image(uiImage: Asset.Images.pollWinnerIcon.image) } @@ -69,7 +67,7 @@ struct TimelinePollAnswerOptionButton: View { .progressViewStyle(LinearProgressViewStyle()) .scaleEffect(x: 1.0, y: 1.2, anchor: .center) - if (poll.shouldDiscloseResults) { + if poll.shouldDiscloseResults { Text(answerOption.count == 1 ? VectorL10n.pollTimelineOneVote : VectorL10n.pollTimelineVotesCount(Int(answerOption.count))) .font(theme.fonts.footnote) .foregroundColor(poll.closed && answerOption.winner ? theme.colors.accent : theme.colors.secondaryContent) @@ -107,33 +105,33 @@ struct TimelinePollAnswerOptionButton_Previews: PreviewProvider { VStack { TimelinePollAnswerOptionButton(poll: buildPoll(closed: false, type: type), answerOption: buildAnswerOption(selected: false), - action: {}) + action: { }) TimelinePollAnswerOptionButton(poll: buildPoll(closed: false, type: type), answerOption: buildAnswerOption(selected: true), - action: {}) + action: { }) TimelinePollAnswerOptionButton(poll: buildPoll(closed: true, type: type), answerOption: buildAnswerOption(selected: false, winner: false), - action: {}) + action: { }) TimelinePollAnswerOptionButton(poll: buildPoll(closed: true, type: type), answerOption: buildAnswerOption(selected: false, winner: true), - action: {}) + action: { }) TimelinePollAnswerOptionButton(poll: buildPoll(closed: true, type: type), answerOption: buildAnswerOption(selected: true, winner: false), - action: {}) + action: { }) TimelinePollAnswerOptionButton(poll: buildPoll(closed: true, type: type), answerOption: buildAnswerOption(selected: true, winner: true), - action: {}) + action: { }) let longText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." TimelinePollAnswerOptionButton(poll: buildPoll(closed: true, type: type), answerOption: buildAnswerOption(text: longText, selected: true, winner: true), - action: {}) + action: { }) } } } @@ -141,12 +139,12 @@ struct TimelinePollAnswerOptionButton_Previews: PreviewProvider { static func buildPoll(closed: Bool, type: TimelinePollType) -> TimelinePollDetails { TimelinePollDetails(question: "", - answerOptions: [], - closed: closed, - totalAnswerCount: 100, - type: type, - maxAllowedSelections: 1, - hasBeenEdited: false) + answerOptions: [], + closed: closed, + totalAnswerCount: 100, + type: type, + maxAllowedSelections: 1, + hasBeenEdited: false) } static func buildAnswerOption(text: String = "Test", selected: Bool, winner: Bool = false) -> TimelinePollAnswerOption { diff --git a/RiotSwiftUI/Modules/Room/TimelinePoll/View/TimelinePollView.swift b/RiotSwiftUI/Modules/Room/TimelinePoll/View/TimelinePollView.swift index 0b2cf80e8..ff2ce2541 100644 --- a/RiotSwiftUI/Modules/Room/TimelinePoll/View/TimelinePollView.swift +++ b/RiotSwiftUI/Modules/Room/TimelinePoll/View/TimelinePollView.swift @@ -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 TimelinePollView: View { - // MARK: - Properties // MARK: Private @@ -32,7 +31,6 @@ struct TimelinePollView: View { let poll = viewModel.viewState.poll VStack(alignment: .leading, spacing: 16.0) { - Text(poll.question) .font(theme.fonts.bodySB) .foregroundColor(theme.colors.primaryContent) + @@ -77,12 +75,12 @@ struct TimelinePollView: View { return VectorL10n.pollTimelineTotalNoVotes case 1: return (poll.hasCurrentUserVoted || poll.type == .undisclosed ? - VectorL10n.pollTimelineTotalOneVote : - VectorL10n.pollTimelineTotalOneVoteNotVoted) + VectorL10n.pollTimelineTotalOneVote : + VectorL10n.pollTimelineTotalOneVoteNotVoted) default: return (poll.hasCurrentUserVoted || poll.type == .undisclosed ? - VectorL10n.pollTimelineTotalVotes(Int(poll.totalAnswerCount)) : - VectorL10n.pollTimelineTotalVotesNotVoted(Int(poll.totalAnswerCount))) + VectorL10n.pollTimelineTotalVotes(Int(poll.totalAnswerCount)) : + VectorL10n.pollTimelineTotalVotesNotVoted(Int(poll.totalAnswerCount))) } } diff --git a/RiotSwiftUI/Modules/Room/UserSuggestion/Coordinator/UserSuggestionCoordinator.swift b/RiotSwiftUI/Modules/Room/UserSuggestion/Coordinator/UserSuggestionCoordinator.swift index fd7bd57b3..c3812b5e8 100644 --- a/RiotSwiftUI/Modules/Room/UserSuggestion/Coordinator/UserSuggestionCoordinator.swift +++ b/RiotSwiftUI/Modules/Room/UserSuggestion/Coordinator/UserSuggestionCoordinator.swift @@ -14,10 +14,10 @@ // limitations under the License. // -import Foundation -import UIKit -import SwiftUI import Combine +import Foundation +import SwiftUI +import UIKit protocol UserSuggestionCoordinatorDelegate: AnyObject { func userSuggestionCoordinator(_ coordinator: UserSuggestionCoordinator, didRequestMentionForMember member: MXRoomMember, textTrigger: String?) @@ -30,7 +30,6 @@ struct UserSuggestionCoordinatorParameters { } final class UserSuggestionCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -94,12 +93,11 @@ final class UserSuggestionCoordinator: Coordinator, Presentable { } // MARK: - Public - func start() { - - } + + func start() { } func toPresentable() -> UIViewController { - return self.userSuggestionHostingController + userSuggestionHostingController } // MARK: - Private @@ -131,13 +129,12 @@ final class UserSuggestionCoordinator: Coordinator, Presentable { } private class UserSuggestionCoordinatorRoomMemberProvider: RoomMembersProviderProtocol { - private let room: MXRoom var roomMembers: [MXRoomMember] = [] init(room: MXRoom) { - self.room = room; + self.room = room } func fetchMembers(_ members: @escaping ([RoomMembersProviderMember]) -> Void) { diff --git a/RiotSwiftUI/Modules/Room/UserSuggestion/Coordinator/UserSuggestionCoordinatorBridge.swift b/RiotSwiftUI/Modules/Room/UserSuggestion/Coordinator/UserSuggestionCoordinatorBridge.swift index 44ddaee9f..c5b68eeee 100644 --- a/RiotSwiftUI/Modules/Room/UserSuggestion/Coordinator/UserSuggestionCoordinatorBridge.swift +++ b/RiotSwiftUI/Modules/Room/UserSuggestion/Coordinator/UserSuggestionCoordinatorBridge.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,10 +24,9 @@ protocol UserSuggestionCoordinatorBridgeDelegate: AnyObject { @objcMembers final class UserSuggestionCoordinatorBridge: NSObject { - - private var _userSuggestionCoordinator: Any? = nil + private var _userSuggestionCoordinator: Any? fileprivate var userSuggestionCoordinator: UserSuggestionCoordinator { - return _userSuggestionCoordinator as! UserSuggestionCoordinator + _userSuggestionCoordinator as! UserSuggestionCoordinator } weak var delegate: UserSuggestionCoordinatorBridgeDelegate? @@ -35,7 +34,7 @@ final class UserSuggestionCoordinatorBridge: NSObject { init(mediaManager: MXMediaManager, room: MXRoom) { let parameters = UserSuggestionCoordinatorParameters(mediaManager: mediaManager, room: room) let userSuggestionCoordinator = UserSuggestionCoordinator(parameters: parameters) - self._userSuggestionCoordinator = userSuggestionCoordinator + _userSuggestionCoordinator = userSuggestionCoordinator super.init() @@ -43,11 +42,11 @@ final class UserSuggestionCoordinatorBridge: NSObject { } func processTextMessage(_ textMessage: String) { - return self.userSuggestionCoordinator.processTextMessage(textMessage) + userSuggestionCoordinator.processTextMessage(textMessage) } func toPresentable() -> UIViewController? { - return self.userSuggestionCoordinator.toPresentable() + userSuggestionCoordinator.toPresentable() } } diff --git a/RiotSwiftUI/Modules/Room/UserSuggestion/Service/UserSuggestionService.swift b/RiotSwiftUI/Modules/Room/UserSuggestion/Service/UserSuggestionService.swift index cb135532f..bf8fa00a5 100644 --- a/RiotSwiftUI/Modules/Room/UserSuggestion/Service/UserSuggestionService.swift +++ b/RiotSwiftUI/Modules/Room/UserSuggestion/Service/UserSuggestionService.swift @@ -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 struct RoomMembersProviderMember { var userId: String @@ -34,7 +34,6 @@ struct UserSuggestionServiceItem: UserSuggestionItemProtocol { } class UserSuggestionService: UserSuggestionServiceProtocol { - // MARK: - Properties // MARK: Private @@ -58,7 +57,7 @@ class UserSuggestionService: UserSuggestionServiceProtocol { init(roomMemberProvider: RoomMembersProviderProtocol, shouldDebounce: Bool = true) { self.roomMemberProvider = roomMemberProvider - if (shouldDebounce) { + if shouldDebounce { currentTextTriggerSubject .debounce(for: 0.5, scheduler: RunLoop.main) .removeDuplicates() @@ -79,12 +78,12 @@ class UserSuggestionService: UserSuggestionServiceProtocol { let lastComponent = textMessage.components(separatedBy: .whitespaces).last, lastComponent.prefix(while: { $0 == "@" }).count == 1 // Partial username should start with one and only one "@" character else { - self.items.send([]) - self.currentTextTriggerSubject.send(nil) + items.send([]) + currentTextTriggerSubject.send(nil) return } - self.currentTextTriggerSubject.send(lastComponent) + currentTextTriggerSubject.send(lastComponent) } // MARK: - Private @@ -105,12 +104,12 @@ class UserSuggestionService: UserSuggestionServiceProtocol { UserSuggestionServiceItem(userId: member.userId, displayName: member.displayName, avatarUrl: member.avatarUrl) } - self.items.send(self.suggestionItems.filter({ userSuggestion in + self.items.send(self.suggestionItems.filter { userSuggestion in let containedInUsername = userSuggestion.userId.lowercased().contains(partialName.lowercased()) let containedInDisplayName = (userSuggestion.displayName ?? "").lowercased().contains(partialName.lowercased()) return (containedInUsername || containedInDisplayName) - })) + }) } } } diff --git a/RiotSwiftUI/Modules/Room/UserSuggestion/Service/UserSuggestionServiceProtocol.swift b/RiotSwiftUI/Modules/Room/UserSuggestion/Service/UserSuggestionServiceProtocol.swift index e1ee70a9c..81edb0df9 100644 --- a/RiotSwiftUI/Modules/Room/UserSuggestion/Service/UserSuggestionServiceProtocol.swift +++ b/RiotSwiftUI/Modules/Room/UserSuggestion/Service/UserSuggestionServiceProtocol.swift @@ -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 protocol UserSuggestionItemProtocol: Avatarable { var userId: String { get } @@ -24,7 +24,6 @@ protocol UserSuggestionItemProtocol: Avatarable { } protocol UserSuggestionServiceProtocol { - var items: CurrentValueSubject<[UserSuggestionItemProtocol], Never> { get } var currentTextTrigger: String? { get } @@ -38,6 +37,7 @@ extension UserSuggestionItemProtocol { var mxContentUri: String? { avatarUrl } + var matrixItemId: String { userId } diff --git a/RiotSwiftUI/Modules/Room/UserSuggestion/Test/UI/UserSuggestionUITests.swift b/RiotSwiftUI/Modules/Room/UserSuggestion/Test/UI/UserSuggestionUITests.swift index 53e3c883d..23b204083 100644 --- a/RiotSwiftUI/Modules/Room/UserSuggestion/Test/UI/UserSuggestionUITests.swift +++ b/RiotSwiftUI/Modules/Room/UserSuggestion/Test/UI/UserSuggestionUITests.swift @@ -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 RiotSwiftUI +import XCTest class UserSuggestionUITests: MockScreenTestCase { func testUserSuggestionScreen() throws { diff --git a/RiotSwiftUI/Modules/Room/UserSuggestion/Test/Unit/UserSuggestionServiceTests.swift b/RiotSwiftUI/Modules/Room/UserSuggestion/Test/Unit/UserSuggestionServiceTests.swift index 552eb4939..b32580c8d 100644 --- a/RiotSwiftUI/Modules/Room/UserSuggestion/Test/Unit/UserSuggestionServiceTests.swift +++ b/RiotSwiftUI/Modules/Room/UserSuggestion/Test/Unit/UserSuggestionServiceTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,13 +14,12 @@ // limitations under the License. // -import XCTest import Combine +import XCTest @testable import RiotSwiftUI class UserSuggestionServiceTests: XCTestCase { - var service: UserSuggestionService? override func setUp() { @@ -107,12 +106,11 @@ class UserSuggestionServiceTests: XCTestCase { extension UserSuggestionServiceTests: RoomMembersProviderProtocol { func fetchMembers(_ members: @escaping ([RoomMembersProviderMember]) -> Void) { - let users = [("Alice", "@alice:matrix.org"), ("Bob", "@bob:matrix.org")] - members(users.map({ user in + members(users.map { user in RoomMembersProviderMember(userId: user.1, displayName: user.0, avatarUrl: "") - })) + }) } } diff --git a/RiotSwiftUI/Modules/Room/UserSuggestion/UserSuggestionModels.swift b/RiotSwiftUI/Modules/Room/UserSuggestion/UserSuggestionModels.swift index 8bc107a3c..d4e984f88 100644 --- a/RiotSwiftUI/Modules/Room/UserSuggestion/UserSuggestionModels.swift +++ b/RiotSwiftUI/Modules/Room/UserSuggestion/UserSuggestionModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Room/UserSuggestion/UserSuggestionScreenState.swift b/RiotSwiftUI/Modules/Room/UserSuggestion/UserSuggestionScreenState.swift index f1b6999f3..f8a8acade 100644 --- a/RiotSwiftUI/Modules/Room/UserSuggestion/UserSuggestionScreenState.swift +++ b/RiotSwiftUI/Modules/Room/UserSuggestion/UserSuggestionScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,13 +20,13 @@ import SwiftUI enum MockUserSuggestionScreenState: MockScreenState, CaseIterable { case multipleResults - static private var members: [RoomMembersProviderMember]! + private static var members: [RoomMembersProviderMember]! var screenType: Any.Type { UserSuggestionList.self } - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let service = UserSuggestionService(roomMemberProvider: self) let listViewModel = UserSuggestionViewModel(userSuggestionService: service) @@ -37,7 +37,7 @@ enum MockUserSuggestionScreenState: MockScreenState, CaseIterable { return ( [service, listViewModel], AnyView(UserSuggestionListWithInput(viewModel: viewModel) - .addDependency(MockAvatarService.example)) + .addDependency(MockAvatarService.example)) ) } } @@ -52,7 +52,7 @@ extension MockUserSuggestionScreenState: RoomMembersProviderProtocol { } private func generateUsersWithCount(_ count: UInt) -> [RoomMembersProviderMember] { - return (0.. +typealias UserSuggestionViewModelType = StateStoreViewModel class UserSuggestionViewModel: UserSuggestionViewModelType, UserSuggestionViewModelProtocol { - // MARK: - Properties // MARK: Private @@ -39,15 +38,15 @@ class UserSuggestionViewModel: UserSuggestionViewModelType, UserSuggestionViewMo self.userSuggestionService = userSuggestionService let items = userSuggestionService.items.value.map { suggestionItem in - return UserSuggestionViewStateItem(id: suggestionItem.userId, avatar: suggestionItem, displayName: suggestionItem.displayName) + UserSuggestionViewStateItem(id: suggestionItem.userId, avatar: suggestionItem, displayName: suggestionItem.displayName) } super.init(initialViewState: UserSuggestionViewState(items: items)) userSuggestionService.items.sink { [weak self] items in - self?.state.items = items.map({ item in + self?.state.items = items.map { item in UserSuggestionViewStateItem(id: item.userId, avatar: item, displayName: item.displayName) - }) + } }.store(in: &cancellables) } diff --git a/RiotSwiftUI/Modules/Room/UserSuggestion/UserSuggestionViewModelProtocol.swift b/RiotSwiftUI/Modules/Room/UserSuggestion/UserSuggestionViewModelProtocol.swift index 7a04cf8c4..1d89ca9b4 100644 --- a/RiotSwiftUI/Modules/Room/UserSuggestion/UserSuggestionViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Room/UserSuggestion/UserSuggestionViewModelProtocol.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Room/UserSuggestion/View/UserSuggestionList.swift b/RiotSwiftUI/Modules/Room/UserSuggestion/View/UserSuggestionList.swift index 9fc137833..859b0b414 100644 --- a/RiotSwiftUI/Modules/Room/UserSuggestion/View/UserSuggestionList.swift +++ b/RiotSwiftUI/Modules/Room/UserSuggestion/View/UserSuggestionList.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,7 @@ import SwiftUI struct UserSuggestionList: View { - private struct Constants { + private enum Constants { static let topPadding: CGFloat = 8.0 static let listItemPadding: CGFloat = 4.0 static let lineSpacing: CGFloat = 10.0 @@ -57,7 +57,7 @@ struct UserSuggestionList: View { userId: item.id ) .padding(.bottom, Constants.listItemPadding) - .padding(.top, (viewModel.viewState.items.first?.id == item.id ? Constants.listItemPadding + Constants.topPadding : Constants.listItemPadding)) + .padding(.top, viewModel.viewState.items.first?.id == item.id ? Constants.listItemPadding + Constants.topPadding : Constants.listItemPadding) } } .listStyle(PlainListStyle()) @@ -76,7 +76,6 @@ struct UserSuggestionList: View { } private struct BackgroundView: View { - var content: () -> Content @Environment(\.theme) private var theme: ThemeSwiftUI diff --git a/RiotSwiftUI/Modules/Room/UserSuggestion/View/UserSuggestionListItem.swift b/RiotSwiftUI/Modules/Room/UserSuggestion/View/UserSuggestionListItem.swift index c5ade662b..0d3328b33 100644 --- a/RiotSwiftUI/Modules/Room/UserSuggestion/View/UserSuggestionListItem.swift +++ b/RiotSwiftUI/Modules/Room/UserSuggestion/View/UserSuggestionListItem.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,13 +17,14 @@ import SwiftUI struct UserSuggestionListItem: View { - // MARK: - Properties // MARK: Private + @Environment(\.theme) private var theme: ThemeSwiftUI // MARK: Public + let avatar: AvatarInputProtocol? let displayName: String? let userId: String diff --git a/RiotSwiftUI/Modules/Room/UserSuggestion/View/UserSuggestionListWithInput.swift b/RiotSwiftUI/Modules/Room/UserSuggestion/View/UserSuggestionListWithInput.swift index cba0fae13..176be8ec4 100644 --- a/RiotSwiftUI/Modules/Room/UserSuggestion/View/UserSuggestionListWithInput.swift +++ b/RiotSwiftUI/Modules/Room/UserSuggestion/View/UserSuggestionListWithInput.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,11 +18,10 @@ import SwiftUI struct UserSuggestionListWithInputViewModel { let listViewModel: UserSuggestionViewModel - let callback: (String)->() + let callback: (String) -> Void } struct UserSuggestionListWithInput: View { - // MARK: - Properties // MARK: Private @@ -30,14 +29,14 @@ struct UserSuggestionListWithInput: View { // MARK: Public var viewModel: UserSuggestionListWithInputViewModel - @State private var inputText: String = "" + @State private var inputText = "" var body: some View { VStack(spacing: 0.0) { UserSuggestionList(viewModel: viewModel.listViewModel.context) TextField("Search for user", text: $inputText) .background(Color.white) - .onChange(of: inputText, perform:viewModel.callback) + .onChange(of: inputText, perform: viewModel.callback) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding([.leading, .trailing]) .onAppear { diff --git a/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordModels.swift b/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordModels.swift index b79c29044..6796dac14 100644 --- a/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordModels.swift +++ b/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -42,8 +42,8 @@ struct ChangePasswordViewState: BindableState { /// Whether the user can submit the form: old password and new passwords should be entered var canSubmit: Bool { !bindings.oldPassword.isEmpty - && !bindings.newPassword1.isEmpty - && !bindings.newPassword2.isEmpty + && !bindings.newPassword1.isEmpty + && !bindings.newPassword2.isEmpty } } diff --git a/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModel.swift b/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModel.swift index b11309e9a..7882f2eab 100644 --- a/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModel.swift +++ b/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModel.swift @@ -17,10 +17,9 @@ import SwiftUI typealias ChangePasswordViewModelType = StateStoreViewModel + Never, + ChangePasswordViewAction> class ChangePasswordViewModel: ChangePasswordViewModelType, ChangePasswordViewModelProtocol { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModelProtocol.swift b/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModelProtocol.swift index d6050d373..db6848c9c 100644 --- a/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Settings/ChangePassword/ChangePasswordViewModelProtocol.swift @@ -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 ChangePasswordViewModelProtocol { - var callback: (@MainActor (ChangePasswordViewModelResult) -> Void)? { get set } var context: ChangePasswordViewModelType.Context { get } diff --git a/RiotSwiftUI/Modules/Settings/ChangePassword/Coordinator/ChangePasswordBridgePresenter.swift b/RiotSwiftUI/Modules/Settings/ChangePassword/Coordinator/ChangePasswordBridgePresenter.swift index 15c99ade3..e84e61570 100644 --- a/RiotSwiftUI/Modules/Settings/ChangePassword/Coordinator/ChangePasswordBridgePresenter.swift +++ b/RiotSwiftUI/Modules/Settings/ChangePassword/Coordinator/ChangePasswordBridgePresenter.swift @@ -30,7 +30,6 @@ import MatrixSDK /// once the underlying Coordinator has been integrated by another Coordinator. @objcMembers final class ChangePasswordCoordinatorBridgePresenter: NSObject { - // MARK: - Constants // MARK: - Properties @@ -57,8 +56,7 @@ final class ChangePasswordCoordinatorBridgePresenter: NSObject { // MARK: - Public func present(from viewController: UIViewController, animated: Bool) { - - let params = ChangePasswordCoordinatorParameters(restClient: self.session.matrixRestClient) + let params = ChangePasswordCoordinatorParameters(restClient: session.matrixRestClient) let changePasswordCoordinator = ChangePasswordCoordinator(parameters: params) changePasswordCoordinator.callback = { [weak self] in @@ -74,11 +72,11 @@ final class ChangePasswordCoordinatorBridgePresenter: NSObject { viewController.present(navController, animated: animated, completion: nil) changePasswordCoordinator.start() - self.coordinator = changePasswordCoordinator + coordinator = changePasswordCoordinator } func dismiss(animated: Bool, completion: (() -> Void)?) { - guard let coordinator = self.coordinator else { + guard let coordinator = coordinator else { return } diff --git a/RiotSwiftUI/Modules/Settings/ChangePassword/Coordinator/ChangePasswordCoordinator.swift b/RiotSwiftUI/Modules/Settings/ChangePassword/Coordinator/ChangePasswordCoordinator.swift index d582e8721..bd3f6fc29 100644 --- a/RiotSwiftUI/Modules/Settings/ChangePassword/Coordinator/ChangePasswordCoordinator.swift +++ b/RiotSwiftUI/Modules/Settings/ChangePassword/Coordinator/ChangePasswordCoordinator.swift @@ -14,15 +14,14 @@ // limitations under the License. // -import SwiftUI import CommonKit +import SwiftUI struct ChangePasswordCoordinatorParameters { let restClient: MXRestClient } final class ChangePasswordCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -77,7 +76,7 @@ final class ChangePasswordCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.changePasswordHostingController + changePasswordHostingController } // MARK: - Private diff --git a/RiotSwiftUI/Modules/Settings/ChangePassword/MockChangePasswordScreenState.swift b/RiotSwiftUI/Modules/Settings/ChangePassword/MockChangePasswordScreenState.swift index e4d109f23..e7a176e20 100644 --- a/RiotSwiftUI/Modules/Settings/ChangePassword/MockChangePasswordScreenState.swift +++ b/RiotSwiftUI/Modules/Settings/ChangePassword/MockChangePasswordScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,7 +34,7 @@ enum MockChangePasswordScreenState: MockScreenState, CaseIterable { } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let viewModel: ChangePasswordViewModel switch self { case .allEmpty: diff --git a/RiotSwiftUI/Modules/Settings/ChangePassword/Test/UI/ChangePasswordUITests.swift b/RiotSwiftUI/Modules/Settings/ChangePassword/Test/UI/ChangePasswordUITests.swift index c96ef6f27..218d6f2c4 100644 --- a/RiotSwiftUI/Modules/Settings/ChangePassword/Test/UI/ChangePasswordUITests.swift +++ b/RiotSwiftUI/Modules/Settings/ChangePassword/Test/UI/ChangePasswordUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class ChangePasswordUITests: MockScreenTestCase { func testAllEmpty() { @@ -125,5 +125,4 @@ class ChangePasswordUITests: MockScreenTestCase { XCTAssertTrue(signoutAllDevicesToggle.exists, "Sign out all devices toggle should exist") XCTAssertTrue(signoutAllDevicesToggle.isOn, "Sign out all devices should be checked") } - } diff --git a/RiotSwiftUI/Modules/Settings/ChangePassword/Test/Unit/ChangePasswordViewModelTests.swift b/RiotSwiftUI/Modules/Settings/ChangePassword/Test/Unit/ChangePasswordViewModelTests.swift index e279c6b53..65f30d16b 100644 --- a/RiotSwiftUI/Modules/Settings/ChangePassword/Test/Unit/ChangePasswordViewModelTests.swift +++ b/RiotSwiftUI/Modules/Settings/ChangePassword/Test/Unit/ChangePasswordViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ import XCTest @testable import RiotSwiftUI class ChangePasswordViewModelTests: XCTestCase { - @MainActor func testEmptyState() async { let viewModel = ChangePasswordViewModel() let context = viewModel.context @@ -46,5 +45,4 @@ class ChangePasswordViewModelTests: XCTestCase { XCTAssertTrue(context.viewState.canSubmit, "The view model should be able to submit.") XCTAssertTrue(context.signoutAllDevices, "Sign out of all devices should be checked.") } - } diff --git a/RiotSwiftUI/Modules/Settings/ChangePassword/View/ChangePasswordScreen.swift b/RiotSwiftUI/Modules/Settings/ChangePassword/View/ChangePasswordScreen.swift index ed7ca3dda..0602c3d4d 100644 --- a/RiotSwiftUI/Modules/Settings/ChangePassword/View/ChangePasswordScreen.swift +++ b/RiotSwiftUI/Modules/Settings/ChangePassword/View/ChangePasswordScreen.swift @@ -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 ChangePasswordScreen: View { - // MARK: - Properties // MARK: Private @@ -72,7 +71,7 @@ struct ChangePasswordScreen: View { configuration: UIKitTextInputConfiguration(returnKeyType: .next, isSecureTextEntry: true), onCommit: { focusedField = .newPassword1 }) - .accessibilityIdentifier("oldPasswordTextField") + .accessibilityIdentifier("oldPasswordTextField") RoundedBorderTextField(placeHolder: VectorL10n.settingsNewPassword, text: $viewModel.newPassword1, @@ -80,7 +79,7 @@ struct ChangePasswordScreen: View { configuration: UIKitTextInputConfiguration(returnKeyType: .next, isSecureTextEntry: true), onCommit: { focusedField = .newPassword2 }) - .accessibilityIdentifier("newPasswordTextField1") + .accessibilityIdentifier("newPasswordTextField1") RoundedBorderTextField(placeHolder: VectorL10n.settingsConfirmPassword, text: $viewModel.newPassword2, @@ -88,7 +87,7 @@ struct ChangePasswordScreen: View { configuration: UIKitTextInputConfiguration(returnKeyType: .done, isSecureTextEntry: true), onCommit: submit) - .accessibilityIdentifier("newPasswordTextField2") + .accessibilityIdentifier("newPasswordTextField2") HStack(alignment: .center, spacing: 8) { Toggle(VectorL10n.authenticationChoosePasswordSignoutAllDevices, isOn: $viewModel.signoutAllDevices) diff --git a/RiotSwiftUI/Modules/Settings/Notifications/Coordinator/NotificationSettingsBridgePresenter.swift b/RiotSwiftUI/Modules/Settings/Notifications/Coordinator/NotificationSettingsBridgePresenter.swift index f8a008b90..651ec3224 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/Coordinator/NotificationSettingsBridgePresenter.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/Coordinator/NotificationSettingsBridgePresenter.swift @@ -25,7 +25,6 @@ import Foundation /// Each bridge should be removed once the underlying Coordinator has been integrated by another Coordinator. @objcMembers final class NotificationSettingsCoordinatorBridgePresenter: NSObject { - // MARK: - Properties // MARK: Private @@ -48,7 +47,6 @@ final class NotificationSettingsCoordinatorBridgePresenter: NSObject { // MARK: - Public func push(from navigationController: UINavigationController, animated: Bool, screen: NotificationSettingsScreen, popCompletion: (() -> Void)?) { - let router = NavigationRouterStore.shared.navigationRouter(for: navigationController) let notificationSettingsCoordinator = NotificationSettingsCoordinator(session: session, screen: screen) @@ -61,12 +59,12 @@ final class NotificationSettingsCoordinatorBridgePresenter: NSObject { notificationSettingsCoordinator.start() - self.coordinator = notificationSettingsCoordinator + coordinator = notificationSettingsCoordinator self.router = router } func dismiss(animated: Bool, completion: (() -> Void)?) { - guard let coordinator = self.coordinator else { + guard let coordinator = coordinator else { return } coordinator.toPresentable().dismiss(animated: animated) { @@ -80,18 +78,17 @@ final class NotificationSettingsCoordinatorBridgePresenter: NSObject { } // MARK: - NotificationSettingsCoordinatorDelegate + extension NotificationSettingsCoordinatorBridgePresenter: NotificationSettingsCoordinatorDelegate { func notificationSettingsCoordinatorDidComplete(_ coordinator: NotificationSettingsCoordinatorType) { - self.delegate?.notificationSettingsCoordinatorBridgePresenterDelegateDidComplete(self) + delegate?.notificationSettingsCoordinatorBridgePresenterDelegateDidComplete(self) } } // MARK: - UIAdaptivePresentationControllerDelegate extension NotificationSettingsCoordinatorBridgePresenter: UIAdaptivePresentationControllerDelegate { - func notificationSettingsCoordinatorDidComplete(_ presentationController: UIPresentationController) { - self.delegate?.notificationSettingsCoordinatorBridgePresenterDelegateDidComplete(self) + delegate?.notificationSettingsCoordinatorBridgePresenterDelegateDidComplete(self) } - } diff --git a/RiotSwiftUI/Modules/Settings/Notifications/Coordinator/NotificationSettingsCoordinator.swift b/RiotSwiftUI/Modules/Settings/Notifications/Coordinator/NotificationSettingsCoordinator.swift index b903bb103..7ca59854f 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/Coordinator/NotificationSettingsCoordinator.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/Coordinator/NotificationSettingsCoordinator.swift @@ -18,7 +18,6 @@ import Foundation import SwiftUI final class NotificationSettingsCoordinator: NotificationSettingsCoordinatorType { - // MARK: - Properties // MARK: Private @@ -49,24 +48,25 @@ final class NotificationSettingsCoordinator: NotificationSettingsCoordinatorType case .other: viewController = VectorHostingController(rootView: OtherNotificationSettings(viewModel: viewModel)) } - self.notificationSettingsViewModel = viewModel - self.notificationSettingsViewController = viewController + notificationSettingsViewModel = viewModel + notificationSettingsViewController = viewController } // MARK: - Public methods - func start() { - self.notificationSettingsViewModel.coordinatorDelegate = self + func start() { + notificationSettingsViewModel.coordinatorDelegate = self } func toPresentable() -> UIViewController { - return self.notificationSettingsViewController + notificationSettingsViewController } } // MARK: - NotificationSettingsViewModelCoordinatorDelegate + extension NotificationSettingsCoordinator: NotificationSettingsViewModelCoordinatorDelegate { func notificationSettingsViewModelDidComplete(_ viewModel: NotificationSettingsViewModelType) { - self.delegate?.notificationSettingsCoordinatorDidComplete(self) + delegate?.notificationSettingsCoordinatorDidComplete(self) } } diff --git a/RiotSwiftUI/Modules/Settings/Notifications/Model/MatrixSDK/MXNotificationPushRule.swift b/RiotSwiftUI/Modules/Settings/Notifications/Model/MatrixSDK/MXNotificationPushRule.swift index 6c67350af..2c4d16d8b 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/Model/MatrixSDK/MXNotificationPushRule.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/Model/MatrixSDK/MXNotificationPushRule.swift @@ -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 DesignKit +import Foundation // Conformance of MXPushRule to the abstraction `NotificationPushRule` for use in `NotificationSettingsViewModel`. extension MXPushRule: NotificationPushRuleType { - /// Given a rule, check it match the actions in the static definition. /// - Parameter standardActions: The standard actions to match against. /// - Returns: Wether `this` rule matches the standard actions. @@ -27,7 +26,7 @@ extension MXPushRule: NotificationPushRuleType { guard let standardActions = standardActions else { return false } - if !enabled && standardActions == .disabled { + if !enabled, standardActions == .disabled { return true } @@ -75,10 +74,10 @@ extension MXPushRule: NotificationPushRuleType { } var notify: Bool { - return getAction(actionType: MXPushRuleActionTypeNotify) != nil + getAction(actionType: MXPushRuleActionTypeNotify) != nil } var dontNotify: Bool { - return getAction(actionType: MXPushRuleActionTypeDontNotify) != nil + getAction(actionType: MXPushRuleActionTypeDontNotify) != nil } } diff --git a/RiotSwiftUI/Modules/Settings/Notifications/Model/Mock/MockNotificationPushRule.swift b/RiotSwiftUI/Modules/Settings/Notifications/Model/Mock/MockNotificationPushRule.swift index 1c83c49f1..49166c99e 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/Model/Mock/MockNotificationPushRule.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/Model/Mock/MockNotificationPushRule.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,6 +20,6 @@ struct MockNotificationPushRule: NotificationPushRuleType { var ruleId: String! var enabled: Bool func matches(standardActions: NotificationStandardActions?) -> Bool { - return false + false } } diff --git a/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationActions.swift b/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationActions.swift index 2facda9cd..88b11b3be 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationActions.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationActions.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationIndex.swift b/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationIndex.swift index 89088159a..b4252ebbd 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationIndex.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationIndex.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,11 +33,11 @@ extension NotificationIndex { /// - Parameter enabled: Enabled/Disabled state. /// - Returns: The associated NotificationIndex static func index(when enabled: Bool) -> NotificationIndex { - return enabled ? .noisy : .off + enabled ? .noisy : .off } /// Used to map from the checked state back to the index. var enabled: Bool { - return self != .off + self != .off } } diff --git a/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationPushRuleDefinitions.swift b/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationPushRuleDefinitions.swift index 10fa5ec90..77c6e1ef2 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationPushRuleDefinitions.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationPushRuleDefinitions.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +16,6 @@ import Foundation - extension NotificationPushRuleId { /// A static definition of the push rule actions. /// diff --git a/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationPushRuleIds.swift b/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationPushRuleIds.swift index 38ed2b521..d74968c8b 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationPushRuleIds.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationPushRuleIds.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,7 +32,6 @@ enum NotificationPushRuleId: String { case keywords = "_keywords" } - extension NotificationPushRuleId: Identifiable { var id: String { rawValue diff --git a/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationPushRuleType.swift b/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationPushRuleType.swift index 5f58befad..1f98242c7 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationPushRuleType.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationPushRuleType.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationSettingsScreen.swift b/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationSettingsScreen.swift index 7049e67bd..fce506096 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationSettingsScreen.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationSettingsScreen.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,7 +26,7 @@ import Foundation extension NotificationSettingsScreen: CaseIterable { } extension NotificationSettingsScreen: Identifiable { - var id: Int { self.rawValue } + var id: Int { rawValue } } extension NotificationSettingsScreen { diff --git a/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationStandardActions.swift b/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationStandardActions.swift index 466b11595..89b8a55b5 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationStandardActions.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/Model/NotificationStandardActions.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Settings/Notifications/Service/MatrixSDK/MXNotificationSettingsService.swift b/RiotSwiftUI/Modules/Settings/Notifications/Service/MatrixSDK/MXNotificationSettingsService.swift index e7ac7a191..375b50ab9 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/Service/MatrixSDK/MXNotificationSettingsService.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/Service/MatrixSDK/MXNotificationSettingsService.swift @@ -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 MXNotificationSettingsService: NotificationSettingsServiceType { - private let session: MXSession private var cancellables = Set() @@ -26,11 +25,11 @@ class MXNotificationSettingsService: NotificationSettingsServiceType { @Published private var rules = [MXPushRule]() var rulesPublisher: AnyPublisher<[NotificationPushRuleType], Never> { - $rules.map({ $0.map({ $0 as NotificationPushRuleType }) }).eraseToAnyPublisher() + $rules.map { $0.map { $0 as NotificationPushRuleType } }.eraseToAnyPublisher() } var contentRulesPublisher: AnyPublisher<[NotificationPushRuleType], Never> { - $contentRules.map({ $0.map({ $0 as NotificationPushRuleType }) }).eraseToAnyPublisher() + $contentRules.map { $0.map { $0 as NotificationPushRuleType } }.eraseToAnyPublisher() } init(session: MXSession) { @@ -45,7 +44,7 @@ class MXNotificationSettingsService: NotificationSettingsServiceType { // Observe future updates to content rules rulesUpdated - .compactMap({ _ in self.session.notificationCenter.rules.global.content as? [MXPushRule] }) + .compactMap { _ in self.session.notificationCenter.rules.global.content as? [MXPushRule] } .assign(to: &$contentRules) // Set initial value of rules @@ -54,7 +53,7 @@ class MXNotificationSettingsService: NotificationSettingsServiceType { } // Observe future updates to rules rulesUpdated - .compactMap({ _ in self.session.notificationCenter.flatRules as? [MXPushRule] }) + .compactMap { _ in self.session.notificationCenter.flatRules as? [MXPushRule] } .assign(to: &$rules) } diff --git a/RiotSwiftUI/Modules/Settings/Notifications/Service/Mock/MockNotificationSettingsService.swift b/RiotSwiftUI/Modules/Settings/Notifications/Service/Mock/MockNotificationSettingsService.swift index a7faceb52..44a553f6c 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/Service/Mock/MockNotificationSettingsService.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/Service/Mock/MockNotificationSettingsService.swift @@ -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 class MockNotificationSettingsService: NotificationSettingsServiceType, ObservableObject { static let example = MockNotificationSettingsService() @@ -44,7 +44,5 @@ class MockNotificationSettingsService: NotificationSettingsServiceType, Observab keywords.remove(keyword) } - func updatePushRuleActions(for ruleId: String, enabled: Bool, actions: NotificationActions?) { - - } + func updatePushRuleActions(for ruleId: String, enabled: Bool, actions: NotificationActions?) { } } diff --git a/RiotSwiftUI/Modules/Settings/Notifications/Service/NotificationSettingsServiceType.swift b/RiotSwiftUI/Modules/Settings/Notifications/Service/NotificationSettingsServiceType.swift index 6b0565ea6..a5a1671e3 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/Service/NotificationSettingsServiceType.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/Service/NotificationSettingsServiceType.swift @@ -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 /// A service for changing notification settings and keywords protocol NotificationSettingsServiceType { diff --git a/RiotSwiftUI/Modules/Settings/Notifications/View/Chip.swift b/RiotSwiftUI/Modules/Settings/Notifications/View/Chip.swift index 0c9bfd088..24e800acb 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/View/Chip.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/View/Chip.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,10 +16,8 @@ import SwiftUI - /// A single rounded rect chip to be rendered within `Chips` collection struct Chip: View { - @Environment(\.isEnabled) var isEnabled @Environment(\.theme) var theme: ThemeSwiftUI @@ -57,7 +55,6 @@ struct Chip: View { .background(backgroundColor) .foregroundColor(foregroundColor) .cornerRadius(20) - } } diff --git a/RiotSwiftUI/Modules/Settings/Notifications/View/Chips.swift b/RiotSwiftUI/Modules/Settings/Notifications/View/Chips.swift index 9b66584d1..caccfad80 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/View/Chips.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/View/Chips.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,8 +18,7 @@ import SwiftUI /// Renders multiple chips in a flow layout. struct Chips: View { - - @State private var frame: CGRect = CGRect.zero + @State private var frame = CGRect.zero let titles: [String] let didDeleteChip: (String) -> Void @@ -56,7 +55,7 @@ struct Chips: View { } return result } - .alignmentGuide(.top) { dimension in + .alignmentGuide(.top) { _ in // Use next y value and reset if its the last. let result = y if chip == titles.last { @@ -82,6 +81,5 @@ struct Chips_Previews: PreviewProvider { Chips(titles: chips, didDeleteChip: { _ in }) .theme(.dark) } - } } diff --git a/RiotSwiftUI/Modules/Settings/Notifications/View/ChipsInput.swift b/RiotSwiftUI/Modules/Settings/Notifications/View/ChipsInput.swift index 5c62ddd34..e913447da 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/View/ChipsInput.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/View/ChipsInput.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,17 +18,15 @@ import SwiftUI /// Renders an input field and a collection of chips. struct ChipsInput: View { - @Environment(\.theme) var theme: ThemeSwiftUI @Environment(\.isEnabled) var isEnabled - @State private var chipText: String = "" + @State private var chipText = "" let titles: [String] let didAddChip: (String) -> Void let didDeleteChip: (String) -> Void - var placeholder: String = "" - + var placeholder = "" var body: some View { VStack(spacing: 16) { @@ -55,6 +53,5 @@ struct ChipsInput_Previews: PreviewProvider { chips.remove(chip) } .disabled(true) - } } diff --git a/RiotSwiftUI/Modules/Settings/Notifications/View/DefaultNotificationSettings.swift b/RiotSwiftUI/Modules/Settings/Notifications/View/DefaultNotificationSettings.swift index 8dd937614..5fecd7e29 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/View/DefaultNotificationSettings.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/View/DefaultNotificationSettings.swift @@ -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 DefaultNotificationSettings: View { - @ObservedObject var viewModel: NotificationSettingsViewModel var body: some View { @@ -38,6 +37,5 @@ struct DefaultNotifications_Previews: PreviewProvider { ) .navigationBarTitleDisplayMode(.inline) } - } } diff --git a/RiotSwiftUI/Modules/Settings/Notifications/View/FormInputFieldStyle.swift b/RiotSwiftUI/Modules/Settings/Notifications/View/FormInputFieldStyle.swift index 3b35cd396..7232dd2c7 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/View/FormInputFieldStyle.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/View/FormInputFieldStyle.swift @@ -19,7 +19,6 @@ import SwiftUI /// An input field style for forms. struct FormInputFieldStyle: TextFieldStyle { - @Environment(\.theme) var theme: ThemeSwiftUI @Environment(\.isEnabled) var isEnabled @@ -31,7 +30,7 @@ struct FormInputFieldStyle: TextFieldStyle { } private var backgroundColor: Color { - if !isEnabled && theme.identifier == .dark { + if !isEnabled, theme.identifier == .dark { return theme.colors.quinaryContent } return theme.colors.background @@ -47,7 +46,6 @@ struct FormInputFieldStyle: TextFieldStyle { } } - struct FormInputFieldStyle_Previews: PreviewProvider { static var previews: some View { Group { @@ -59,7 +57,6 @@ struct FormInputFieldStyle_Previews: PreviewProvider { TextField("Placeholder", text: .constant("Web")) .textFieldStyle(FormInputFieldStyle()) .disabled(true) - } .padding() VectorForm { @@ -70,11 +67,9 @@ struct FormInputFieldStyle_Previews: PreviewProvider { TextField("Placeholder", text: .constant("Web")) .textFieldStyle(FormInputFieldStyle()) .disabled(true) - } .padding() .theme(ThemeIdentifier.dark) } - } } diff --git a/RiotSwiftUI/Modules/Settings/Notifications/View/MentionsAndKeywordNotificationSettings.swift b/RiotSwiftUI/Modules/Settings/Notifications/View/MentionsAndKeywordNotificationSettings.swift index 78a4d733c..ac1316bfd 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/View/MentionsAndKeywordNotificationSettings.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/View/MentionsAndKeywordNotificationSettings.swift @@ -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 MentionsAndKeywordNotificationSettings: View { - @ObservedObject var viewModel: NotificationSettingsViewModel var keywordSection: some View { @@ -28,6 +27,7 @@ struct MentionsAndKeywordNotificationSettings: View { NotificationSettingsKeywords(viewModel: viewModel) } } + var body: some View { NotificationSettings( viewModel: viewModel, diff --git a/RiotSwiftUI/Modules/Settings/Notifications/View/NotificationSettings.swift b/RiotSwiftUI/Modules/Settings/Notifications/View/NotificationSettings.swift index 6943009ce..18be2680d 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/View/NotificationSettings.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/View/NotificationSettings.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,7 +21,6 @@ import SwiftUI /// Also renders an optional bottom section. /// Used in the case of keywords, for the keyword chips and input. struct NotificationSettings: View { - @ObservedObject var viewModel: NotificationSettingsViewModel var bottomSection: BottomSection? diff --git a/RiotSwiftUI/Modules/Settings/Notifications/View/NotificationSettingsKeywords.swift b/RiotSwiftUI/Modules/Settings/Notifications/View/NotificationSettingsKeywords.swift index 6c358f555..a83980710 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/View/NotificationSettingsKeywords.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/View/NotificationSettingsKeywords.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,7 +27,6 @@ struct NotificationSettingsKeywords: View { placeholder: VectorL10n.settingsNewKeyword ) .disabled(!(viewModel.viewState.selectionState[.keywords] ?? false)) - } } diff --git a/RiotSwiftUI/Modules/Settings/Notifications/View/OtherNotificationSettings.swift b/RiotSwiftUI/Modules/Settings/Notifications/View/OtherNotificationSettings.swift index 5536a662b..ba906fc13 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/View/OtherNotificationSettings.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/View/OtherNotificationSettings.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Settings/Notifications/ViewModel/NotificationSettingsViewModel.swift b/RiotSwiftUI/Modules/Settings/Notifications/ViewModel/NotificationSettingsViewModel.swift index ad1af1014..588597572 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/ViewModel/NotificationSettingsViewModel.swift +++ b/RiotSwiftUI/Modules/Settings/Notifications/ViewModel/NotificationSettingsViewModel.swift @@ -16,12 +16,11 @@ limitations under the License. */ -import Foundation import Combine +import Foundation import SwiftUI final class NotificationSettingsViewModel: NotificationSettingsViewModelType, ObservableObject { - // MARK: - Properties // MARK: Private @@ -46,7 +45,7 @@ final class NotificationSettingsViewModel: NotificationSettingsViewModelType, Ob init(notificationSettingsService: NotificationSettingsServiceType, ruleIds: [NotificationPushRuleId], initialState: NotificationSettingsViewState) { self.notificationSettingsService = notificationSettingsService self.ruleIds = ruleIds - self.viewState = initialState + viewState = initialState // Observe when the rules are updated, to subsequently update the state of the settings. notificationSettingsService.rulesPublisher @@ -57,11 +56,11 @@ final class NotificationSettingsViewModel: NotificationSettingsViewModelType, Ob if ruleIds.contains(.keywords) { // Publisher of all the keyword push rules (keyword rules do not start with '.') let keywordsRules = notificationSettingsService.contentRulesPublisher - .map { $0.filter { !$0.ruleId.starts(with: ".")} } + .map { $0.filter { !$0.ruleId.starts(with: ".") } } // Map to just the keyword strings let keywords = keywordsRules - .map { Set($0.compactMap { $0.ruleId }) } + .map { Set($0.compactMap(\.ruleId)) } // Update the keyword set keywords @@ -100,7 +99,7 @@ final class NotificationSettingsViewModel: NotificationSettingsViewModelType, Ob } convenience init(notificationSettingsService: NotificationSettingsServiceType, ruleIds: [NotificationPushRuleId]) { - let ruleState = Dictionary(uniqueKeysWithValues: ruleIds.map({ ($0, selected: true) })) + let ruleState = Dictionary(uniqueKeysWithValues: ruleIds.map { ($0, selected: true) }) self.init(notificationSettingsService: notificationSettingsService, ruleIds: ruleIds, initialState: NotificationSettingsViewState(saving: false, ruleIds: ruleIds, selectionState: ruleState)) } @@ -125,7 +124,7 @@ final class NotificationSettingsViewModel: NotificationSettingsViewModelType, Ob private func updateKeywords(isChecked: Bool) { guard !keywordsOrdered.isEmpty else { - self.viewState.selectionState[.keywords]?.toggle() + viewState.selectionState[.keywords]?.toggle() return } // Get the static definition and update the actions and enabled state for every keyword. @@ -149,22 +148,23 @@ final class NotificationSettingsViewModel: NotificationSettingsViewModelType, Ob } func remove(keyword: String) { - keywordsOrdered = keywordsOrdered.filter({ $0 != keyword }) + keywordsOrdered = keywordsOrdered.filter { $0 != keyword } notificationSettingsService.remove(keyword: keyword) } // MARK: - Private + private func rulesUpdated(newRules: [NotificationPushRuleType]) { for rule in newRules { guard let ruleId = NotificationPushRuleId(rawValue: rule.ruleId), ruleIds.contains(ruleId) else { continue } - self.viewState.selectionState[ruleId] = self.isChecked(rule: rule) + viewState.selectionState[ruleId] = isChecked(rule: rule) } } private func keywordRuleUpdated(anyEnabled: Bool) { if !keywordsOrdered.isEmpty { - self.viewState.selectionState[.keywords] = anyEnabled + viewState.selectionState[.keywords] = anyEnabled } } @@ -178,7 +178,7 @@ final class NotificationSettingsViewModel: NotificationSettingsViewModelType, Ob guard let ruleId = NotificationPushRuleId(rawValue: rule.ruleId) else { return false } let firstIndex = NotificationIndex.allCases.first { nextIndex in - return rule.matches(standardActions: ruleId.standardActions(for: nextIndex)) + rule.matches(standardActions: ruleId.standardActions(for: nextIndex)) } guard let index = firstIndex else { @@ -187,5 +187,4 @@ final class NotificationSettingsViewModel: NotificationSettingsViewModelType, Ob return index.enabled } - } diff --git a/RiotSwiftUI/Modules/Spaces/AddRoomSelector/Coordinator/AddRoomSelectorViewProvider.swift b/RiotSwiftUI/Modules/Spaces/AddRoomSelector/Coordinator/AddRoomSelectorViewProvider.swift index c24d5b6ed..af1fe6ee6 100644 --- a/RiotSwiftUI/Modules/Spaces/AddRoomSelector/Coordinator/AddRoomSelectorViewProvider.swift +++ b/RiotSwiftUI/Modules/Spaces/AddRoomSelector/Coordinator/AddRoomSelectorViewProvider.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +18,6 @@ import SwiftUI class AddRoomSelectorViewProvider: MatrixItemChooserCoordinatorViewProvider { func view(with viewModel: MatrixItemChooserViewModelType.Context) -> AnyView { - return AnyView(AddRoomSelector(viewModel: viewModel)) + AnyView(AddRoomSelector(viewModel: viewModel)) } } diff --git a/RiotSwiftUI/Modules/Spaces/AddRoomSelector/Service/MatrixSDK/AddRoomItemsProcessor.swift b/RiotSwiftUI/Modules/Spaces/AddRoomSelector/Service/MatrixSDK/AddRoomItemsProcessor.swift index 2696ee49b..ec2ad692c 100644 --- a/RiotSwiftUI/Modules/Spaces/AddRoomSelector/Service/MatrixSDK/AddRoomItemsProcessor.swift +++ b/RiotSwiftUI/Modules/Spaces/AddRoomSelector/Service/MatrixSDK/AddRoomItemsProcessor.swift @@ -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 class AddRoomItemsProcessor: MatrixItemChooserProcessorProtocol { - // MARK: Private private let parentSpace: MXSpace @@ -40,14 +39,14 @@ class AddRoomItemsProcessor: MatrixItemChooserProcessorProtocol { addChild(from: itemsIds, at: 0, completion: completion) } - func isItemIncluded(_ item: (MatrixListItemData)) -> Bool { - return !parentSpace.isRoomAChild(roomId: item.id) + func isItemIncluded(_ item: MatrixListItemData) -> Bool { + !parentSpace.isRoomAChild(roomId: item.id) } // MARK: Private /// Add room with roomId from list of room IDs at index to the parentSpace. - /// Recurse to the next index once done. + /// Recurse to the next index once done. func addChild(from roomIds: [String], at index: Int, completion: @escaping (Result) -> Void) { guard index < roomIds.count else { // last item has been processed or list is empty --> the recursion has finished diff --git a/RiotSwiftUI/Modules/Spaces/AddRoomSelector/View/AddRoomSelector.swift b/RiotSwiftUI/Modules/Spaces/AddRoomSelector/View/AddRoomSelector.swift index adfc48471..3babc259b 100644 --- a/RiotSwiftUI/Modules/Spaces/AddRoomSelector/View/AddRoomSelector.swift +++ b/RiotSwiftUI/Modules/Spaces/AddRoomSelector/View/AddRoomSelector.swift @@ -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 AddRoomSelector: View { - // MARK: Properties @ObservedObject var viewModel: MatrixItemChooserViewModel.Context @@ -26,7 +25,7 @@ struct AddRoomSelector: View { @Environment(\.theme) private var theme: ThemeSwiftUI private var isDoneEnabled: Bool { - return !viewModel.viewState.selectedItemIds.isEmpty && !viewModel.viewState.loading + !viewModel.viewState.selectedItemIds.isEmpty && !viewModel.viewState.loading } // MARK: Setup diff --git a/RiotSwiftUI/Modules/Spaces/LeaveSpace/Coordinator/LeaveSpaceViewProvider.swift b/RiotSwiftUI/Modules/Spaces/LeaveSpace/Coordinator/LeaveSpaceViewProvider.swift index e1e5df850..ced508155 100644 --- a/RiotSwiftUI/Modules/Spaces/LeaveSpace/Coordinator/LeaveSpaceViewProvider.swift +++ b/RiotSwiftUI/Modules/Spaces/LeaveSpace/Coordinator/LeaveSpaceViewProvider.swift @@ -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 class LeaveSpaceViewProvider: MatrixItemChooserCoordinatorViewProvider { - private let navTitle: String? init(navTitle: String?) { @@ -25,6 +24,6 @@ class LeaveSpaceViewProvider: MatrixItemChooserCoordinatorViewProvider { } func view(with viewModel: MatrixItemChooserViewModelType.Context) -> AnyView { - return AnyView(LeaveSpace(viewModel: viewModel, navTitle: navTitle)) + AnyView(LeaveSpace(viewModel: viewModel, navTitle: navTitle)) } } diff --git a/RiotSwiftUI/Modules/Spaces/LeaveSpace/Service/MatrixSDK/LeaveSpaceItemsProcessor.swift b/RiotSwiftUI/Modules/Spaces/LeaveSpace/Service/MatrixSDK/LeaveSpaceItemsProcessor.swift index 912ad551d..3fb4cbb99 100644 --- a/RiotSwiftUI/Modules/Spaces/LeaveSpace/Service/MatrixSDK/LeaveSpaceItemsProcessor.swift +++ b/RiotSwiftUI/Modules/Spaces/LeaveSpace/Service/MatrixSDK/LeaveSpaceItemsProcessor.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ import Foundation import MatrixSDK class LeaveSpaceItemsProcessor: MatrixItemChooserProcessorProtocol { - // MARK: Private private let spaceId: String @@ -29,7 +28,7 @@ class LeaveSpaceItemsProcessor: MatrixItemChooserProcessorProtocol { init(spaceId: String, session: MXSession) { self.spaceId = spaceId self.session = session - self.dataSource = MatrixItemChooserDirectChildrenDataSource(parentId: spaceId) + dataSource = MatrixItemChooserDirectChildrenDataSource(parentId: spaceId) } // MARK: MatrixItemChooserSelectionProcessorProtocol @@ -41,11 +40,11 @@ class LeaveSpaceItemsProcessor: MatrixItemChooserProcessorProtocol { } func computeSelection(withIds itemsIds: [String], completion: @escaping (Result) -> Void) { - guard let space = self.session.spaceService.getSpace(withId: self.spaceId) else { + guard let space = session.spaceService.getSpace(withId: spaceId) else { return } - self.leaveAllRooms(from: itemsIds, at: 0) { [weak self] result in + leaveAllRooms(from: itemsIds, at: 0) { [weak self] result in guard let self = self else { return } switch result { @@ -57,8 +56,8 @@ class LeaveSpaceItemsProcessor: MatrixItemChooserProcessorProtocol { } } - func isItemIncluded(_ item: (MatrixListItemData)) -> Bool { - return true + func isItemIncluded(_ item: MatrixListItemData) -> Bool { + true } // MARK: Private @@ -71,8 +70,8 @@ class LeaveSpaceItemsProcessor: MatrixItemChooserProcessorProtocol { return } - guard let room = self.session.room(withRoomId: roomIds[index]), !room.isDirect else { - self.leaveAllRooms(from: roomIds, at: index+1, completion: completion) + guard let room = session.room(withRoomId: roomIds[index]), !room.isDirect else { + leaveAllRooms(from: roomIds, at: index + 1, completion: completion) return } @@ -82,7 +81,7 @@ class LeaveSpaceItemsProcessor: MatrixItemChooserProcessorProtocol { switch response { case .success: - self.leaveAllRooms(from: roomIds, at: index+1, completion: completion) + self.leaveAllRooms(from: roomIds, at: index + 1, completion: completion) case .failure(let error): MXLog.error("[LeaveSpaceItemsProcessor] failed to leave room", context: error) completion(.failure(error)) diff --git a/RiotSwiftUI/Modules/Spaces/LeaveSpace/View/LeaveSpace.swift b/RiotSwiftUI/Modules/Spaces/LeaveSpace/View/LeaveSpace.swift index da065f36f..4de0a5af6 100644 --- a/RiotSwiftUI/Modules/Spaces/LeaveSpace/View/LeaveSpace.swift +++ b/RiotSwiftUI/Modules/Spaces/LeaveSpace/View/LeaveSpace.swift @@ -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 LeaveSpace: View { - // MARK: Properties @ObservedObject var viewModel: MatrixItemChooserViewModel.Context @@ -53,5 +52,4 @@ struct LeaveSpace: View { .buttonStyle(PrimaryActionButtonStyle(customColor: theme.colors.alert)) .padding() } - } diff --git a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Coordinator/MatrixItemChooserCoordinator.swift b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Coordinator/MatrixItemChooserCoordinator.swift index c8a632ada..467c69eb9 100644 --- a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Coordinator/MatrixItemChooserCoordinator.swift +++ b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Coordinator/MatrixItemChooserCoordinator.swift @@ -15,8 +15,8 @@ // import Foundation -import UIKit import SwiftUI +import UIKit internal protocol MatrixItemChooserCoordinatorViewProvider { func view(with viewModel: MatrixItemChooserViewModelType.Context) -> AnyView @@ -49,7 +49,6 @@ struct MatrixItemChooserCoordinatorParameters { } final class MatrixItemChooserCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -94,6 +93,6 @@ final class MatrixItemChooserCoordinator: Coordinator, Presentable { // MARK: - Presentable func toPresentable() -> UIViewController { - return self.matrixItemChooserHostingController + matrixItemChooserHostingController } } diff --git a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/MatrixItemChooserModels.swift b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/MatrixItemChooserModels.swift index da1374498..3493ae131 100644 --- a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/MatrixItemChooserModels.swift +++ b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/MatrixItemChooserModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -58,7 +58,7 @@ struct MatrixListItemSectionData { } } -extension MatrixListItemSectionData: Identifiable, Equatable {} +extension MatrixListItemSectionData: Identifiable, Equatable { } struct MatrixListItemData { let id: String @@ -68,7 +68,7 @@ struct MatrixListItemData { let detailText: String? } -extension MatrixListItemData: Identifiable, Equatable {} +extension MatrixListItemData: Identifiable, Equatable { } struct MatrixItemChooserSelectionHeader { var title: String diff --git a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/MatrixItemChooserViewModel.swift b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/MatrixItemChooserViewModel.swift index 9aa6786c8..0e487565e 100644 --- a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/MatrixItemChooserViewModel.swift +++ b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/MatrixItemChooserViewModel.swift @@ -14,21 +14,20 @@ // limitations under the License. // -import SwiftUI import Combine +import SwiftUI typealias MatrixItemChooserViewModelType = StateStoreViewModel + Never, + MatrixItemChooserViewAction> class MatrixItemChooserViewModel: MatrixItemChooserViewModelType, MatrixItemChooserViewModelProtocol { - // MARK: - Properties // MARK: Private private var matrixItemChooserService: MatrixItemChooserServiceProtocol - private var isLoading: Bool = false { + private var isLoading = false { didSet { state.loading = isLoading if isLoading { @@ -44,7 +43,7 @@ class MatrixItemChooserViewModel: MatrixItemChooserViewModelType, MatrixItemChoo // MARK: - Setup static func makeMatrixItemChooserViewModel(matrixItemChooserService: MatrixItemChooserServiceProtocol, title: String?, detail: String?, selectionHeader: MatrixItemChooserSelectionHeader?) -> MatrixItemChooserViewModelProtocol { - return MatrixItemChooserViewModel(matrixItemChooserService: matrixItemChooserService, title: title, detail: detail, selectionHeader: selectionHeader) + MatrixItemChooserViewModel(matrixItemChooserService: matrixItemChooserService, title: title, detail: detail, selectionHeader: selectionHeader) } private init(matrixItemChooserService: MatrixItemChooserServiceProtocol, title: String?, detail: String?, selectionHeader: MatrixItemChooserSelectionHeader?) { @@ -98,13 +97,13 @@ class MatrixItemChooserViewModel: MatrixItemChooserViewModelType, MatrixItemChoo } } case .searchTextChanged(let searchText): - self.matrixItemChooserService.searchText = searchText + matrixItemChooserService.searchText = searchText case .itemTapped(let itemId): - self.matrixItemChooserService.reverseSelectionForItem(withId: itemId) + matrixItemChooserService.reverseSelectionForItem(withId: itemId) case .selectAll: - self.matrixItemChooserService.selectAllItems() + matrixItemChooserService.selectAllItems() case .selectNone: - self.matrixItemChooserService.deselectAllItems() + matrixItemChooserService.deselectAllItems() } } @@ -119,5 +118,4 @@ class MatrixItemChooserViewModel: MatrixItemChooserViewModelType, MatrixItemChoo private func back() { completion?(.back) } - } diff --git a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/MatrixItemChooserViewModelProtocol.swift b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/MatrixItemChooserViewModelProtocol.swift index 3bf385f7f..d9e7899e9 100644 --- a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/MatrixItemChooserViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/MatrixItemChooserViewModelProtocol.swift @@ -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 MatrixItemChooserViewModelProtocol { - var completion: ((MatrixItemChooserViewModelResult) -> Void)? { get set } static func makeMatrixItemChooserViewModel(matrixItemChooserService: MatrixItemChooserServiceProtocol, title: String?, detail: String?, selectionHeader: MatrixItemChooserSelectionHeader?) -> MatrixItemChooserViewModelProtocol var context: MatrixItemChooserViewModelType.Context { get } diff --git a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/MockMatrixItemChooserScreenState.swift b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/MockMatrixItemChooserScreenState.swift index 8b32c9fb5..e18476c24 100644 --- a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/MockMatrixItemChooserScreenState.swift +++ b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/MockMatrixItemChooserScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixItemChooserServiceProtocol.swift b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixItemChooserServiceProtocol.swift index 88218ff79..ce396d993 100644 --- a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixItemChooserServiceProtocol.swift +++ b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixItemChooserServiceProtocol.swift @@ -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 protocol MatrixItemChooserServiceProtocol { var sectionsSubject: CurrentValueSubject<[MatrixListItemSectionData], Never> { get } diff --git a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserDirectChildrenDataSource.swift b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserDirectChildrenDataSource.swift index c48d6abdb..1a359d60c 100644 --- a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserDirectChildrenDataSource.swift +++ b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserDirectChildrenDataSource.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,6 @@ import Foundation class MatrixItemChooserDirectChildrenDataSource: MatrixItemChooserDataSource { - // MARK: - Private private let parentId: String @@ -34,13 +33,13 @@ class MatrixItemChooserDirectChildrenDataSource: MatrixItemChooserDataSource { func sections(with session: MXSession, completion: @escaping (Result<[MatrixListItemSectionData], Error>) -> Void) { let space = session.spaceService.getSpace(withId: parentId) - let children: [MatrixListItemData] = space?.childRoomIds.compactMap({ roomId in + let children: [MatrixListItemData] = space?.childRoomIds.compactMap { roomId in guard let room = session.room(withRoomId: roomId), !room.isDirect else { return nil } return MatrixListItemData(mxRoom: room, spaceService: session.spaceService) - }) ?? [] + } ?? [] completion(Result(catching: { [ MatrixListItemSectionData(items: children) diff --git a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserRoomAncestorsDataSource.swift b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserRoomAncestorsDataSource.swift index aee17961b..d3ee2bee5 100644 --- a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserRoomAncestorsDataSource.swift +++ b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserRoomAncestorsDataSource.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,7 +28,7 @@ class MatrixItemChooserRoomAncestorsDataSource: MatrixItemChooserDataSource { func sections(with session: MXSession, completion: @escaping (Result<[MatrixListItemSectionData], Error>) -> Void) { let ancestorsIds = session.spaceService.ancestorsPerRoomId[roomId] ?? [] completion(Result(catching: { - return [ + [ MatrixListItemSectionData(title: VectorL10n.roomAccessSpaceChooserKnownSpacesSection(session.room(withRoomId: roomId)?.displayName ?? ""), items: ancestorsIds.compactMap { spaceId in guard let space = session.spaceService.getSpace(withId: spaceId) else { return nil diff --git a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserRoomDirectParentsDataSource.swift b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserRoomDirectParentsDataSource.swift index 95e292356..dade8ced2 100644 --- a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserRoomDirectParentsDataSource.swift +++ b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserRoomDirectParentsDataSource.swift @@ -22,7 +22,6 @@ enum MatrixItemChooserRoomDirectParentsDataSourcePreselectionMode { } class MatrixItemChooserRoomDirectParentsDataSource: MatrixItemChooserDataSource { - private let roomId: String private let preselectionMode: MatrixItemChooserRoomDirectParentsDataSourcePreselectionMode @@ -44,7 +43,7 @@ class MatrixItemChooserRoomDirectParentsDataSource: MatrixItemChooserDataSource } completion(Result(catching: { - return [ + [ MatrixListItemSectionData(title: VectorL10n.roomAccessSpaceChooserKnownSpacesSection(session.room(withRoomId: roomId)?.displayName ?? ""), items: ancestorsIds.compactMap { spaceId in guard let space = session.spaceService.getSpace(withId: spaceId) else { return nil diff --git a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserRoomRestrictedAllowedParentsDataSource.swift b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserRoomRestrictedAllowedParentsDataSource.swift index 4f4443c44..999d96cb9 100644 --- a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserRoomRestrictedAllowedParentsDataSource.swift +++ b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserRoomRestrictedAllowedParentsDataSource.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,7 +34,7 @@ class MatrixItemChooserRoomRestrictedAllowedParentsDataSource: MatrixItemChooser } room.state { [weak self] state in - guard let self = self else { return } + guard let self = self else { return } let joinRuleEvent = state?.stateEvents(with: .roomJoinRules)?.last let allowContent: [[String: String]] = joinRuleEvent?.wireContent[kMXJoinRulesContentKeyAllow] as? [[String: String]] ?? [] @@ -74,19 +74,20 @@ class MatrixItemChooserRoomRestrictedAllowedParentsDataSource: MatrixItemChooser sections.append(MatrixListItemSectionData( title: VectorL10n.roomAccessSpaceChooserOtherSpacesSection, infoText: VectorL10n.roomAccessSpaceChooserOtherSpacesSectionInfo(room.displayName ?? ""), - items: unknownParents.compactMap({ roomId in + items: unknownParents.compactMap { roomId in MatrixListItemData( id: roomId, type: .space, avatar: AvatarInput(mxContentUri: roomId, matrixItemId: roomId, displayName: roomId), displayName: roomId, - detailText: nil) - }) + detailText: nil + ) + } )) } completion(Result(catching: { - return sections + sections })) } } diff --git a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserRoomsDataSource.swift b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserRoomsDataSource.swift index 5906cdba1..348c4bb71 100644 --- a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserRoomsDataSource.swift +++ b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserRoomsDataSource.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserService.swift b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserService.swift index 22a624413..28ed8a754 100644 --- a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserService.swift +++ b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserService.swift @@ -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 protocol MatrixItemChooserDataSource { func sections(with session: MXSession, completion: @escaping (Result<[MatrixListItemSectionData], Error>) -> Void) @@ -25,12 +25,11 @@ protocol MatrixItemChooserDataSource { protocol MatrixItemChooserProcessorProtocol { var loadingText: String? { get } var dataSource: MatrixItemChooserDataSource { get } - func computeSelection(withIds itemsIds:[String], completion: @escaping (Result) -> Void) - func isItemIncluded(_ item: (MatrixListItemData)) -> Bool + func computeSelection(withIds itemsIds: [String], completion: @escaping (Result) -> Void) + func isItemIncluded(_ item: MatrixListItemData) -> Bool } class MatrixItemChooserService: MatrixItemChooserServiceProtocol { - // MARK: - Properties // MARK: Private @@ -45,6 +44,7 @@ class MatrixItemChooserService: MatrixItemChooserServiceProtocol { sectionsSubject.send(filteredSections) } } + private var selectedItemIds: Set private let itemsProcessor: MatrixItemChooserProcessorProtocol @@ -52,14 +52,16 @@ class MatrixItemChooserService: MatrixItemChooserServiceProtocol { private(set) var sectionsSubject: CurrentValueSubject<[MatrixListItemSectionData], Never> private(set) var selectedItemIdsSubject: CurrentValueSubject, Never> - var searchText: String = "" { + var searchText = "" { didSet { refresh() } } + var loadingText: String? { itemsProcessor.loadingText } + var itemCount: Int { var itemCount = 0 for section in sections { @@ -72,10 +74,10 @@ class MatrixItemChooserService: MatrixItemChooserServiceProtocol { init(session: MXSession, selectedItemIds: [String], itemsProcessor: MatrixItemChooserProcessorProtocol) { self.session = session - self.sectionsSubject = CurrentValueSubject(self.sections) + sectionsSubject = CurrentValueSubject(sections) self.selectedItemIds = Set(selectedItemIds) - self.selectedItemIdsSubject = CurrentValueSubject(self.selectedItemIds) + selectedItemIdsSubject = CurrentValueSubject(self.selectedItemIds) self.itemsProcessor = itemsProcessor itemsProcessor.dataSource.sections(with: session) { [weak self] result in @@ -115,7 +117,7 @@ class MatrixItemChooserService: MatrixItemChooserServiceProtocol { } func refresh() { - self.processingQueue.async { [weak self] in + processingQueue.async { [weak self] in guard let self = self else { return } let filteredSections = self.filter(sections: self.sections) @@ -132,12 +134,12 @@ class MatrixItemChooserService: MatrixItemChooserServiceProtocol { newSelection.insert(item.id) } } - self.selectedItemIds = newSelection + selectedItemIds = newSelection selectedItemIdsSubject.send(selectedItemIds) } func deselectAllItems() { - self.selectedItemIds = Set() + selectedItemIds = Set() selectedItemIdsSubject.send(selectedItemIds) } @@ -153,7 +155,7 @@ class MatrixItemChooserService: MatrixItemChooserServiceProtocol { itemsProcessor.isItemIncluded($0) } } else { - let lowercasedSearchText = self.searchText.lowercased() + let lowercasedSearchText = searchText.lowercased() items = section.items.filter { itemsProcessor.isItemIncluded($0) && ($0.id.lowercased().contains(lowercasedSearchText) || ($0.displayName ?? "").lowercased().contains(lowercasedSearchText)) } diff --git a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserUsersDataSource.swift b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserUsersDataSource.swift index 3194c37d7..184005866 100644 --- a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserUsersDataSource.swift +++ b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixItemChooserUsersDataSource.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixListItemData+Riot.swift b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixListItemData+Riot.swift index 5e8cc6119..292ad2ee0 100644 --- a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixListItemData+Riot.swift +++ b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/MatrixSDK/MatrixListItemData+Riot.swift @@ -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 extension MatrixListItemData { - init(mxUser: MXUser) { self.init(id: mxUser.userId, type: .user, avatar: mxUser.avatarData, displayName: mxUser.displayname, detailText: mxUser.userId) } @@ -54,5 +53,4 @@ extension MatrixListItemData { } self.init(id: mxRoom.roomId, type: type, avatar: mxRoom.avatarData, displayName: mxRoom.summary.displayname, detailText: detailText) } - } diff --git a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/Mock/MockMatrixItemChooserService.swift b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/Mock/MockMatrixItemChooserService.swift index b08ede2fe..e1426bb6f 100644 --- a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/Mock/MockMatrixItemChooserService.swift +++ b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Service/Mock/MockMatrixItemChooserService.swift @@ -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 MockMatrixItemChooserService: MatrixItemChooserServiceProtocol { - static let mockSections = [ MatrixListItemSectionData(title: "Section 1", infoText: "This is the first section with a very long description in order to check multi line description", items: [ MatrixListItemData(id: "!aaabaa:matrix.org", type: .room, avatar: MockAvatarInput.example, displayName: "Item #1 section #1", detailText: "Descripton of this room"), @@ -33,11 +32,12 @@ class MockMatrixItemChooserService: MatrixItemChooserServiceProtocol { ] var sectionsSubject: CurrentValueSubject<[MatrixListItemSectionData], Never> var selectedItemIdsSubject: CurrentValueSubject, Never> - var searchText: String = "" + var searchText = "" var selectedItemIds: Set = Set() var loadingText: String? { nil } + var itemCount: Int { var itemCount = 0 for section in sectionsSubject.value { @@ -82,9 +82,7 @@ class MockMatrixItemChooserService: MatrixItemChooserServiceProtocol { completion(Result.success(())) } - func refresh() { - - } + func refresh() { } func selectAllItems() { var newSelection: Set = Set() @@ -93,12 +91,12 @@ class MockMatrixItemChooserService: MatrixItemChooserServiceProtocol { newSelection.insert(item.id) } } - self.selectedItemIds = newSelection + selectedItemIds = newSelection selectedItemIdsSubject.send(selectedItemIds) } func deselectAllItems() { - self.selectedItemIds = Set() + selectedItemIds = Set() selectedItemIdsSubject.send(selectedItemIds) } } diff --git a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Test/UI/MatrixItemChooserUITests.swift b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Test/UI/MatrixItemChooserUITests.swift index edcd683a3..52bccd9aa 100644 --- a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Test/UI/MatrixItemChooserUITests.swift +++ b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Test/UI/MatrixItemChooserUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class MatrixItemChooserUITests: MockScreenTestCase { func testEmptyScreen() { @@ -42,5 +42,4 @@ class MatrixItemChooserUITests: MockScreenTestCase { XCTAssertEqual(app.staticTexts["messageText"].label, VectorL10n.spacesCreationAddRoomsMessage) XCTAssertEqual(app.staticTexts["emptyListMessage"].exists, false) } - } diff --git a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Test/Unit/MatrixItemChooserViewModelTests.swift b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Test/Unit/MatrixItemChooserViewModelTests.swift index 604674ce4..626707a1a 100644 --- a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Test/Unit/MatrixItemChooserViewModelTests.swift +++ b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/Test/Unit/MatrixItemChooserViewModelTests.swift @@ -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 diff --git a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/View/MatrixItemChooser.swift b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/View/MatrixItemChooser.swift index eeb7743d3..6b7236788 100644 --- a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/View/MatrixItemChooser.swift +++ b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/View/MatrixItemChooser.swift @@ -19,12 +19,11 @@ import SwiftUI struct MatrixItemChooser: View { - // MARK: Properties @ObservedObject var viewModel: MatrixItemChooserViewModel.Context let listBottomPadding: CGFloat? - @State var searchText: String = "" + @State var searchText = "" // MARK: Private @@ -113,7 +112,7 @@ struct MatrixItemChooser: View { } Spacer().frame(height: spacerHeight) SearchBar(placeholder: VectorL10n.searchDefaultPlaceholder, text: $searchText) - .onChange(of: searchText) { value in + .onChange(of: searchText) { _ in viewModel.send(viewAction: .searchTextChanged(searchText)) } if let selectionHeader = viewModel.viewState.selectionHeader, searchText.isEmpty { @@ -124,7 +123,7 @@ struct MatrixItemChooser: View { } private func itemSelectionHeader(with selectionHeader: MatrixItemChooserSelectionHeader) -> some View { - VStack(alignment:.leading) { + VStack(alignment: .leading) { HStack { Text(selectionHeader.title) .font(theme.fonts.calloutSB) @@ -151,7 +150,6 @@ struct MatrixItemChooser: View { // MARK: - Previews struct MatrixItemChooser_Previews: PreviewProvider { - static let stateRenderer = MockMatrixItemChooserScreenState.stateRenderer static var previews: some View { stateRenderer.screenGroup(addNavigation: false) diff --git a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/View/MatrixItemChooserListRow.swift b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/View/MatrixItemChooserListRow.swift index f5d6db9c8..1d67f2a72 100644 --- a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/View/MatrixItemChooserListRow.swift +++ b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/View/MatrixItemChooserListRow.swift @@ -17,7 +17,6 @@ import SwiftUI struct MatrixItemChooserListRow: View { - // MARK: - Properties // MARK: Private @@ -34,7 +33,7 @@ struct MatrixItemChooserListRow: View { @ViewBuilder var body: some View { - HStack{ + HStack { if type == .space { SpaceAvatarImage(avatarData: avatar, size: .small) } else { diff --git a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/View/MatrixItemChooserSectionHeader.swift b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/View/MatrixItemChooserSectionHeader.swift index 632403587..a8a75c96a 100644 --- a/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/View/MatrixItemChooserSectionHeader.swift +++ b/RiotSwiftUI/Modules/Spaces/MatrixItemChooser/View/MatrixItemChooserSectionHeader.swift @@ -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 MatrixItemChooserSectionHeader: View { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Spaces/RoomAncestorSelector/Coordinator/RoomAncestorSelectorViewProvider.swift b/RiotSwiftUI/Modules/Spaces/RoomAncestorSelector/Coordinator/RoomAncestorSelectorViewProvider.swift index 070a31967..1ec2d21f3 100644 --- a/RiotSwiftUI/Modules/Spaces/RoomAncestorSelector/Coordinator/RoomAncestorSelectorViewProvider.swift +++ b/RiotSwiftUI/Modules/Spaces/RoomAncestorSelector/Coordinator/RoomAncestorSelectorViewProvider.swift @@ -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 class RoomAncestorSelectorViewProvider: MatrixItemChooserCoordinatorViewProvider { - private let navTitle: String? init(navTitle: String?) { @@ -25,6 +24,6 @@ class RoomAncestorSelectorViewProvider: MatrixItemChooserCoordinatorViewProvider } func view(with viewModel: MatrixItemChooserViewModelType.Context) -> AnyView { - return AnyView(RoomAncestorSelector(viewModel: viewModel, navTitle: navTitle)) + AnyView(RoomAncestorSelector(viewModel: viewModel, navTitle: navTitle)) } } diff --git a/RiotSwiftUI/Modules/Spaces/RoomAncestorSelector/Service/MatrixSDK/RoomAncestorSelectorItemsProcessor.swift b/RiotSwiftUI/Modules/Spaces/RoomAncestorSelector/Service/MatrixSDK/RoomAncestorSelectorItemsProcessor.swift index 0c8f8884c..7b28dc2b2 100644 --- a/RiotSwiftUI/Modules/Spaces/RoomAncestorSelector/Service/MatrixSDK/RoomAncestorSelectorItemsProcessor.swift +++ b/RiotSwiftUI/Modules/Spaces/RoomAncestorSelector/Service/MatrixSDK/RoomAncestorSelectorItemsProcessor.swift @@ -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 class RoomAncestorSelectorItemsProcessor: MatrixItemChooserProcessorProtocol { - // MARK: Private private let roomId: String @@ -26,7 +25,7 @@ class RoomAncestorSelectorItemsProcessor: MatrixItemChooserProcessorProtocol { init(roomId: String) { self.roomId = roomId - self.dataSource = MatrixItemChooserRoomAncestorsDataSource(roomId: roomId) + dataSource = MatrixItemChooserRoomAncestorsDataSource(roomId: roomId) } // MARK: MatrixItemChooserSelectionProcessorProtocol @@ -41,7 +40,7 @@ class RoomAncestorSelectorItemsProcessor: MatrixItemChooserProcessorProtocol { completion(Result.success(())) } - func isItemIncluded(_ item: (MatrixListItemData)) -> Bool { - return true + func isItemIncluded(_ item: MatrixListItemData) -> Bool { + true } } diff --git a/RiotSwiftUI/Modules/Spaces/RoomAncestorSelector/View/RoomAncestorSelector.swift b/RiotSwiftUI/Modules/Spaces/RoomAncestorSelector/View/RoomAncestorSelector.swift index 91ac64a40..3d1c2557a 100644 --- a/RiotSwiftUI/Modules/Spaces/RoomAncestorSelector/View/RoomAncestorSelector.swift +++ b/RiotSwiftUI/Modules/Spaces/RoomAncestorSelector/View/RoomAncestorSelector.swift @@ -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 RoomAncestorSelector: View { - // MARK: Properties @ObservedObject var viewModel: MatrixItemChooserViewModel.Context @@ -46,5 +45,4 @@ struct RoomAncestorSelector: View { } } } - } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/Coordinator/SpaceCreationCoordinator.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/Coordinator/SpaceCreationCoordinator.swift index 592fe50bd..ad7e56d2a 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/Coordinator/SpaceCreationCoordinator.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/Coordinator/SpaceCreationCoordinator.swift @@ -22,7 +22,6 @@ import UIKit @objcMembers final class SpaceCreationCoordinator: Coordinator { - // MARK: - Properties // MARK: Private @@ -30,7 +29,7 @@ final class SpaceCreationCoordinator: Coordinator { private let parameters: SpaceCreationCoordinatorParameters private var navigationRouter: NavigationRouterType { - return self.parameters.navigationRouter + parameters.navigationRouter } private let spaceVisibilityMenuParameters: SpaceCreationMenuCoordinatorParameters @@ -57,7 +56,7 @@ final class SpaceCreationCoordinator: Coordinator { } self.parameters = parameters - self.spaceVisibilityMenuParameters = SpaceCreationMenuCoordinatorParameters( + spaceVisibilityMenuParameters = SpaceCreationMenuCoordinatorParameters( session: parameters.session, creationParams: parameters.creationParameters, navTitle: VectorL10n.spacesCreateSpaceTitle, @@ -70,7 +69,7 @@ final class SpaceCreationCoordinator: Coordinator { ] ) - self.spaceSharingTypeMenuParameters = SpaceCreationMenuCoordinatorParameters( + spaceSharingTypeMenuParameters = SpaceCreationMenuCoordinatorParameters( session: parameters.session, creationParams: parameters.creationParameters, navTitle: nil, @@ -91,26 +90,26 @@ final class SpaceCreationCoordinator: Coordinator { Analytics.shared.trackScreen(.createSpace) - let rootCoordinator = self.createMenuCoordinator(with: spaceVisibilityMenuParameters) + let rootCoordinator = createMenuCoordinator(with: spaceVisibilityMenuParameters) rootCoordinator.start() - self.add(childCoordinator: rootCoordinator) + add(childCoordinator: rootCoordinator) - self.toPresentable().isModalInPresentation = true + toPresentable().isModalInPresentation = true - 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 @@ -118,7 +117,7 @@ final class SpaceCreationCoordinator: 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) }) @@ -126,7 +125,7 @@ final class SpaceCreationCoordinator: Coordinator { } private func createMenuCoordinator(with parameters: SpaceCreationMenuCoordinatorParameters) -> SpaceCreationMenuCoordinator { - let coordinator: SpaceCreationMenuCoordinator = SpaceCreationMenuCoordinator(parameters: parameters) + let coordinator = SpaceCreationMenuCoordinator(parameters: parameters) coordinator.callback = { [weak self] result in MXLog.debug("[SpaceCreationCoordinator] SpaceCreationMenuCoordinator did complete with result \(result).") @@ -217,7 +216,8 @@ final class SpaceCreationCoordinator: Coordinator { detail: VectorL10n.spacesCreationInviteByUsernameMessage, selectedItemsIds: parameters.creationParameters.userIdInvites, viewProvider: SpaceCreationMatrixItemChooserViewProvider(), - itemsProcessor: SpaceCreationInviteUsersItemsProcessor(creationParams: parameters.creationParameters)) + itemsProcessor: SpaceCreationInviteUsersItemsProcessor(creationParams: parameters.creationParameters) + ) let coordinator = MatrixItemChooserCoordinator(parameters: parameters) coordinator.completion = { [weak self] result in guard let self = self else { return } @@ -240,7 +240,8 @@ final class SpaceCreationCoordinator: Coordinator { detail: VectorL10n.spacesCreationAddRoomsMessage, selectedItemsIds: parameters.creationParameters.addedRoomIds ?? [], viewProvider: SpaceCreationMatrixItemChooserViewProvider(), - itemsProcessor: SpaceCreationAddRoomsItemsProcessor(creationParams: parameters.creationParameters)) + itemsProcessor: SpaceCreationAddRoomsItemsProcessor(creationParams: parameters.creationParameters) + ) let coordinator = MatrixItemChooserCoordinator(parameters: parameters) coordinator.completion = { [weak self] result in guard let self = self else { return } @@ -275,13 +276,13 @@ final class SpaceCreationCoordinator: Coordinator { UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) let alert = UIAlertController(title: VectorL10n.spacesCreationCancelTitle, message: VectorL10n.spacesCreationCancelMessage, preferredStyle: .alert) - alert.addAction(UIAlertAction(title: VectorL10n.stop, style: .destructive, handler: { action in + alert.addAction(UIAlertAction(title: VectorL10n.stop, style: .destructive, handler: { _ in self.callback?(.cancel) })) alert.addAction(UIAlertAction(title: VectorL10n.continue, style: .cancel, handler: nil)) navigationRouter.present(alert, animated: true) } else { - self.callback?(.cancel) + callback?(.cancel) } } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/Coordinator/SpaceCreationCoordinatorAction.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/Coordinator/SpaceCreationCoordinatorAction.swift index 879d8e0f8..fee96634a 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/Coordinator/SpaceCreationCoordinatorAction.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/Coordinator/SpaceCreationCoordinatorAction.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/Coordinator/SpaceCreationCoordinatorParameters.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/Coordinator/SpaceCreationCoordinatorParameters.swift index f965b81ab..a78eebcfb 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/Coordinator/SpaceCreationCoordinatorParameters.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/Coordinator/SpaceCreationCoordinatorParameters.swift @@ -22,7 +22,6 @@ import Foundation /// SpaceCreationCoordinator input parameters struct SpaceCreationCoordinatorParameters { - /// The Matrix session let session: MXSession @@ -30,7 +29,7 @@ struct SpaceCreationCoordinatorParameters { let parentSpaceId: String? /// Parameters needed to create the new space - let creationParameters: SpaceCreationParameters = SpaceCreationParameters() + let creationParameters = SpaceCreationParameters() /// The navigation router that manage physical navigation let navigationRouter: NavigationRouterType diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Coordinator/SpaceCreationEmailInvitesCoordinator.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Coordinator/SpaceCreationEmailInvitesCoordinator.swift index 986f03b35..28792056f 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Coordinator/SpaceCreationEmailInvitesCoordinator.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Coordinator/SpaceCreationEmailInvitesCoordinator.swift @@ -17,11 +17,10 @@ */ import Foundation -import UIKit import SwiftUI +import UIKit final class SpaceCreationEmailInvitesCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -75,7 +74,7 @@ final class SpaceCreationEmailInvitesCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.spaceCreationEmailInvitesHostingController + spaceCreationEmailInvitesHostingController } // MARK: - Identity service @@ -90,34 +89,34 @@ final class SpaceCreationEmailInvitesCoordinator: Coordinator, Presentable { let presenter = ServiceTermsModalCoordinatorBridgePresenter(session: parameters.session, baseUrl: baseUrl, serviceType: MXServiceTypeIdentityService, accessToken: accessToken) presenter.delegate = self - presenter.present(from: self.toPresentable(), animated: true) + presenter.present(from: toPresentable(), animated: true) serviceTermsModalCoordinatorBridgePresenter = presenter } private func showIdentityServiceFailure(_ error: Error?) { let alertController = UIAlertController(title: VectorL10n.findYourContactsIdentityServiceError, message: nil, preferredStyle: .alert) alertController.addAction(UIAlertAction(title: VectorL10n.ok, style: .default, handler: nil)) - self.toPresentable().present(alertController, animated: true, completion: nil); + toPresentable().present(alertController, animated: true, completion: nil) } } extension SpaceCreationEmailInvitesCoordinator: ServiceTermsModalCoordinatorBridgePresenterDelegate { func serviceTermsModalCoordinatorBridgePresenterDelegateDidAccept(_ coordinatorBridgePresenter: ServiceTermsModalCoordinatorBridgePresenter) { coordinatorBridgePresenter.dismiss(animated: true) { - self.serviceTermsModalCoordinatorBridgePresenter = nil; + self.serviceTermsModalCoordinatorBridgePresenter = nil self.callback?(.done) } } func serviceTermsModalCoordinatorBridgePresenterDelegateDidDecline(_ coordinatorBridgePresenter: ServiceTermsModalCoordinatorBridgePresenter, session: MXSession) { coordinatorBridgePresenter.dismiss(animated: true) { - self.serviceTermsModalCoordinatorBridgePresenter = nil; + self.serviceTermsModalCoordinatorBridgePresenter = nil } } func serviceTermsModalCoordinatorBridgePresenterDelegateDidClose(_ coordinatorBridgePresenter: ServiceTermsModalCoordinatorBridgePresenter) { coordinatorBridgePresenter.dismiss(animated: true) { - self.serviceTermsModalCoordinatorBridgePresenter = nil; + self.serviceTermsModalCoordinatorBridgePresenter = nil } } } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Coordinator/SpaceCreationEmailInvitesCoordinatorParameters.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Coordinator/SpaceCreationEmailInvitesCoordinatorParameters.swift index af2ac696c..3b2d32f78 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Coordinator/SpaceCreationEmailInvitesCoordinatorParameters.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Coordinator/SpaceCreationEmailInvitesCoordinatorParameters.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationEmailInvites SpaceCreationEmailInvites -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesCoordinatorAction.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesCoordinatorAction.swift index cec48fc61..5eb47645f 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesCoordinatorAction.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesCoordinatorAction.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesStateAction.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesStateAction.swift index ead48ebf2..b266fbfb7 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesStateAction.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesStateAction.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationEmailInvites SpaceCreationEmailInvites -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesViewAction.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesViewAction.swift index 0f08acea8..b2fbfc34f 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesViewAction.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesViewAction.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationEmailInvites SpaceCreationEmailInvites -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesViewModelBindings.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesViewModelBindings.swift index 531689fa1..39b560c62 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesViewModelBindings.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesViewModelBindings.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesViewModelResult.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesViewModelResult.swift index d4f55e4a3..06bf52215 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesViewModelResult.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesViewModelResult.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationEmailInvites SpaceCreationEmailInvites -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesViewState.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesViewState.swift index e3028134f..ee7d48e08 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesViewState.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Model/SpaceCreationEmailInvitesViewState.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationEmailInvites SpaceCreationEmailInvites -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Service/MatrixSDK/SpaceCreationEmailInvitesService.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Service/MatrixSDK/SpaceCreationEmailInvitesService.swift index e011cbc59..e49d6030a 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Service/MatrixSDK/SpaceCreationEmailInvitesService.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Service/MatrixSDK/SpaceCreationEmailInvitesService.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationEmailInvites SpaceCreationEmailInvites -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,11 +16,10 @@ // limitations under the License. // -import Foundation import Combine +import Foundation class SpaceCreationEmailInvitesService: SpaceCreationEmailInvitesServiceProtocol { - private let session: MXSession private(set) var isLoadingSubject: CurrentValueSubject @@ -37,12 +36,12 @@ class SpaceCreationEmailInvitesService: SpaceCreationEmailInvitesServiceProtocol } func validate(_ emailAddresses: [String]) -> [Bool] { - return emailAddresses.map { $0.isEmpty || MXTools.isEmailAddress($0) } + emailAddresses.map { $0.isEmpty || MXTools.isEmailAddress($0) } } func prepareIdentityService(prepared: ((String?, String?) -> Void)?, failure: ((Error?) -> Void)?) { isLoadingSubject.send(true) - session.prepareIdentityServiceForTerms(withDefault: RiotSettings.shared.identityServerUrlString) { [weak self] session, baseURL, accessToken in + session.prepareIdentityServiceForTerms(withDefault: RiotSettings.shared.identityServerUrlString) { [weak self] _, baseURL, accessToken in self?.isLoadingSubject.send(false) prepared?(baseURL, accessToken) } failure: { [weak self] error in diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Service/Mock/MockSpaceCreationEmailInvitesScreenState.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Service/Mock/MockSpaceCreationEmailInvitesScreenState.swift index 09a3d4b82..0b70a8746 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Service/Mock/MockSpaceCreationEmailInvitesScreenState.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Service/Mock/MockSpaceCreationEmailInvitesScreenState.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationEmailInvites SpaceCreationEmailInvites -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -41,7 +41,7 @@ enum MockSpaceCreationEmailInvitesScreenState: MockScreenState, CaseIterable { } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let creationParams = SpaceCreationParameters() let service: MockSpaceCreationEmailInvitesService switch self { diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Service/Mock/MockSpaceCreationEmailInvitesService.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Service/Mock/MockSpaceCreationEmailInvitesService.swift index a34a9b801..5c308f044 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Service/Mock/MockSpaceCreationEmailInvitesService.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Service/Mock/MockSpaceCreationEmailInvitesService.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationEmailInvites SpaceCreationEmailInvites -// +// // 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 class MockSpaceCreationEmailInvitesService: SpaceCreationEmailInvitesServiceProtocol { var isLoadingSubject: CurrentValueSubject @@ -25,16 +25,16 @@ class MockSpaceCreationEmailInvitesService: SpaceCreationEmailInvitesServiceProt private let defaultValidation: Bool var isIdentityServiceReady: Bool { - return true + true } init(defaultValidation: Bool, isLoading: Bool) { self.defaultValidation = defaultValidation - self.isLoadingSubject = CurrentValueSubject(isLoading) + isLoadingSubject = CurrentValueSubject(isLoading) } func validate(_ emailAddresses: [String]) -> [Bool] { - return emailAddresses.map { _ in defaultValidation } + emailAddresses.map { _ in defaultValidation } } func prepareIdentityService(prepared: ((String?, String?) -> Void)?, failure: ((Error?) -> Void)?) { diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Service/SpaceCreationEmailInvitesServiceProtocol.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Service/SpaceCreationEmailInvitesServiceProtocol.swift index c92a2cd8d..cae561374 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Service/SpaceCreationEmailInvitesServiceProtocol.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Service/SpaceCreationEmailInvitesServiceProtocol.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationEmailInvites SpaceCreationEmailInvites -// +// // 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 SpaceCreationEmailInvitesServiceProtocol { var isIdentityServiceReady: Bool { get } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Test/UI/SpaceCreationEmailInvitesUITests.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Test/UI/SpaceCreationEmailInvitesUITests.swift index 897230312..9397206b4 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Test/UI/SpaceCreationEmailInvitesUITests.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Test/UI/SpaceCreationEmailInvitesUITests.swift @@ -16,8 +16,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class SpaceCreationEmailInvitesUITests: MockScreenTestCase { func testDefaultEmailValues() { diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Test/Unit/SpaceCreationEmailInvitesViewModelTests.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Test/Unit/SpaceCreationEmailInvitesViewModelTests.swift index bbea5e3e2..b2477d145 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Test/Unit/SpaceCreationEmailInvitesViewModelTests.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/Test/Unit/SpaceCreationEmailInvitesViewModelTests.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationEmailInvites SpaceCreationEmailInvites -// +// // 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 Combine +import XCTest @testable import RiotSwiftUI diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/View/SpaceCreationEmailInvites.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/View/SpaceCreationEmailInvites.swift index 80f9abe87..ddaca92f1 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/View/SpaceCreationEmailInvites.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/View/SpaceCreationEmailInvites.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationEmailInvites SpaceCreationEmailInvites -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ import SwiftUI struct SpaceCreationEmailInvites: View { - // MARK: - Properties @ObservedObject var viewModel: SpaceCreationEmailInvitesViewModel.Context @@ -85,7 +84,7 @@ struct SpaceCreationEmailInvites: View { private var formView: some View { VStack { VStack(spacing: 20) { - ForEach(viewModel.emailInvites.indices) { index in + ForEach(viewModel.emailInvites.indices, id: \.self) { index in RoundedBorderTextField(title: VectorL10n.spacesCreationEmailInvitesEmailTitle, placeHolder: VectorL10n.spacesCreationEmailInvitesEmailTitle, text: $viewModel.emailInvites[index], footerText: viewModel.viewState.emailAddressesValid[index] ? nil : VectorL10n.authInvalidEmail, isError: !viewModel.viewState.emailAddressesValid[index], configuration: UIKitTextInputConfiguration(keyboardType: .emailAddress, returnKeyType: index < viewModel.emailInvites.endIndex - 1 ? .next : .done, autocapitalizationType: .none, autocorrectionType: .no)) .accessibility(identifier: "emailTextField") } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/ViewModel/SpaceCreationEmailInvitesViewModel.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/ViewModel/SpaceCreationEmailInvitesViewModel.swift index 55a2c6750..239dadb6f 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/ViewModel/SpaceCreationEmailInvitesViewModel.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/ViewModel/SpaceCreationEmailInvitesViewModel.swift @@ -16,14 +16,13 @@ // limitations under the License. // -import SwiftUI import Combine +import SwiftUI typealias SpaceCreationEmailInvitesViewModelType = StateStoreViewModel + SpaceCreationEmailInvitesStateAction, + SpaceCreationEmailInvitesViewAction> class SpaceCreationEmailInvitesViewModel: SpaceCreationEmailInvitesViewModelType, SpaceCreationEmailInvitesViewModelProtocol { - // MARK: - Properties // MARK: Private @@ -86,14 +85,14 @@ class SpaceCreationEmailInvitesViewModel: SpaceCreationEmailInvitesViewModelType } private func done() { - self.creationParameters.emailInvites = self.context.emailInvites - self.creationParameters.inviteType = .email - let emailAddressesValidity = service.validate(self.context.emailInvites) + creationParameters.emailInvites = context.emailInvites + creationParameters.inviteType = .email + let emailAddressesValidity = service.validate(context.emailInvites) dispatch(action: .updateEmailValidity(emailAddressesValidity)) - if self.context.emailInvites.reduce(true, { $0 && $1.isEmpty }) { + if context.emailInvites.reduce(true, { $0 && $1.isEmpty }) { completion?(.done) - } else if emailAddressesValidity.reduce(true, { $0 && $1}) { + } else if emailAddressesValidity.reduce(true, { $0 && $1 }) { if service.isIdentityServiceReady { completion?(.done) } else { diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/ViewModel/SpaceCreationEmailInvitesViewModelProtocol.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/ViewModel/SpaceCreationEmailInvitesViewModelProtocol.swift index 88c154805..72b28d33b 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/ViewModel/SpaceCreationEmailInvitesViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationEmailInvites/ViewModel/SpaceCreationEmailInvitesViewModelProtocol.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationEmailInvites SpaceCreationEmailInvites -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ import Foundation protocol SpaceCreationEmailInvitesViewModelProtocol { - var completion: ((SpaceCreationEmailInvitesViewModelResult) -> Void)? { get set } var context: SpaceCreationEmailInvitesViewModelType.Context { get } } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMatrixItemChooser/Coordinator/SpaceCreationMatrixItemChooserViewProvider.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMatrixItemChooser/Coordinator/SpaceCreationMatrixItemChooserViewProvider.swift index a4e80561f..f22a4a978 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMatrixItemChooser/Coordinator/SpaceCreationMatrixItemChooserViewProvider.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMatrixItemChooser/Coordinator/SpaceCreationMatrixItemChooserViewProvider.swift @@ -18,6 +18,6 @@ import SwiftUI class SpaceCreationMatrixItemChooserViewProvider: MatrixItemChooserCoordinatorViewProvider { func view(with viewModel: MatrixItemChooserViewModelType.Context) -> AnyView { - return AnyView(SpaceCreationMatrixItemChooser(viewModel: viewModel)) + AnyView(SpaceCreationMatrixItemChooser(viewModel: viewModel)) } } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMatrixItemChooser/Service/MatrixSDK/SpaceCreationAddRoomsItemsProcessor.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMatrixItemChooser/Service/MatrixSDK/SpaceCreationAddRoomsItemsProcessor.swift index 4638d585e..03c32f7f7 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMatrixItemChooser/Service/MatrixSDK/SpaceCreationAddRoomsItemsProcessor.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMatrixItemChooser/Service/MatrixSDK/SpaceCreationAddRoomsItemsProcessor.swift @@ -17,7 +17,6 @@ import Foundation class SpaceCreationAddRoomsItemsProcessor: MatrixItemChooserProcessorProtocol { - // MARK: Private private let creationParams: SpaceCreationParameters @@ -41,8 +40,7 @@ class SpaceCreationAddRoomsItemsProcessor: MatrixItemChooserProcessorProtocol { completion(.success(())) } - func isItemIncluded(_ item: (MatrixListItemData)) -> Bool { - return true + func isItemIncluded(_ item: MatrixListItemData) -> Bool { + true } - } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMatrixItemChooser/Service/MatrixSDK/SpaceCreationInviteUsersItemsProcessor.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMatrixItemChooser/Service/MatrixSDK/SpaceCreationInviteUsersItemsProcessor.swift index 327f6589b..5fb15d88a 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMatrixItemChooser/Service/MatrixSDK/SpaceCreationInviteUsersItemsProcessor.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMatrixItemChooser/Service/MatrixSDK/SpaceCreationInviteUsersItemsProcessor.swift @@ -17,7 +17,6 @@ import Foundation class SpaceCreationInviteUsersItemsProcessor: MatrixItemChooserProcessorProtocol { - // MARK: Private private let creationParams: SpaceCreationParameters @@ -42,8 +41,7 @@ class SpaceCreationInviteUsersItemsProcessor: MatrixItemChooserProcessorProtocol completion(.success(())) } - func isItemIncluded(_ item: (MatrixListItemData)) -> Bool { - return true + func isItemIncluded(_ item: MatrixListItemData) -> Bool { + true } - } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMatrixItemChooser/View/SpaceCreationMatrixItemChooser.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMatrixItemChooser/View/SpaceCreationMatrixItemChooser.swift index 856b5c6c1..f1d6f5453 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMatrixItemChooser/View/SpaceCreationMatrixItemChooser.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMatrixItemChooser/View/SpaceCreationMatrixItemChooser.swift @@ -17,7 +17,6 @@ import SwiftUI struct SpaceCreationMatrixItemChooser: View { - // MARK: Properties @ObservedObject var viewModel: MatrixItemChooserViewModel.Context @@ -52,7 +51,6 @@ struct SpaceCreationMatrixItemChooser: View { } } - @ViewBuilder private var footerView: some View { ThemableButton(icon: nil, title: viewModel.viewState.selectedItemIds.isEmpty ? VectorL10n.skip : VectorL10n.next) { diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Coordinator/SpaceCreationMenuCoordinator.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Coordinator/SpaceCreationMenuCoordinator.swift index 286f9b2e2..8d590936d 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Coordinator/SpaceCreationMenuCoordinator.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Coordinator/SpaceCreationMenuCoordinator.swift @@ -17,11 +17,10 @@ */ import Foundation -import UIKit import SwiftUI +import UIKit final class SpaceCreationMenuCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -63,12 +62,11 @@ final class SpaceCreationMenuCoordinator: Coordinator, Presentable { self.callback?(.cancel) case .back: self.callback?(.back) - break } } } func toPresentable() -> UIViewController { - return self.spaceCreationMenuHostingController + spaceCreationMenuHostingController } } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Coordinator/SpaceCreationMenuCoordinatorParamaters.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Coordinator/SpaceCreationMenuCoordinatorParamaters.swift index 099c12b68..51c8108b3 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Coordinator/SpaceCreationMenuCoordinatorParamaters.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Coordinator/SpaceCreationMenuCoordinatorParamaters.swift @@ -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"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuCoordinatorAction.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuCoordinatorAction.swift index c3715ee52..148623a05 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuCoordinatorAction.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuCoordinatorAction.swift @@ -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"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuRoom.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuRoom.swift index 27c95e48c..1d16fa0a2 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuRoom.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuRoom.swift @@ -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"); @@ -38,4 +38,4 @@ struct SpaceCreationMenuRoomOption { let detail: String } -extension SpaceCreationMenuRoomOption: Identifiable, Equatable {} +extension SpaceCreationMenuRoomOption: Identifiable, Equatable { } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuStateAction.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuStateAction.swift index 3109b348b..15c7a4ffc 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuStateAction.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuStateAction.swift @@ -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,5 +19,4 @@ import Foundation /// Actions to be performed on the `ViewModel` State -enum SpaceCreationMenuStateAction { -} +enum SpaceCreationMenuStateAction { } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuViewAction.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuViewAction.swift index 7d0afb05e..35e44e4a1 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuViewAction.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuViewAction.swift @@ -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"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuViewModelAction.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuViewModelAction.swift index 079ddab25..f8e415d34 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuViewModelAction.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuViewModelAction.swift @@ -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"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuViewState.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuViewState.swift index d25f2bf1a..fd71eaf89 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuViewState.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationMenuViewState.swift @@ -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"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationParameters.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationParameters.swift index a9c2036f4..a07e840de 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationParameters.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Model/SpaceCreationParameters.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,26 +28,31 @@ class SpaceCreationParameters { isModified = true } } + var topic: String? { didSet { isModified = true } } + var address: String? { didSet { isModified = true } } + var userDefinedAddress: String? { didSet { isModified = true } } - var isPublic: Bool = false { + + var isPublic = false { didSet { isModified = true } } + var showAddress: Bool { isPublic } @@ -57,7 +62,8 @@ class SpaceCreationParameters { isModified = true } } - var isShared: Bool = false { + + var isShared = false { didSet { isModified = true } @@ -84,22 +90,26 @@ class SpaceCreationParameters { isModified = true } } + var userDefinedEmailInvites: [String] { - return emailInvites.filter { address in - return !address.isEmpty + emailInvites.filter { address in + !address.isEmpty } } + var userIdInvites: [String] = [] { didSet { isModified = true } } + var inviteType: SpaceCreationInviteType = .email { didSet { isModified = true } } - var isModified: Bool = false + + var isModified = false } struct SpaceCreationNewRoom: Equatable { @@ -107,6 +117,6 @@ struct SpaceCreationNewRoom: Equatable { var defaultName: String static func == (lhs: Self, rhs: Self) -> Bool { - return lhs.defaultName == rhs.defaultName && lhs.name == rhs.name + lhs.defaultName == rhs.defaultName && lhs.name == rhs.name } } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Test/UI/SpaceCreationMenuUITests.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Test/UI/SpaceCreationMenuUITests.swift index 251fb5429..d6c5d47df 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Test/UI/SpaceCreationMenuUITests.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Test/UI/SpaceCreationMenuUITests.swift @@ -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,14 +16,14 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class SpaceCreationMenuUITests: MockScreenTestCase { func testSpaceCreationMenuOptions() { app.goToScreenWithIdentifier(MockSpaceCreationMenuScreenState.options.title) - let optionButtonCount = app.buttons.matching(identifier:"optionButton").count + let optionButtonCount = app.buttons.matching(identifier: "optionButton").count XCTAssertEqual(optionButtonCount, 2) let titleText = app.staticTexts["titleText"] diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Test/Unit/SpaceCreationMenuViewModelTests.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Test/Unit/SpaceCreationMenuViewModelTests.swift index 72c694556..9c3561724 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Test/Unit/SpaceCreationMenuViewModelTests.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/Test/Unit/SpaceCreationMenuViewModelTests.swift @@ -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,14 +16,13 @@ // limitations under the License. // -import XCTest import Combine +import XCTest @testable import RiotSwiftUI class SpaceCreationMenuViewModelTests: XCTestCase { - private enum Constants { - } + private enum Constants { } let navTitle = VectorL10n.spacesCreateSpaceTitle var creationParams = SpaceCreationParameters() diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/View/SpaceCreationMenu.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/View/SpaceCreationMenu.swift index fc1c80593..aac7cb983 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/View/SpaceCreationMenu.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/View/SpaceCreationMenu.swift @@ -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 SwiftUI struct SpaceCreationMenu: View { - // MARK: - Properties @ObservedObject var viewModel: SpaceCreationMenuViewModelType.Context @@ -100,7 +99,6 @@ struct SpaceCreationMenu: View { // MARK: - Previews struct SpaceCreationMenu_Previews: PreviewProvider { - static let stateRenderer = MockSpaceCreationMenuScreenState.stateRenderer static var previews: some View { diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/ViewModel/SpaceCreationMenuViewModel.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/ViewModel/SpaceCreationMenuViewModel.swift index 62b48d3a7..ffbf21dac 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/ViewModel/SpaceCreationMenuViewModel.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/ViewModel/SpaceCreationMenuViewModel.swift @@ -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,14 +16,13 @@ // limitations under the License. // -import SwiftUI import Combine +import SwiftUI typealias SpaceCreationMenuViewModelType = StateStoreViewModel + SpaceCreationMenuStateAction, + SpaceCreationMenuViewAction> class SpaceCreationMenuViewModel: SpaceCreationMenuViewModelType, SpaceCreationMenuViewModelProtocol { - // MARK: - Properties // MARK: Private @@ -43,7 +42,7 @@ class SpaceCreationMenuViewModel: SpaceCreationMenuViewModelType, SpaceCreationM } private static func defaultState(navTitle: String?, creationParams: SpaceCreationParameters, title: String, detail: String, options: [SpaceCreationMenuRoomOption]) -> SpaceCreationMenuViewState { - var navigationTitle: String = "" + var navigationTitle = "" if let navTitle = navTitle { navigationTitle = navTitle } else { @@ -60,13 +59,13 @@ class SpaceCreationMenuViewModel: SpaceCreationMenuViewModelType, SpaceCreationM case .didSelectOption(let optionId): switch optionId { case .publicSpace: - self.creationParams.isPublic = true + creationParams.isPublic = true case .privateSpace: - self.creationParams.isPublic = false + creationParams.isPublic = false case .ownedPrivateSpace: - self.creationParams.isShared = false + creationParams.isShared = false case .sharedPrivateSpace: - self.creationParams.isShared = true + creationParams.isShared = true } didSelectOption(withId: optionId) diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/ViewModel/SpaceCreationMenuViewModelProtocol.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/ViewModel/SpaceCreationMenuViewModelProtocol.swift index f3660dd08..29fd9b10a 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/ViewModel/SpaceCreationMenuViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationMenu/ViewModel/SpaceCreationMenuViewModelProtocol.swift @@ -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"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Coordinator/SpaceCreationPostProcessCoordinator.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Coordinator/SpaceCreationPostProcessCoordinator.swift index f5c46f7e6..a1838458d 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Coordinator/SpaceCreationPostProcessCoordinator.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Coordinator/SpaceCreationPostProcessCoordinator.swift @@ -17,11 +17,10 @@ */ import Foundation -import UIKit import SwiftUI +import UIKit final class SpaceCreationPostProcessCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -50,6 +49,7 @@ final class SpaceCreationPostProcessCoordinator: Coordinator, Presentable { } // MARK: - Public + func start() { MXLog.debug("[SpaceCreationPostProcessCoordinator] did start.") spaceCreationPostProcessViewModel.completion = { [weak self] result in @@ -65,6 +65,6 @@ final class SpaceCreationPostProcessCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.spaceCreationPostProcessHostingController + spaceCreationPostProcessHostingController } } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Coordinator/SpaceCreationPostProcessCoordinatorParameters.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Coordinator/SpaceCreationPostProcessCoordinatorParameters.swift index 68a99c879..b71b1f773 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Coordinator/SpaceCreationPostProcessCoordinatorParameters.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Coordinator/SpaceCreationPostProcessCoordinatorParameters.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationPostProcess SpaceCreationPostProcess -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessCoordinatorAction.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessCoordinatorAction.swift index d384c3a5d..5d27c5fa2 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessCoordinatorAction.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessCoordinatorAction.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessStateAction.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessStateAction.swift index 31003ed4e..880de2a4d 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessStateAction.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessStateAction.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationPostProcess SpaceCreationPostProcess -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessTask.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessTask.swift index 6c2d8baf1..c02e27f55 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessTask.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessTask.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -38,11 +38,12 @@ struct SpaceCreationPostProcessTask: Equatable { let title: String var state: SpaceCreationPostProcessTaskState var isFinished: Bool { - return state == .failure || state == .success + state == .failure || state == .success } + var subTasks: [SpaceCreationPostProcessTask] = [] static func == (lhs: SpaceCreationPostProcessTask, rhs: SpaceCreationPostProcessTask) -> Bool { - return lhs.type == rhs.type && lhs.title == rhs.title && lhs.state == rhs.state && lhs.subTasks == lhs.subTasks + lhs.type == rhs.type && lhs.title == rhs.title && lhs.state == rhs.state && lhs.subTasks == lhs.subTasks } } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessViewAction.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessViewAction.swift index dc7397f46..ad1a80a15 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessViewAction.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessViewAction.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationPostProcess SpaceCreationPostProcess -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessViewModelResult.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessViewModelResult.swift index 38ee7179d..39221a3c1 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessViewModelResult.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessViewModelResult.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationPostProcess SpaceCreationPostProcess -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessViewState.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessViewState.swift index 311b2fcba..1fe80fff8 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessViewState.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Model/SpaceCreationPostProcessViewState.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationPostProcess SpaceCreationPostProcess -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Service/MatrixSDK/SpaceCreationPostProcessService.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Service/MatrixSDK/SpaceCreationPostProcessService.swift index 99a45c3cd..4fd4fe06d 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Service/MatrixSDK/SpaceCreationPostProcessService.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Service/MatrixSDK/SpaceCreationPostProcessService.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationPostProcess SpaceCreationPostProcess -// +// // 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 SpaceCreationPostProcessService: SpaceCreationPostProcessServiceProtocol { - // MARK: - Properties // MARK: Private @@ -39,19 +38,16 @@ class SpaceCreationPostProcessService: SpaceCreationPostProcessServiceProtocol { createdSpaceId = createdSpace?.spaceId } } + private var createdRoomsByName: [String: MXRoom] = [:] private var currentSubTaskIndex = 0 private var processingQueue = DispatchQueue(label: "io.element.MXSpace.processingQueue", attributes: .concurrent) - private lazy var stateEventBuilder: MXRoomInitialStateEventBuilder = { - return MXRoomInitialStateEventBuilder() - }() + private lazy var stateEventBuilder = MXRoomInitialStateEventBuilder() - private lazy var mediaUploader: MXMediaLoader = { - return MXMediaManager.prepareUploader(withMatrixSession: session, initialRange: 0, andRange: 1.0) - }() + private lazy var mediaUploader: MXMediaLoader = MXMediaManager.prepareUploader(withMatrixSession: session, initialRange: 0, andRange: 1.0) // MARK: Public @@ -61,8 +57,9 @@ class SpaceCreationPostProcessService: SpaceCreationPostProcessServiceProtocol { let alias = creationParams.userDefinedAddress.isEmptyOrNil ? creationParams.address : creationParams.userDefinedAddress return AvatarInput(mxContentUri: alias, matrixItemId: "", displayName: creationParams.name) } + var avatarImage: UIImage? { - return creationParams.userSelectedAvatar + creationParams.userSelectedAvatar } // MARK: - Setup @@ -71,18 +68,17 @@ class SpaceCreationPostProcessService: SpaceCreationPostProcessServiceProtocol { self.session = session self.parentSpaceId = parentSpaceId self.creationParams = creationParams - self.tasks = Self.tasks(with: creationParams) - self.tasksSubject = CurrentValueSubject(tasks) + tasks = Self.tasks(with: creationParams) + tasksSubject = CurrentValueSubject(tasks) } - deinit { - } + deinit { } // MARK: - Public func run() { - self.isRetry = self.currentTaskIndex > 0 - self.currentTaskIndex = -1 + isRetry = currentTaskIndex > 0 + currentTaskIndex = -1 runNextTask() } @@ -106,13 +102,13 @@ class SpaceCreationPostProcessService: SpaceCreationPostProcessServiceProtocol { tasks.append(SpaceCreationPostProcessTask(type: .addRooms, title: VectorL10n.spacesCreationPostProcessAddingRooms("\(addedRoomIds.count)"), state: .none, subTasks: subTasks)) } } else { - tasks.append(contentsOf: creationParams.newRooms.compactMap({ room in + tasks.append(contentsOf: creationParams.newRooms.compactMap { room in guard !room.name.isEmpty else { return nil } return SpaceCreationPostProcessTask(type: .createRoom(room.name), title: VectorL10n.spacesCreationPostProcessCreatingRoom(room.name), state: .none) - })) + }) } if creationParams.inviteType == .email { @@ -183,7 +179,7 @@ class SpaceCreationPostProcessService: SpaceCreationPostProcessServiceProtocol { return } - parentSpace.addChild(roomId: createdSpaceId) { [weak self] response in + parentSpace.addChild(roomId: createdSpaceId) { [weak self] _ in guard let self = self else { return } self.updateCurrentTask(with: .success) @@ -194,45 +190,45 @@ class SpaceCreationPostProcessService: SpaceCreationPostProcessServiceProtocol { } private func uploadAvatar(andUpdate task: SpaceCreationPostProcessTask) { - self.updateCurrentTask(with: .started) + updateCurrentTask(with: .started) - guard let avatar = creationParams.userSelectedAvatar, let spaceRoom = self.createdSpace?.room else { - self.updateCurrentTask(with: .success) - self.runNextTask() + guard let avatar = creationParams.userSelectedAvatar, let spaceRoom = createdSpace?.room else { + updateCurrentTask(with: .success) + runNextTask() return } 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 } - guard let urlString = urlString else { return } - guard let url = URL(string: urlString) else { return } + success: { [weak self] urlString in + guard let self = self else { return } + guard let urlString = urlString else { return } + guard let url = URL(string: urlString) else { return } - self.setAvatar(ofRoom: spaceRoom, withURL: url, andUpdate: task) + self.setAvatar(ofRoom: spaceRoom, withURL: url, andUpdate: task) }, - failure: { [weak self] (error) in - guard let self = self else { return } + failure: { [weak self] _ in + guard let self = self else { return } - self.updateCurrentTask(with: .failure) - self.runNextTask() + self.updateCurrentTask(with: .failure) + self.runNextTask() }) } private func setAvatar(ofRoom room: MXRoom, withURL url: URL, andUpdate task: SpaceCreationPostProcessTask) { updateCurrentTask(with: .started) - room.setAvatar(url: url) { [weak self] (response) in + room.setAvatar(url: url) { [weak self] response in guard let self = self else { return } - self.updateCurrentTask(with: response.isSuccess ? .success: .failure) + self.updateCurrentTask(with: response.isSuccess ? .success : .failure) self.runNextTask() } } private func createRoom(withName roomName: String, andUpdate task: SpaceCreationPostProcessTask) { - guard let createdSpace = self.createdSpace else { + guard let createdSpace = createdSpace else { updateCurrentTask(with: .failure) runNextTask() return @@ -257,7 +253,7 @@ class SpaceCreationPostProcessService: SpaceCreationPostProcessServiceProtocol { } private func addToSpace(room: MXRoom) { - guard let createdSpace = self.createdSpace else { + guard let createdSpace = createdSpace else { updateCurrentTask(with: .failure) runNextTask() return @@ -282,7 +278,7 @@ class SpaceCreationPostProcessService: SpaceCreationPostProcessServiceProtocol { } private func inviteNextUserByEmail() { - guard let createdSpace = self.createdSpace, let room = createdSpace.room else { + guard let createdSpace = createdSpace, let room = createdSpace.room else { updateCurrentTask(with: .failure) runNextTask() return @@ -291,7 +287,7 @@ class SpaceCreationPostProcessService: SpaceCreationPostProcessServiceProtocol { currentSubTaskIndex += 1 guard currentSubTaskIndex < tasks[currentTaskIndex].subTasks.count else { - let isSuccess = tasks[currentTaskIndex].subTasks.reduce(true, { $0 && $1.state == .success }) + let isSuccess = tasks[currentTaskIndex].subTasks.reduce(true) { $0 && $1.state == .success } updateCurrentTask(with: isSuccess ? .success : .failure) runNextTask() return @@ -306,7 +302,7 @@ class SpaceCreationPostProcessService: SpaceCreationPostProcessServiceProtocol { } private func addNextExistingRoom() { - guard let createdSpace = self.createdSpace else { + guard let createdSpace = createdSpace else { updateCurrentTask(with: .failure) runNextTask() return @@ -315,7 +311,7 @@ class SpaceCreationPostProcessService: SpaceCreationPostProcessServiceProtocol { currentSubTaskIndex += 1 guard currentSubTaskIndex < tasks[currentTaskIndex].subTasks.count else { - let isSuccess = tasks[currentTaskIndex].subTasks.reduce(true, { $0 && $1.state == .success }) + let isSuccess = tasks[currentTaskIndex].subTasks.reduce(true) { $0 && $1.state == .success } updateCurrentTask(with: isSuccess ? .success : .failure) runNextTask() return @@ -351,6 +347,6 @@ class SpaceCreationPostProcessService: SpaceCreationPostProcessServiceProtocol { } tasks[currentTaskIndex].state = state - self.tasksSubject.send(tasks) + tasksSubject.send(tasks) } } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Service/Mock/MockSpaceCreationPostProcessScreenState.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Service/Mock/MockSpaceCreationPostProcessScreenState.swift index a8220d8cc..27c003b71 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Service/Mock/MockSpaceCreationPostProcessScreenState.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Service/Mock/MockSpaceCreationPostProcessScreenState.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationPostProcess SpaceCreationPostProcess -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,7 +24,6 @@ import SwiftUI enum MockSpaceCreationPostProcessScreenState: MockScreenState { static var screenStates: [MockScreenState] = [MockSpaceCreationPostProcessScreenState.running, MockSpaceCreationPostProcessScreenState.done, MockSpaceCreationPostProcessScreenState.doneWithError] - // A case for each state you want to represent // with specific, minimal associated data that will allow you // mock that screen. @@ -38,7 +37,7 @@ enum MockSpaceCreationPostProcessScreenState: MockScreenState { } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let service: MockSpaceCreationPostProcessService switch self { case .running: diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Service/Mock/MockSpaceCreationPostProcessService.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Service/Mock/MockSpaceCreationPostProcessService.swift index 4e10a9abd..514b35fab 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Service/Mock/MockSpaceCreationPostProcessService.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Service/Mock/MockSpaceCreationPostProcessService.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationPostProcess SpaceCreationPostProcess -// +// // 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 UIKit class MockSpaceCreationPostProcessService: SpaceCreationPostProcessServiceProtocol { - static let defaultTasks: [SpaceCreationPostProcessTask] = [ SpaceCreationPostProcessTask(type: .createSpace, title: "Space creation", state: .success), SpaceCreationPostProcessTask(type: .createRoom("Room#1"), title: "Room#1 creation", state: .failure), @@ -53,22 +52,22 @@ class MockSpaceCreationPostProcessService: SpaceCreationPostProcessServiceProtoc var tasksSubject: CurrentValueSubject<[SpaceCreationPostProcessTask], Never> private(set) var createdSpaceId: String? var avatar: AvatarInput { - return AvatarInput(mxContentUri: nil, matrixItemId: "", displayName: "Some space") + AvatarInput(mxContentUri: nil, matrixItemId: "", displayName: "Some space") } + var avatarImage: UIImage? { - return nil + nil } init( tasks: [SpaceCreationPostProcessTask] = defaultTasks ) { - self.tasksSubject = CurrentValueSubject<[SpaceCreationPostProcessTask], Never>(tasks) + tasksSubject = CurrentValueSubject<[SpaceCreationPostProcessTask], Never>(tasks) } func simulateUpdate(tasks: [SpaceCreationPostProcessTask]) { - self.tasksSubject.send(tasks) + tasksSubject.send(tasks) } - func run() { - } + func run() { } } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Service/SpaceCreationPostProcessServiceProtocol.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Service/SpaceCreationPostProcessServiceProtocol.swift index 7ff9e73cf..e9e4e711b 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Service/SpaceCreationPostProcessServiceProtocol.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Service/SpaceCreationPostProcessServiceProtocol.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationPostProcess SpaceCreationPostProcess -// +// // 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 import UIKit protocol SpaceCreationPostProcessServiceProtocol: AnyObject { diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Test/UI/SpaceCreationPostProcessUITests.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Test/UI/SpaceCreationPostProcessUITests.swift index 75c624772..4bfcbc424 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Test/UI/SpaceCreationPostProcessUITests.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Test/UI/SpaceCreationPostProcessUITests.swift @@ -16,8 +16,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class SpaceCreationPostProcessUITests: MockScreenTestCase { // No tests have been implemented diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Test/Unit/SpaceCreationPostProcessViewModelTests.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Test/Unit/SpaceCreationPostProcessViewModelTests.swift index cb274b1ba..6859b9565 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Test/Unit/SpaceCreationPostProcessViewModelTests.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/Test/Unit/SpaceCreationPostProcessViewModelTests.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationPostProcess SpaceCreationPostProcess -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,13 +16,12 @@ // limitations under the License. // -import XCTest import Combine +import XCTest @testable import RiotSwiftUI class SpaceCreationPostProcessViewModelTests: XCTestCase { - var service: MockSpaceCreationPostProcessService! var viewModel: SpaceCreationPostProcessViewModelProtocol! var context: SpaceCreationPostProcessViewModelType.Context! diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/View/SpaceCreationPostProcess.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/View/SpaceCreationPostProcess.swift index 3c5ad177e..38f99a935 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/View/SpaceCreationPostProcess.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/View/SpaceCreationPostProcess.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationPostProcess SpaceCreationPostProcess -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ import SwiftUI struct SpaceCreationPostProcess: View { - // MARK: - Properties // MARK: Private @@ -44,7 +43,7 @@ struct SpaceCreationPostProcess: View { .navigationBarHidden(true) .background(theme.colors.background.ignoresSafeArea()) .frame(maxHeight: .infinity) - .onAppear() { + .onAppear { viewModel.send(viewAction: .runTasks) } } @@ -62,7 +61,7 @@ struct SpaceCreationPostProcess: View { @ViewBuilder private var tasksList: some View { VStack(alignment: .leading, spacing: 11) { - ForEach(viewModel.viewState.tasks.indices) { index in + ForEach(viewModel.viewState.tasks.indices, id: \.self) { index in SpaceCreationPostProcessItem(title: viewModel.viewState.tasks[index].title, state: viewModel.viewState.tasks[index].state) } } @@ -85,7 +84,7 @@ struct SpaceCreationPostProcess: View { private var avatarView: some View { ZStack { SpaceAvatarImage(mxContentUri: viewModel.viewState.avatar.mxContentUri, matrixItemId: viewModel.viewState.avatar.matrixItemId, displayName: viewModel.viewState.avatar.displayName, size: .xLarge) - .padding(6) + .padding(6) if let image = viewModel.viewState.avatarImage { Image(uiImage: image) .resizable() @@ -95,7 +94,6 @@ struct SpaceCreationPostProcess: View { } } } - } // MARK: - Previews diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/View/SpaceCreationPostProcessItem.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/View/SpaceCreationPostProcessItem.swift index 8fe554b10..58f69884f 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/View/SpaceCreationPostProcessItem.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/View/SpaceCreationPostProcessItem.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/ViewModel/SpaceCreationPostProcessViewModel.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/ViewModel/SpaceCreationPostProcessViewModel.swift index 57a736b09..25b1a85c4 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/ViewModel/SpaceCreationPostProcessViewModel.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/ViewModel/SpaceCreationPostProcessViewModel.swift @@ -16,16 +16,13 @@ // limitations under the License. // -import SwiftUI import Combine - - +import SwiftUI typealias SpaceCreationPostProcessViewModelType = StateStoreViewModel + SpaceCreationPostProcessStateAction, + SpaceCreationPostProcessViewAction> class SpaceCreationPostProcessViewModel: SpaceCreationPostProcessViewModelType, SpaceCreationPostProcessViewModelProtocol { - // MARK: - Properties // MARK: Private @@ -40,7 +37,7 @@ class SpaceCreationPostProcessViewModel: SpaceCreationPostProcessViewModelType, // MARK: - Setup static func makeSpaceCreationPostProcessViewModel(spaceCreationPostProcessService: SpaceCreationPostProcessServiceProtocol) -> SpaceCreationPostProcessViewModelProtocol { - return SpaceCreationPostProcessViewModel(spaceCreationPostProcessService: spaceCreationPostProcessService) + SpaceCreationPostProcessViewModel(spaceCreationPostProcessService: spaceCreationPostProcessService) } private init(spaceCreationPostProcessService: SpaceCreationPostProcessServiceProtocol) { @@ -55,8 +52,8 @@ class SpaceCreationPostProcessViewModel: SpaceCreationPostProcessViewModelType, avatar: spaceCreationPostProcessService.avatar, avatarImage: spaceCreationPostProcessService.avatarImage, tasks: tasks, - isFinished: tasks.first?.state == .failure || tasks.reduce(true, { result, task in result && task.isFinished }), - errorCount: tasks.reduce(0, { result, task in result + (task.state == .failure ? 1 : 0) }) + isFinished: tasks.first?.state == .failure || tasks.reduce(true) { result, task in result && task.isFinished }, + errorCount: tasks.reduce(0) { result, task in result + (task.state == .failure ? 1 : 0) } ) } @@ -74,7 +71,7 @@ class SpaceCreationPostProcessViewModel: SpaceCreationPostProcessViewModelType, return } - if state.isFinished && state.errorCount == 0 { + if state.isFinished, state.errorCount == 0 { guard let spaceId = self.spaceCreationPostProcessService.createdSpaceId else { self.cancel() return @@ -108,11 +105,11 @@ class SpaceCreationPostProcessViewModel: SpaceCreationPostProcessViewModelType, switch action { case .updateTasks(let tasks): state.tasks = tasks - state.isFinished = tasks.first?.state == .failure || tasks.reduce(true, { result, task in result && task.isFinished }) - state.errorCount = tasks.reduce(0, { result, task in result + (task.state == .failure ? 1 : 0) }) + state.isFinished = tasks.first?.state == .failure || tasks.reduce(true) { result, task in result && task.isFinished } + state.errorCount = tasks.reduce(0) { result, task in result + (task.state == .failure ? 1 : 0) } } - NotificationCenter.default.post(name: SpaceCreationPostProcessViewModel.didUpdate, object: nil, userInfo: [SpaceCreationPostProcessViewModel.newStateKey : state]) + NotificationCenter.default.post(name: SpaceCreationPostProcessViewModel.didUpdate, object: nil, userInfo: [SpaceCreationPostProcessViewModel.newStateKey: state]) UILog.debug("[SpaceCreationPostProcessViewModel] reducer with action \(action) produced state: \(state)") } @@ -131,6 +128,7 @@ class SpaceCreationPostProcessViewModel: SpaceCreationPostProcessViewModelType, } // MARK: - MXSpaceService notification constants + extension SpaceCreationPostProcessViewModel { /// Posted once the process is finished public static let didUpdate = Notification.Name("SpaceCreationPostProcessViewModelDidUpdate") diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/ViewModel/SpaceCreationPostProcessViewModelProtocol.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/ViewModel/SpaceCreationPostProcessViewModelProtocol.swift index f71785b35..4d5ea2713 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/ViewModel/SpaceCreationPostProcessViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationPostProcess/ViewModel/SpaceCreationPostProcessViewModelProtocol.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationPostProcess SpaceCreationPostProcess -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ import Foundation protocol SpaceCreationPostProcessViewModelProtocol { - var completion: ((SpaceCreationPostProcessViewModelResult) -> Void)? { get set } static func makeSpaceCreationPostProcessViewModel(spaceCreationPostProcessService: SpaceCreationPostProcessServiceProtocol) -> SpaceCreationPostProcessViewModelProtocol var context: SpaceCreationPostProcessViewModelType.Context { get } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Coordinator/SpaceCreationRoomsCoordinator.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Coordinator/SpaceCreationRoomsCoordinator.swift index e3da21122..2e94feec2 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Coordinator/SpaceCreationRoomsCoordinator.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Coordinator/SpaceCreationRoomsCoordinator.swift @@ -17,11 +17,10 @@ */ import Foundation -import UIKit import SwiftUI +import UIKit final class SpaceCreationRoomsCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -68,6 +67,6 @@ final class SpaceCreationRoomsCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.spaceCreationRoomsHostingController + spaceCreationRoomsHostingController } } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Coordinator/SpaceCreationRoomsCoordinatorParameters.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Coordinator/SpaceCreationRoomsCoordinatorParameters.swift index 6e095f71b..04a85dcac 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Coordinator/SpaceCreationRoomsCoordinatorParameters.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Coordinator/SpaceCreationRoomsCoordinatorParameters.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationRooms SpaceCreationRooms -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsCoordinatorAction.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsCoordinatorAction.swift index 749d87bd1..7455b5aa6 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsCoordinatorAction.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsCoordinatorAction.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsPresence.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsPresence.swift index 3790e6207..052148c8d 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsPresence.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsPresence.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationRooms SpaceCreationRooms -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsStateAction.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsStateAction.swift index 3515e1250..8cfcd7660 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsStateAction.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsStateAction.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationRooms SpaceCreationRooms -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,5 +18,4 @@ import Foundation -enum SpaceCreationRoomsStateAction { -} +enum SpaceCreationRoomsStateAction { } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsViewAction.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsViewAction.swift index c7ed6ce24..a1586ca41 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsViewAction.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsViewAction.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationRooms SpaceCreationRooms -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsViewModelBindings.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsViewModelBindings.swift index f9d2ad6e7..e5f17b85a 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsViewModelBindings.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsViewModelBindings.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsViewModelResult.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsViewModelResult.swift index 8368baacc..96c036877 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsViewModelResult.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsViewModelResult.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationRooms SpaceCreationRooms -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsViewState.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsViewState.swift index 81bf820ec..7d469c314 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsViewState.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Model/SpaceCreationRoomsViewState.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationRooms SpaceCreationRooms -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Service/Mock/MockSpaceCreationRoomsScreenState.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Service/Mock/MockSpaceCreationRoomsScreenState.swift index fd5919029..3ef06a64f 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Service/Mock/MockSpaceCreationRoomsScreenState.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Service/Mock/MockSpaceCreationRoomsScreenState.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationRooms SpaceCreationRooms -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,7 +39,7 @@ enum MockSpaceCreationRoomsScreenState: MockScreenState, CaseIterable { } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let creationParams = SpaceCreationParameters() switch self { case .defaultValues: break diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Test/UI/SpaceCreationRoomsUITests.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Test/UI/SpaceCreationRoomsUITests.swift index 2dedafb37..90cdff13b 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Test/UI/SpaceCreationRoomsUITests.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Test/UI/SpaceCreationRoomsUITests.swift @@ -16,8 +16,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class SpaceCreationRoomsUITests: MockScreenTestCase { func testDefaultValues() { diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Test/Unit/SpaceCreationRoomsViewModelTests.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Test/Unit/SpaceCreationRoomsViewModelTests.swift index c09e85826..3960a2d05 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Test/Unit/SpaceCreationRoomsViewModelTests.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/Test/Unit/SpaceCreationRoomsViewModelTests.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationRooms SpaceCreationRooms -// +// // 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 Combine +import XCTest @testable import RiotSwiftUI diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/View/SpaceCreationRooms.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/View/SpaceCreationRooms.swift index 8137dce9f..fbb86d7f4 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/View/SpaceCreationRooms.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/View/SpaceCreationRooms.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationRooms SpaceCreationRooms -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ import SwiftUI struct SpaceCreationRooms: View { - // MARK: - Properties // MARK: Private @@ -50,7 +49,7 @@ struct SpaceCreationRooms: View { VStack { GeometryReader { reader in ScrollView { - ScrollViewReader { scrollViewReader in + ScrollViewReader { _ in VStack(spacing: 20) { Text(VectorL10n.spacesCreationNewRoomsTitle) .multilineTextAlignment(.center) @@ -61,8 +60,8 @@ struct SpaceCreationRooms: View { .font(theme.fonts.body) .foregroundColor(theme.colors.secondaryContent) Spacer() - ForEach(viewModel.rooms.indices) { index in - RoundedBorderTextField(title: VectorL10n.spacesCreationNewRoomsRoomNameTitle, placeHolder: viewModel.rooms[index].defaultName, text: $viewModel.rooms[index].name, configuration: UIKitTextInputConfiguration( returnKeyType: index < viewModel.rooms.endIndex - 1 ? .next : .done)) + ForEach(viewModel.rooms.indices, id: \.self) { index in + RoundedBorderTextField(title: VectorL10n.spacesCreationNewRoomsRoomNameTitle, placeHolder: viewModel.rooms[index].defaultName, text: $viewModel.rooms[index].name, configuration: UIKitTextInputConfiguration(returnKeyType: index < viewModel.rooms.endIndex - 1 ? .next : .done)) .accessibility(identifier: "roomTextField") } } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/ViewModel/SpaceCreationRoomsViewModel.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/ViewModel/SpaceCreationRoomsViewModel.swift index dfb989a80..034c7a427 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/ViewModel/SpaceCreationRoomsViewModel.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/ViewModel/SpaceCreationRoomsViewModel.swift @@ -16,16 +16,13 @@ // limitations under the License. // -import SwiftUI import Combine - - +import SwiftUI typealias SpaceCreationRoomsViewModelType = StateStoreViewModel + SpaceCreationRoomsStateAction, + SpaceCreationRoomsViewAction> class SpaceCreationRoomsViewModel: SpaceCreationRoomsViewModelType, SpaceCreationRoomsViewModelProtocol { - // MARK: - Setup // MARK: Private @@ -51,7 +48,6 @@ class SpaceCreationRoomsViewModel: SpaceCreationRoomsViewModelType, SpaceCreatio ) } - // MARK: - Public override func process(viewAction: SpaceCreationRoomsViewAction) { @@ -65,13 +61,12 @@ class SpaceCreationRoomsViewModel: SpaceCreationRoomsViewModelType, SpaceCreatio } } - override class func reducer(state: inout SpaceCreationRoomsViewState, action: SpaceCreationRoomsStateAction) { - } + override class func reducer(state: inout SpaceCreationRoomsViewState, action: SpaceCreationRoomsStateAction) { } // MARK: - Private private func done() { - self.creationParameters.newRooms = self.context.rooms + creationParameters.newRooms = context.rooms callback?(.done) } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/ViewModel/SpaceCreationRoomsViewModelProtocol.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/ViewModel/SpaceCreationRoomsViewModelProtocol.swift index f7bbd263b..dac8fbe83 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/ViewModel/SpaceCreationRoomsViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationRooms/ViewModel/SpaceCreationRoomsViewModelProtocol.swift @@ -1,6 +1,6 @@ // File created from SimpleUserProfileExample // $ createScreen.sh Spaces/SpaceCreation/SpaceCreationRooms SpaceCreationRooms -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ import Foundation protocol SpaceCreationRoomsViewModelProtocol { - var callback: ((SpaceCreationRoomsViewModelResult) -> Void)? { get set } var context: SpaceCreationRoomsViewModelType.Context { get } } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Coordinator/SpaceCreationSettingsCoordinator.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Coordinator/SpaceCreationSettingsCoordinator.swift index 9461faaae..5077e4657 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Coordinator/SpaceCreationSettingsCoordinator.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Coordinator/SpaceCreationSettingsCoordinator.swift @@ -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)) diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Coordinator/SpaceCreationSettingsCoordinatorParamaters.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Coordinator/SpaceCreationSettingsCoordinatorParamaters.swift index f79a0c749..5a865710e 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Coordinator/SpaceCreationSettingsCoordinatorParamaters.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Coordinator/SpaceCreationSettingsCoordinatorParamaters.swift @@ -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"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsAddressValidationStatus.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsAddressValidationStatus.swift index b7262a430..2457e1ae8 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsAddressValidationStatus.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsAddressValidationStatus.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsCoordinatorAction.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsCoordinatorAction.swift index b94d0d3c2..719b213f7 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsCoordinatorAction.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsCoordinatorAction.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsStateAction.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsStateAction.swift index 670015eae..33fa8b36c 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsStateAction.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsStateAction.swift @@ -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"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsViewAction.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsViewAction.swift index de2350fc9..c8d9dadcc 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsViewAction.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsViewAction.swift @@ -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"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsViewModelAction.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsViewModelAction.swift index 94b838e38..7eb605e8c 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsViewModelAction.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsViewModelAction.swift @@ -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"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsViewModelBindings.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsViewModelBindings.swift index 0a1757979..0dafd1f6c 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsViewModelBindings.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsViewModelBindings.swift @@ -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"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsViewState.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsViewState.swift index 663d968df..a61da6598 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsViewState.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Model/SpaceCreationSettingsViewState.swift @@ -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 } - diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Service/MatrixSDK/SpaceCreationSettingsService.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Service/MatrixSDK/SpaceCreationSettingsService.swift index bf5835b62..9b7e2d846 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Service/MatrixSDK/SpaceCreationSettingsService.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Service/MatrixSDK/SpaceCreationSettingsService.swift @@ -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 { diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Service/Mock/MockSpaceCreationSettingsScreenState.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Service/Mock/MockSpaceCreationSettingsScreenState.swift index cf18234d6..8738289a9 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Service/Mock/MockSpaceCreationSettingsScreenState.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Service/Mock/MockSpaceCreationSettingsScreenState.swift @@ -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)) ) } } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Service/Mock/MockSpaceCreationSettingsService.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Service/Mock/MockSpaceCreationSettingsService.swift index 5e9fa46d4..616381292 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Service/Mock/MockSpaceCreationSettingsService.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Service/Mock/MockSpaceCreationSettingsService.swift @@ -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 var avatarViewDataSubject: CurrentValueSubject var defaultAddressSubject: CurrentValueSubject 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() diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Service/SpaceCreationSettingsServiceProtocol.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Service/SpaceCreationSettingsServiceProtocol.swift index 7b594fecc..35a176ed8 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Service/SpaceCreationSettingsServiceProtocol.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Service/SpaceCreationSettingsServiceProtocol.swift @@ -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 { get } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Test/UI/SpaceCreationSettingsUITests.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Test/UI/SpaceCreationSettingsUITests.swift index f1f0e705d..685488026 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Test/UI/SpaceCreationSettingsUITests.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Test/UI/SpaceCreationSettingsUITests.swift @@ -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() { diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Test/Unit/SpaceCreationSettingsViewModelTests.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Test/Unit/SpaceCreationSettingsViewModelTests.swift index dcefa9fb7..4a0e74afd 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Test/Unit/SpaceCreationSettingsViewModelTests.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/Test/Unit/SpaceCreationSettingsViewModelTests.swift @@ -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() - override func setUpWithError() throws { creationParameters.name = "Fake" creationParameters.isPublic = true diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/View/SpaceCreationSettings.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/View/SpaceCreationSettings.swift index d8e697dcd..9135bf8cc 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/View/SpaceCreationSettings.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/View/SpaceCreationSettings.swift @@ -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)) }) diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/ViewModel/SpaceCreationSettingsViewModel.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/ViewModel/SpaceCreationSettingsViewModel.swift index 742504b41..f3aca8133 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/ViewModel/SpaceCreationSettingsViewModel.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/ViewModel/SpaceCreationSettingsViewModel.swift @@ -16,15 +16,14 @@ // limitations under the License. // -import SwiftUI import Combine +import SwiftUI typealias SpaceCreationSettingsViewModelType = StateStoreViewModel + SpaceCreationSettingsStateAction, + SpaceCreationSettingsViewAction> class SpaceCreationSettingsViewModel: SpaceCreationSettingsViewModelType, SpaceCreationSettingsViewModelProtocol { - // MARK: - Properties // MARK: Private @@ -67,7 +66,8 @@ class SpaceCreationSettingsViewModel: SpaceCreationSettingsViewModelType, SpaceC 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,7 +78,8 @@ class SpaceCreationSettingsViewModel: SpaceCreationSettingsViewModelType, SpaceC isAddressValid: validationStatus.isValid, avatar: AvatarInput(mxContentUri: nil, matrixItemId: "", displayName: nil), avatarImage: creationParameters.userSelectedAvatar, - bindings: bindings) + bindings: bindings + ) } // MARK: - Public diff --git a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/ViewModel/SpaceCreationSettingsViewModelProtocol.swift b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/ViewModel/SpaceCreationSettingsViewModelProtocol.swift index 9802bca02..aa62cc895 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/ViewModel/SpaceCreationSettingsViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceCreation/SpaceCreationSettings/ViewModel/SpaceCreationSettingsViewModelProtocol.swift @@ -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"); diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/Coordinator/SpaceSelectorBottomSheetCoordinator.swift b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/Coordinator/SpaceSelectorBottomSheetCoordinator.swift index 7237b0aa3..a6c7539c2 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/Coordinator/SpaceSelectorBottomSheetCoordinator.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/Coordinator/SpaceSelectorBottomSheetCoordinator.swift @@ -39,7 +39,6 @@ struct SpaceSelectorBottomSheetCoordinatorParameters { } final class SpaceSelectorBottomSheetCoordinator: NSObject, Coordinator, Presentable { - // MARK: - Properties private let parameters: SpaceSelectorBottomSheetCoordinatorParameters @@ -61,11 +60,11 @@ final class SpaceSelectorBottomSheetCoordinator: NSObject, Coordinator, Presenta navigationRouter: NavigationRouterType = NavigationRouter(navigationController: RiotNavigationController())) { self.parameters = parameters self.navigationRouter = navigationRouter - self.spaceIdStack = [] + spaceIdStack = [] super.init() - self.setupNavigationRouter() + setupNavigationRouter() } // MARK: - Public @@ -76,7 +75,7 @@ final class SpaceSelectorBottomSheetCoordinator: NSObject, Coordinator, Presenta } func toPresentable() -> UIViewController { - return self.navigationRouter.toPresentable() + navigationRouter.toPresentable() } // MARK: - Private @@ -84,7 +83,7 @@ final class SpaceSelectorBottomSheetCoordinator: NSObject, Coordinator, Presenta private func setupNavigationRouter() { guard #available(iOS 15.0, *) else { return } - guard let sheetController = self.navigationRouter.toPresentable().sheetPresentationController else { + guard let sheetController = navigationRouter.toPresentable().sheetPresentationController else { MXLog.debug("[SpaceSelectorBottomSheetCoordinator] setup: no sheetPresentationController found") return } @@ -94,14 +93,14 @@ final class SpaceSelectorBottomSheetCoordinator: NSObject, Coordinator, Presenta sheetController.selectedDetentIdentifier = .medium sheetController.prefersScrollingExpandsWhenScrolledToEdge = true - self.navigationRouter.toPresentable().presentationController?.delegate = self + navigationRouter.toPresentable().presentationController?.delegate = self } private func push(_ coordinator: Coordinator & Presentable) { - if self.navigationRouter.modules.isEmpty { - self.navigationRouter.setRootModule(coordinator) + if navigationRouter.modules.isEmpty { + navigationRouter.setRootModule(coordinator) } else { - self.navigationRouter.push(coordinator.toPresentable(), animated: true) { [weak self] in + navigationRouter.push(coordinator.toPresentable(), animated: true) { [weak self] in guard let self = self else { return } self.remove(childCoordinator: coordinator) @@ -145,10 +144,10 @@ final class SpaceSelectorBottomSheetCoordinator: NSObject, Coordinator, Presenta coordinator.start() - self.add(childCoordinator: coordinator) + add(childCoordinator: coordinator) if let spaceId = parentSpaceId { - self.spaceIdStack.append(spaceId) + spaceIdStack.append(spaceId) } return coordinator @@ -166,13 +165,12 @@ final class SpaceSelectorBottomSheetCoordinator: NSObject, Coordinator, Presenta self.completion?(.spaceJoined(spaceId)) case .open, .cancel, .dismiss: self.navigationRouter.popModule(animated: true) - break } } coordinator.start() - self.add(childCoordinator: coordinator) + add(childCoordinator: coordinator) return coordinator } @@ -194,9 +192,7 @@ final class SpaceSelectorBottomSheetCoordinator: NSObject, Coordinator, Presenta // MARK: - UIAdaptivePresentationControllerDelegate extension SpaceSelectorBottomSheetCoordinator: UIAdaptivePresentationControllerDelegate { - func presentationControllerDidDismiss(_ presentationController: UIPresentationController) { completion?(.cancel) } - } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/Coordinator/SpaceSelectorBottomSheetCoordinatorBridgePresenter.swift b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/Coordinator/SpaceSelectorBottomSheetCoordinatorBridgePresenter.swift index b80be9e30..425063a87 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/Coordinator/SpaceSelectorBottomSheetCoordinatorBridgePresenter.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/Coordinator/SpaceSelectorBottomSheetCoordinatorBridgePresenter.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,7 +29,6 @@ import Foundation /// Each bridge should be removed once the underlying Coordinator has been integrated by another Coordinator. @objcMembers final class SpaceSelectorBottomSheetCoordinatorBridgePresenter: NSObject { - // MARK: - Properties // MARK: Private @@ -82,7 +81,7 @@ final class SpaceSelectorBottomSheetCoordinatorBridgePresenter: NSObject { } func dismiss(animated: Bool, completion: (() -> Void)?) { - guard let coordinator = self.coordinator else { + guard let coordinator = coordinator else { return } coordinator.toPresentable().dismiss(animated: animated) { @@ -92,4 +91,3 @@ final class SpaceSelectorBottomSheetCoordinatorBridgePresenter: NSObject { } } } - diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Coordinator/SpaceSelectorCoordinator.swift b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Coordinator/SpaceSelectorCoordinator.swift index 8c13f0216..771ad0b8f 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Coordinator/SpaceSelectorCoordinator.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Coordinator/SpaceSelectorCoordinator.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import SwiftUI import CommonKit +import SwiftUI struct SpaceSelectorCoordinatorParameters { let session: MXSession @@ -38,7 +38,6 @@ struct SpaceSelectorCoordinatorParameters { } final class SpaceSelectorCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -99,7 +98,7 @@ final class SpaceSelectorCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.hostingViewController + hostingViewController } // MARK: - Private diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/MockSpaceSelectorScreenState.swift b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/MockSpaceSelectorScreenState.swift index f267ef6a9..22a613be2 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/MockSpaceSelectorScreenState.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/MockSpaceSelectorScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -38,7 +38,7 @@ enum MockSpaceSelectorScreenState: MockScreenState, CaseIterable { } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let service: MockSpaceSelectorService switch self { case .emptyList: diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Service/MatrixSDK/SpaceSelectorService.swift b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Service/MatrixSDK/SpaceSelectorService.swift index 1ba496e9b..4db35bf69 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Service/MatrixSDK/SpaceSelectorService.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Service/MatrixSDK/SpaceSelectorService.swift @@ -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 SpaceSelectorService: SpaceSelectorServiceProtocol { - // MARK: - Properties // MARK: Private @@ -65,7 +64,7 @@ class SpaceSelectorService: SpaceSelectorServiceProtocol { var itemList: [SpaceSelectorListItemData] = [] itemList.append(contentsOf: invitedSpaces) - if showHomeSpace && parentSpaceId == nil { + if showHomeSpace, parentSpaceId == nil { itemList.append(SpaceSelectorListItemData(id: SpaceSelectorConstants.homeSpaceId, icon: Asset.Images.sideMenuActionIconFeedback.image, displayName: VectorL10n.allChatsTitle, isJoined: true)) } itemList.append(contentsOf: joinedSpaces) @@ -93,14 +92,14 @@ class SpaceSelectorService: SpaceSelectorServiceProtocol { self.session = session self.parentSpaceId = parentSpaceId self.showHomeSpace = showHomeSpace - self.spaceListSubject = CurrentValueSubject([]) - self.parentSpaceNameSubject = CurrentValueSubject(nil) + spaceListSubject = CurrentValueSubject([]) + parentSpaceNameSubject = CurrentValueSubject(nil) self.selectedSpaceId = selectedSpaceId spaceListSubject.send(spaceList) parentSpaceNameSubject.send(parentSpaceName) - NotificationCenter.default.addObserver(self, selector: #selector(self.spaceServiceDidUpdate), name: MXSpaceService.didBuildSpaceGraph, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(spaceServiceDidUpdate), name: MXSpaceService.didBuildSpaceGraph, object: nil) } @objc private func spaceServiceDidUpdate() { @@ -108,7 +107,7 @@ class SpaceSelectorService: SpaceSelectorServiceProtocol { } } -fileprivate extension SpaceSelectorListItemData { +private extension SpaceSelectorListItemData { static func itemData(with space: MXSpace, notificationCounter: MXSpaceNotificationCounter) -> SpaceSelectorListItemData? { guard let summary = space.summary else { return nil @@ -116,7 +115,7 @@ fileprivate extension SpaceSelectorListItemData { let notificationState = notificationCounter.notificationState(forSpaceWithId: space.spaceId) - return SpaceSelectorListItemData(id:summary.roomId, + return SpaceSelectorListItemData(id: summary.roomId, avatar: summary.room.avatarData, displayName: summary.displayname, notificationCount: notificationState?.groupMissedDiscussionsCount ?? 0, diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Service/Mock/MockSpaceSelectorService.swift b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Service/Mock/MockSpaceSelectorService.swift index 5a3435252..590a5b849 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Service/Mock/MockSpaceSelectorService.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Service/Mock/MockSpaceSelectorService.swift @@ -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 UIKit class MockSpaceSelectorService: SpaceSelectorServiceProtocol { - static let homeItem = SpaceSelectorListItemData(id: SpaceSelectorConstants.homeSpaceId, avatar: nil, icon: UIImage(systemName: "house"), displayName: "All Chats", notificationCount: 0, highlightedNotificationCount: 0, hasSubItems: false) static let defaultSpaceList = [ homeItem, @@ -35,8 +34,8 @@ class MockSpaceSelectorService: SpaceSelectorServiceProtocol { var selectedSpaceId: String? init(spaceList: [SpaceSelectorListItemData] = defaultSpaceList, parentSpaceName: String? = nil, selectedSpaceId: String = SpaceSelectorConstants.homeSpaceId) { - self.spaceListSubject = CurrentValueSubject(spaceList) - self.parentSpaceNameSubject = CurrentValueSubject(parentSpaceName) + spaceListSubject = CurrentValueSubject(spaceList) + parentSpaceNameSubject = CurrentValueSubject(parentSpaceName) self.selectedSpaceId = selectedSpaceId } } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Service/SpaceSelectorServiceProtocol.swift b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Service/SpaceSelectorServiceProtocol.swift index 48ebec3e6..e5a17462b 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Service/SpaceSelectorServiceProtocol.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Service/SpaceSelectorServiceProtocol.swift @@ -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 protocol SpaceSelectorServiceProtocol { var spaceListSubject: CurrentValueSubject<[SpaceSelectorListItemData], Never> { get } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/SpaceSelectorModels.swift b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/SpaceSelectorModels.swift index 1a9f16bc5..7511044fb 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/SpaceSelectorModels.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/SpaceSelectorModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -76,7 +76,7 @@ struct SpaceSelectorListItemData { } } -extension SpaceSelectorListItemData: Identifiable, Equatable {} +extension SpaceSelectorListItemData: Identifiable, Equatable { } enum SpaceSelectorViewModelResult { /// Cancel button has been presed diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/SpaceSelectorViewModel.swift b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/SpaceSelectorViewModel.swift index 37b7bc787..bed0600ed 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/SpaceSelectorViewModel.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/SpaceSelectorViewModel.swift @@ -14,15 +14,14 @@ // limitations under the License. // -import SwiftUI import Combine +import SwiftUI typealias SpaceSelectorViewModelType = StateStoreViewModel + Never, + SpaceSelectorViewAction> class SpaceSelectorViewModel: SpaceSelectorViewModelType, SpaceSelectorViewModelProtocol { - // MARK: - Properties // MARK: Private @@ -36,7 +35,7 @@ class SpaceSelectorViewModel: SpaceSelectorViewModelType, SpaceSelectorViewModel // MARK: - Setup static func makeViewModel(service: SpaceSelectorServiceProtocol, showCancel: Bool) -> SpaceSelectorViewModelProtocol { - return SpaceSelectorViewModel(service: service, showCancel: showCancel) + SpaceSelectorViewModel(service: service, showCancel: showCancel) } private init(service: SpaceSelectorServiceProtocol, showCancel: Bool) { @@ -55,7 +54,7 @@ class SpaceSelectorViewModel: SpaceSelectorViewModelType, SpaceSelectorViewModel private func setupObservers() { service.spaceListSubject.sink { [weak self] spaceList in - self?.state.items = spaceList + self?.state.items = spaceList } .store(in: &cancellables) } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/SpaceSelectorViewModelProtocol.swift b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/SpaceSelectorViewModelProtocol.swift index 79263720d..ed0f477ba 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/SpaceSelectorViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/SpaceSelectorViewModelProtocol.swift @@ -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 SpaceSelectorViewModelProtocol { - var completion: ((SpaceSelectorViewModelResult) -> Void)? { get set } static func makeViewModel(service: SpaceSelectorServiceProtocol, showCancel: Bool) -> SpaceSelectorViewModelProtocol var context: SpaceSelectorViewModelType.Context { get } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Test/UI/SpaceSelectorUITests.swift b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Test/UI/SpaceSelectorUITests.swift index 020127ea3..4cbc0fcad 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Test/UI/SpaceSelectorUITests.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Test/UI/SpaceSelectorUITests.swift @@ -14,16 +14,15 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class SpaceSelectorUITests: MockScreenTestCase { - func testInitialDisplay() { app.goToScreenWithIdentifier(MockSpaceSelectorScreenState.initialList.title) let disclosureButtons = app.buttons.matching(identifier: "disclosureButton").allElementsBoundByIndex - XCTAssertEqual(disclosureButtons.count, MockSpaceSelectorService.defaultSpaceList.filter { $0.hasSubItems }.count) + XCTAssertEqual(disclosureButtons.count, MockSpaceSelectorService.defaultSpaceList.filter(\.hasSubItems).count) let notificationBadges = app.staticTexts.matching(identifier: "notificationBadge").allElementsBoundByIndex let itemsWithNotifications = MockSpaceSelectorService.defaultSpaceList.filter { $0.notificationCount > 0 || !$0.isJoined } @@ -65,5 +64,4 @@ class SpaceSelectorUITests: MockScreenTestCase { XCTAssertEqual(app.staticTexts["emptyListPlaceholderMessage"].exists, exists) XCTAssertEqual(app.buttons["createSpaceButton"].exists, exists) } - } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Test/Unit/SpaceSelectorViewModelTests.swift b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Test/Unit/SpaceSelectorViewModelTests.swift index 58d5f9304..9395349a9 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Test/Unit/SpaceSelectorViewModelTests.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/Test/Unit/SpaceSelectorViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,13 +14,12 @@ // limitations under the License. // -import XCTest import Combine +import XCTest @testable import RiotSwiftUI class SpaceSelectorViewModelTests: XCTestCase { - var service: MockSpaceSelectorService! var viewModel: SpaceSelectorViewModelProtocol! var context: SpaceSelectorViewModelType.Context! @@ -37,5 +36,4 @@ class SpaceSelectorViewModelTests: XCTestCase { XCTAssertEqual(context.viewState.items, MockSpaceSelectorService.defaultSpaceList) XCTAssertEqual(context.viewState.navigationTitle, VectorL10n.spaceSelectorTitle) } - } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/View/SpaceSelector.swift b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/View/SpaceSelector.swift index 115a51444..df9c52906 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/View/SpaceSelector.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/View/SpaceSelector.swift @@ -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 SpaceSelector: View { - // MARK: - Properties // MARK: Private @@ -53,12 +52,11 @@ struct SpaceSelector: View { notificationCount: item.notificationCount, highlightedNotificationCount: item.highlightedNotificationCount, disclosureAction: { - viewModel.send(viewAction: .spaceDisclosure(item)) + viewModel.send(viewAction: .spaceDisclosure(item)) + }) + .onTapGesture { + viewModel.send(viewAction: .spaceSelected(item)) } - ) - .onTapGesture { - viewModel.send(viewAction: .spaceSelected(item)) - } } } } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/View/SpaceSelectorListRow.swift b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/View/SpaceSelectorListRow.swift index aa60c5dd4..d9e67c9b9 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/View/SpaceSelectorListRow.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSelectorBottomSheet/SpaceSelector/View/SpaceSelectorListRow.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -70,7 +70,7 @@ struct SpaceSelectorListRow: View { .renderingMode(.template) .foregroundColor(theme.colors.secondaryContent) } - if hasSubItems && isJoined { + if hasSubItems, isJoined { Button { disclosureAction?() } label: { @@ -91,7 +91,7 @@ struct SpaceSelectorListRow: View { } private func badge(with text: String, color: Color) -> some View { - return Text(text) + Text(text) .multilineTextAlignment(.center) .foregroundColor(theme.colors.background) .font(theme.fonts.footnote) @@ -106,7 +106,6 @@ struct SpaceSelectorListRow: View { // MARK: - Previews struct SpaceSelectorListRow_Previews: PreviewProvider { - static var previews: some View { sampleView.theme(.light).preferredColorScheme(.light) sampleView.theme(.dark).preferredColorScheme(.dark) @@ -121,5 +120,4 @@ struct SpaceSelectorListRow_Previews: PreviewProvider { SpaceSelectorListRow(avatar: nil, icon: UIImage(systemName: "house"), displayName: "Space name", hasSubItems: true, isJoined: true, isSelected: true, notificationCount: 99, highlightedNotificationCount: 1, disclosureAction: nil) } } - } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSettings/Coordinator/SpaceSettingsModalCoordinator.swift b/RiotSwiftUI/Modules/Spaces/SpaceSettings/Coordinator/SpaceSettingsModalCoordinator.swift index b2d10971c..8e7da9792 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSettings/Coordinator/SpaceSettingsModalCoordinator.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSettings/Coordinator/SpaceSettingsModalCoordinator.swift @@ -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) }) } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSettings/Coordinator/SpaceSettingsModalCoordinatorBridgePresenter.swift b/RiotSwiftUI/Modules/Spaces/SpaceSettings/Coordinator/SpaceSettingsModalCoordinatorBridgePresenter.swift index 5614f2d08..c76f0aac7 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSettings/Coordinator/SpaceSettingsModalCoordinatorBridgePresenter.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSettings/Coordinator/SpaceSettingsModalCoordinatorBridgePresenter.swift @@ -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) } - } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSettings/Coordinator/SpaceSettingsModalCoordinatorParameters.swift b/RiotSwiftUI/Modules/Spaces/SpaceSettings/Coordinator/SpaceSettingsModalCoordinatorParameters.swift index 04778e3ed..85b3cf924 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSettings/Coordinator/SpaceSettingsModalCoordinatorParameters.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSettings/Coordinator/SpaceSettingsModalCoordinatorParameters.swift @@ -18,7 +18,6 @@ import Foundation /// SpaceSettingsModalCoordinator input parameters struct SpaceSettingsModalCoordinatorParameters { - /// The Matrix session let session: MXSession diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Coordinator/SpaceSettingsCoordinator.swift b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Coordinator/SpaceSettingsCoordinator.swift index 74d88ad09..0224ae5cf 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Coordinator/SpaceSettingsCoordinator.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Coordinator/SpaceSettingsCoordinator.swift @@ -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)) diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/MockSpaceSettingsScreenState.swift b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/MockSpaceSettingsScreenState.swift index 3a28e7f65..f18482638 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/MockSpaceSettingsScreenState.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/MockSpaceSettingsScreenState.swift @@ -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) diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Service/MatrixSDK/SpaceSettingsService.swift b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Service/MatrixSDK/SpaceSettingsService.swift index 51028a11c..8b74bda67 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Service/MatrixSDK/SpaceSettingsService.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Service/MatrixSDK/SpaceSettingsService.swift @@ -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() } } - } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Service/Mock/MockSpaceSettingsService.swift b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Service/Mock/MockSpaceSettingsService.swift index 96bc1f503..c9b7feb41 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Service/Mock/MockSpaceSettingsService.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Service/Mock/MockSpaceSettingsService.swift @@ -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() { } } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Service/SpaceSettingsServiceProtocol.swift b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Service/SpaceSettingsServiceProtocol.swift index 4788c8e75..730a98bfe 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Service/SpaceSettingsServiceProtocol.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Service/SpaceSettingsServiceProtocol.swift @@ -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 } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/SpaceSettingsModels.swift b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/SpaceSettingsModels.swift index 6ca32eef4..2601d00d2 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/SpaceSettingsModels.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/SpaceSettingsModels.swift @@ -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 } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/SpaceSettingsViewModel.swift b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/SpaceSettingsViewModel.swift index e98257b3f..b35fad927 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/SpaceSettingsViewModel.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/SpaceSettingsViewModel.swift @@ -14,14 +14,13 @@ // limitations under the License. // -import SwiftUI import Combine +import SwiftUI typealias SpaceSettingsViewModelType = StateStoreViewModel + 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) diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/SpaceSettingsViewModelProtocol.swift b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/SpaceSettingsViewModelProtocol.swift index a2859c8a4..808265e83 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/SpaceSettingsViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/SpaceSettingsViewModelProtocol.swift @@ -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 } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Test/UI/SpaceSettingsUITests.swift b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Test/UI/SpaceSettingsUITests.swift index abece45dd..583035c4c 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Test/UI/SpaceSettingsUITests.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Test/UI/SpaceSettingsUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class SpaceSettingsUITests: MockScreenTestCase { // Tests to be implemented. diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Test/Unit/SpaceSettingsViewModelTests.swift b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Test/Unit/SpaceSettingsViewModelTests.swift index 1e018fb85..102ba5669 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Test/Unit/SpaceSettingsViewModelTests.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/Test/Unit/SpaceSettingsViewModelTests.swift @@ -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) diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/View/SpaceSettings.swift b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/View/SpaceSettings.swift index 42d8f71b3..8c1d31359 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/View/SpaceSettings.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/View/SpaceSettings.swift @@ -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) } } } diff --git a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/View/SpaceSettingsOptionListItem.swift b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/View/SpaceSettingsOptionListItem.swift index 6287ab24d..11b921ce7 100644 --- a/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/View/SpaceSettingsOptionListItem.swift +++ b/RiotSwiftUI/Modules/Spaces/SpaceSettings/SpaceSettings/View/SpaceSettingsOptionListItem.swift @@ -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) } } - } diff --git a/RiotSwiftUI/Modules/Template/SimpleScreenExample/Coordinator/TemplateSimpleScreenCoordinator.swift b/RiotSwiftUI/Modules/Template/SimpleScreenExample/Coordinator/TemplateSimpleScreenCoordinator.swift index a794c88ab..ec2bd32d2 100644 --- a/RiotSwiftUI/Modules/Template/SimpleScreenExample/Coordinator/TemplateSimpleScreenCoordinator.swift +++ b/RiotSwiftUI/Modules/Template/SimpleScreenExample/Coordinator/TemplateSimpleScreenCoordinator.swift @@ -14,15 +14,14 @@ // limitations under the License. // -import SwiftUI import CommonKit +import SwiftUI struct TemplateSimpleScreenCoordinatorParameters { let promptType: TemplateSimpleScreenPromptType } final class TemplateSimpleScreenCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -65,7 +64,7 @@ final class TemplateSimpleScreenCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.templateSimpleScreenHostingController + templateSimpleScreenHostingController } // MARK: - Private diff --git a/RiotSwiftUI/Modules/Template/SimpleScreenExample/MockTemplateSimpleScreenScreenState.swift b/RiotSwiftUI/Modules/Template/SimpleScreenExample/MockTemplateSimpleScreenScreenState.swift index 4a2d885cd..5db4451ec 100644 --- a/RiotSwiftUI/Modules/Template/SimpleScreenExample/MockTemplateSimpleScreenScreenState.swift +++ b/RiotSwiftUI/Modules/Template/SimpleScreenExample/MockTemplateSimpleScreenScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,7 +37,7 @@ enum MockTemplateSimpleScreenScreenState: MockScreenState, CaseIterable { } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let promptType: TemplateSimpleScreenPromptType switch self { case .promptType(let type): diff --git a/RiotSwiftUI/Modules/Template/SimpleScreenExample/TemplateSimpleScreenModels.swift b/RiotSwiftUI/Modules/Template/SimpleScreenExample/TemplateSimpleScreenModels.swift index 2238fc709..d1755f432 100644 --- a/RiotSwiftUI/Modules/Template/SimpleScreenExample/TemplateSimpleScreenModels.swift +++ b/RiotSwiftUI/Modules/Template/SimpleScreenExample/TemplateSimpleScreenModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Template/SimpleScreenExample/TemplateSimpleScreenViewModel.swift b/RiotSwiftUI/Modules/Template/SimpleScreenExample/TemplateSimpleScreenViewModel.swift index 892e91a82..c90e70346 100644 --- a/RiotSwiftUI/Modules/Template/SimpleScreenExample/TemplateSimpleScreenViewModel.swift +++ b/RiotSwiftUI/Modules/Template/SimpleScreenExample/TemplateSimpleScreenViewModel.swift @@ -17,11 +17,10 @@ import SwiftUI typealias TemplateSimpleScreenViewModelType = StateStoreViewModel + Never, + TemplateSimpleScreenViewAction> class TemplateSimpleScreenViewModel: TemplateSimpleScreenViewModelType, TemplateSimpleScreenViewModelProtocol { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Template/SimpleScreenExample/TemplateSimpleScreenViewModelProtocol.swift b/RiotSwiftUI/Modules/Template/SimpleScreenExample/TemplateSimpleScreenViewModelProtocol.swift index 9d19bf528..cbab2a69a 100644 --- a/RiotSwiftUI/Modules/Template/SimpleScreenExample/TemplateSimpleScreenViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Template/SimpleScreenExample/TemplateSimpleScreenViewModelProtocol.swift @@ -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 TemplateSimpleScreenViewModelProtocol { - var completion: ((TemplateSimpleScreenViewModelResult) -> Void)? { get set } var context: TemplateSimpleScreenViewModelType.Context { get } } diff --git a/RiotSwiftUI/Modules/Template/SimpleScreenExample/Test/UI/TemplateSimpleScreenUITests.swift b/RiotSwiftUI/Modules/Template/SimpleScreenExample/Test/UI/TemplateSimpleScreenUITests.swift index 4b02918dd..4af3689ac 100644 --- a/RiotSwiftUI/Modules/Template/SimpleScreenExample/Test/UI/TemplateSimpleScreenUITests.swift +++ b/RiotSwiftUI/Modules/Template/SimpleScreenExample/Test/UI/TemplateSimpleScreenUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class TemplateSimpleScreenUITests: MockScreenTestCase { func testTemplateSimpleScreenPromptRegular() { diff --git a/RiotSwiftUI/Modules/Template/SimpleScreenExample/Test/Unit/TemplateSimpleScreenViewModelTests.swift b/RiotSwiftUI/Modules/Template/SimpleScreenExample/Test/Unit/TemplateSimpleScreenViewModelTests.swift index c3c0849a4..2ae36f733 100644 --- a/RiotSwiftUI/Modules/Template/SimpleScreenExample/Test/Unit/TemplateSimpleScreenViewModelTests.swift +++ b/RiotSwiftUI/Modules/Template/SimpleScreenExample/Test/Unit/TemplateSimpleScreenViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Template/SimpleScreenExample/View/TemplateSimpleScreen.swift b/RiotSwiftUI/Modules/Template/SimpleScreenExample/View/TemplateSimpleScreen.swift index fa43120b6..4fe4302ef 100644 --- a/RiotSwiftUI/Modules/Template/SimpleScreenExample/View/TemplateSimpleScreen.swift +++ b/RiotSwiftUI/Modules/Template/SimpleScreenExample/View/TemplateSimpleScreen.swift @@ -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 TemplateSimpleScreen: View { - // MARK: - Properties // MARK: Private @@ -64,10 +63,10 @@ struct TemplateSimpleScreen: View { Image(viewModel.viewState.promptType.image.name) .resizable() .scaledToFit() - .frame(width:100) + .frame(width: 100) .foregroundColor(theme.colors.accent) - HStack{ + HStack { Text("Counter: \(viewModel.viewState.count)") .foregroundColor(theme.colors.primaryContent) diff --git a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Coordinator/TemplateUserProfileCoordinator.swift b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Coordinator/TemplateUserProfileCoordinator.swift index c2050e6ed..38525cc2c 100644 --- a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Coordinator/TemplateUserProfileCoordinator.swift +++ b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Coordinator/TemplateUserProfileCoordinator.swift @@ -14,15 +14,14 @@ // limitations under the License. // -import SwiftUI import CommonKit +import SwiftUI struct TemplateUserProfileCoordinatorParameters { let session: MXSession } final class TemplateUserProfileCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -68,7 +67,7 @@ final class TemplateUserProfileCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.templateUserProfileHostingController + templateUserProfileHostingController } // MARK: - Private diff --git a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/MockTemplateUserProfileScreenState.swift b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/MockTemplateUserProfileScreenState.swift index f43fb2557..08082aec5 100644 --- a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/MockTemplateUserProfileScreenState.swift +++ b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/MockTemplateUserProfileScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,12 +35,12 @@ enum MockTemplateUserProfileScreenState: MockScreenState, CaseIterable { static var allCases: [MockTemplateUserProfileScreenState] { // Each of the presence statuses TemplateUserProfilePresence.allCases.map(MockTemplateUserProfileScreenState.presence) - // A long display name - + [.longDisplayName("Somebody with a super long name we would like to test")] + // A long display name + + [.longDisplayName("Somebody with a super long name we would like to test")] } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let service: MockTemplateUserProfileService switch self { case .presence(let presence): diff --git a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Service/MatrixSDK/TemplateUserProfileService.swift b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Service/MatrixSDK/TemplateUserProfileService.swift index 77341c1b3..409e868a5 100644 --- a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Service/MatrixSDK/TemplateUserProfileService.swift +++ b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Service/MatrixSDK/TemplateUserProfileService.swift @@ -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 TemplateUserProfileService: TemplateUserProfileServiceProtocol { - // MARK: - Properties // MARK: Private @@ -46,8 +45,8 @@ class TemplateUserProfileService: TemplateUserProfileServiceProtocol { init(session: MXSession) { self.session = session - self.presenceSubject = CurrentValueSubject(TemplateUserProfilePresence(mxPresence: session.myUser.presence)) - self.listenerReference = setupPresenceListener() + presenceSubject = CurrentValueSubject(TemplateUserProfilePresence(mxPresence: session.myUser.presence)) + listenerReference = setupPresenceListener() } deinit { @@ -70,8 +69,7 @@ class TemplateUserProfileService: TemplateUserProfileServiceProtocol { } } -fileprivate extension TemplateUserProfilePresence { - +private extension TemplateUserProfilePresence { init(mxPresence: MXPresence) { switch mxPresence { case .online: diff --git a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Service/Mock/MockTemplateUserProfileService.swift b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Service/Mock/MockTemplateUserProfileService.swift index 86fe1c49a..4bd94dbd4 100644 --- a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Service/Mock/MockTemplateUserProfileService.swift +++ b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Service/Mock/MockTemplateUserProfileService.swift @@ -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 class MockTemplateUserProfileService: TemplateUserProfileServiceProtocol { var presenceSubject: CurrentValueSubject @@ -23,19 +23,17 @@ class MockTemplateUserProfileService: TemplateUserProfileServiceProtocol { let userId: String let displayName: String? let avatarUrl: String? - init( - userId: String = "@alice:matrix.org", - displayName: String? = "Alice", - avatarUrl: String? = "mxc://matrix.org/VyNYAgahaiAzUoOeZETtQ", - presence: TemplateUserProfilePresence = .offline - ) { + init(userId: String = "@alice:matrix.org", + displayName: String? = "Alice", + avatarUrl: String? = "mxc://matrix.org/VyNYAgahaiAzUoOeZETtQ", + presence: TemplateUserProfilePresence = .offline) { self.userId = userId self.displayName = displayName self.avatarUrl = avatarUrl - self.presenceSubject = CurrentValueSubject(presence) + presenceSubject = CurrentValueSubject(presence) } func simulateUpdate(presence: TemplateUserProfilePresence) { - self.presenceSubject.value = presence + presenceSubject.value = presence } } diff --git a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Service/TemplateUserProfileServiceProtocol.swift b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Service/TemplateUserProfileServiceProtocol.swift index a446d840f..d4317d2e3 100644 --- a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Service/TemplateUserProfileServiceProtocol.swift +++ b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Service/TemplateUserProfileServiceProtocol.swift @@ -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 protocol TemplateUserProfileServiceProtocol: Avatarable { var userId: String { get } @@ -30,6 +30,7 @@ extension TemplateUserProfileServiceProtocol { var mxContentUri: String? { avatarUrl } + var matrixItemId: String { userId } diff --git a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/TemplateUserProfileModels.swift b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/TemplateUserProfileModels.swift index e57ce601e..6456e2b08 100644 --- a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/TemplateUserProfileModels.swift +++ b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/TemplateUserProfileModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/TemplateUserProfileViewModel.swift b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/TemplateUserProfileViewModel.swift index 3dfc27a9f..554eac157 100644 --- a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/TemplateUserProfileViewModel.swift +++ b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/TemplateUserProfileViewModel.swift @@ -14,15 +14,14 @@ // limitations under the License. // -import SwiftUI import Combine +import SwiftUI typealias TemplateUserProfileViewModelType = StateStoreViewModel + Never, + TemplateUserProfileViewAction> class TemplateUserProfileViewModel: TemplateUserProfileViewModelType, TemplateUserProfileViewModelProtocol { - // MARK: - Properties // MARK: Private @@ -36,7 +35,7 @@ class TemplateUserProfileViewModel: TemplateUserProfileViewModelType, TemplateUs // MARK: - Setup static func makeTemplateUserProfileViewModel(templateUserProfileService: TemplateUserProfileServiceProtocol) -> TemplateUserProfileViewModelProtocol { - return TemplateUserProfileViewModel(templateUserProfileService: templateUserProfileService) + TemplateUserProfileViewModel(templateUserProfileService: templateUserProfileService) } private init(templateUserProfileService: TemplateUserProfileServiceProtocol) { @@ -46,7 +45,7 @@ class TemplateUserProfileViewModel: TemplateUserProfileViewModelType, TemplateUs } private static func defaultState(templateUserProfileService: TemplateUserProfileServiceProtocol) -> TemplateUserProfileViewState { - return TemplateUserProfileViewState( + TemplateUserProfileViewState( avatar: templateUserProfileService.avatarData, displayName: templateUserProfileService.displayName, presence: templateUserProfileService.presenceSubject.value, diff --git a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/TemplateUserProfileViewModelProtocol.swift b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/TemplateUserProfileViewModelProtocol.swift index 6862c6a20..6df29b71d 100644 --- a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/TemplateUserProfileViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/TemplateUserProfileViewModelProtocol.swift @@ -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 TemplateUserProfileViewModelProtocol { - var completion: ((TemplateUserProfileViewModelResult) -> Void)? { get set } static func makeTemplateUserProfileViewModel(templateUserProfileService: TemplateUserProfileServiceProtocol) -> TemplateUserProfileViewModelProtocol var context: TemplateUserProfileViewModelType.Context { get } diff --git a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Test/UI/TemplateUserProfileUITests.swift b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Test/UI/TemplateUserProfileUITests.swift index b23b4174e..feecd0e37 100644 --- a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Test/UI/TemplateUserProfileUITests.swift +++ b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Test/UI/TemplateUserProfileUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class TemplateUserProfileUITests: MockScreenTestCase { func testTemplateUserProfilePresenceIdle() { @@ -53,5 +53,4 @@ class TemplateUserProfileUITests: MockScreenTestCase { XCTAssert(displayNameText.exists) XCTAssertEqual(displayNameText.label, name) } - } diff --git a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Test/Unit/TemplateUserProfileViewModelTests.swift b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Test/Unit/TemplateUserProfileViewModelTests.swift index be0420f8f..c3fffa429 100644 --- a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Test/Unit/TemplateUserProfileViewModelTests.swift +++ b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/Test/Unit/TemplateUserProfileViewModelTests.swift @@ -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 @@ -24,6 +24,7 @@ class TemplateUserProfileViewModelTests: XCTestCase { static let presenceInitialValue: TemplateUserProfilePresence = .offline static let displayName = "Alice" } + var service: MockTemplateUserProfileService! var viewModel: TemplateUserProfileViewModelProtocol! var context: TemplateUserProfileViewModelType.Context! diff --git a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/View/TemplateUserProfile.swift b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/View/TemplateUserProfile.swift index 073431f39..7bf54cd21 100644 --- a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/View/TemplateUserProfile.swift +++ b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/View/TemplateUserProfile.swift @@ -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 TemplateUserProfile: View { - // MARK: - Properties // MARK: Private @@ -36,7 +35,7 @@ struct TemplateUserProfile: View { presence: viewModel.viewState.presence ) Divider() - HStack{ + HStack { Text("Counter: \(viewModel.viewState.count)") .font(theme.fonts.title2) .foregroundColor(theme.colors.secondaryContent) diff --git a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/View/TemplateUserProfileHeader.swift b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/View/TemplateUserProfileHeader.swift index b67f6971b..e3ec295e2 100644 --- a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/View/TemplateUserProfileHeader.swift +++ b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/View/TemplateUserProfileHeader.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,13 +17,14 @@ import SwiftUI struct TemplateUserProfileHeader: View { - // MARK: - Properties // MARK: Private + @Environment(\.theme) private var theme: ThemeSwiftUI // MARK: Public + let avatar: AvatarInputProtocol? let displayName: String? let presence: TemplateUserProfilePresence @@ -32,9 +33,9 @@ struct TemplateUserProfileHeader: View { VStack { if let avatar = avatar { AvatarImage(avatarData: avatar, size: .xxLarge) - .padding(.vertical) + .padding(.vertical) } - VStack(spacing: 8){ + VStack(spacing: 8) { Text(displayName ?? "") .font(theme.fonts.title3) .accessibility(identifier: "displayNameText") diff --git a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/View/TemplateUserProfilePresenceView.swift b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/View/TemplateUserProfilePresenceView.swift index 0428474cf..1a49a4d18 100644 --- a/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/View/TemplateUserProfilePresenceView.swift +++ b/RiotSwiftUI/Modules/Template/SimpleUserProfileExample/View/TemplateUserProfilePresenceView.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,10 +17,10 @@ import SwiftUI struct TemplateUserProfilePresenceView: View { - // MARK: - Properties // MARK: Public + let presence: TemplateUserProfilePresence var body: some View { @@ -54,7 +54,7 @@ struct TemplateUserProfilePresenceView: View { struct TemplateUserProfilePresenceView_Previews: PreviewProvider { static var previews: some View { - VStack(alignment:.leading){ + VStack(alignment: .leading) { Text("Presence") ForEach(TemplateUserProfilePresence.allCases) { presence in TemplateUserProfilePresenceView(presence: presence) diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/Coordinator/TemplateRoomsCoordinator.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/Coordinator/TemplateRoomsCoordinator.swift index fa6029248..869766600 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/Coordinator/TemplateRoomsCoordinator.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/Coordinator/TemplateRoomsCoordinator.swift @@ -18,7 +18,6 @@ import UIKit @objcMembers final class TemplateRoomsCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -26,7 +25,7 @@ final class TemplateRoomsCoordinator: Coordinator, Presentable { private let parameters: TemplateRoomsCoordinatorParameters private var navigationRouter: NavigationRouterType { - return self.parameters.navigationRouter + parameters.navigationRouter } // MARK: Public @@ -40,37 +39,36 @@ final class TemplateRoomsCoordinator: Coordinator, Presentable { init(parameters: TemplateRoomsCoordinatorParameters) { self.parameters = parameters - } + } // MARK: - Public - func start() { MXLog.debug("[TemplateRoomsCoordinator] did start.") - let rootCoordinator = self.createTemplateRoomListCoordinator() + let rootCoordinator = createTemplateRoomListCoordinator() 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 private func createTemplateRoomListCoordinator() -> TemplateRoomListCoordinator { - let coordinator: TemplateRoomListCoordinator = TemplateRoomListCoordinator(parameters: TemplateRoomListCoordinatorParameters(session: parameters.session)) + let coordinator = TemplateRoomListCoordinator(parameters: TemplateRoomListCoordinatorParameters(session: parameters.session)) coordinator.callback = { [weak self] result in MXLog.debug("[TemplateRoomsCoordinator] TemplateRoomListCoordinator did complete with result \(result).") @@ -86,7 +84,7 @@ final class TemplateRoomsCoordinator: Coordinator, Presentable { } private func createTemplateRoomChatCoordinator(room: MXRoom) -> TemplateRoomChatCoordinator { - let coordinator: TemplateRoomChatCoordinator = TemplateRoomChatCoordinator(parameters: TemplateRoomChatCoordinatorParameters(room: room)) + let coordinator = TemplateRoomChatCoordinator(parameters: TemplateRoomChatCoordinatorParameters(room: room)) return coordinator } @@ -99,7 +97,7 @@ final class TemplateRoomsCoordinator: Coordinator, Presentable { add(childCoordinator: templateRoomChatCoordinator) - self.navigationRouter.push(templateRoomChatCoordinator, animated: true, popCompletion: { [weak self] in + navigationRouter.push(templateRoomChatCoordinator, animated: true, popCompletion: { [weak self] in self?.remove(childCoordinator: templateRoomChatCoordinator) }) diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/Coordinator/TemplateRoomsCoordinatorParameters.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/Coordinator/TemplateRoomsCoordinatorParameters.swift index dd9cd4295..bce458e79 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/Coordinator/TemplateRoomsCoordinatorParameters.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/Coordinator/TemplateRoomsCoordinatorParameters.swift @@ -18,7 +18,6 @@ import Foundation /// TemplateRoomsCoordinator input parameters struct TemplateRoomsCoordinatorParameters { - /// The Matrix session let session: MXSession diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Coordinator/TemplateRoomChatCoordinator.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Coordinator/TemplateRoomChatCoordinator.swift index 5f1dcd5e6..2a8c79c7e 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Coordinator/TemplateRoomChatCoordinator.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Coordinator/TemplateRoomChatCoordinator.swift @@ -21,7 +21,6 @@ struct TemplateRoomChatCoordinatorParameters { } final class TemplateRoomChatCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -48,6 +47,7 @@ final class TemplateRoomChatCoordinator: Coordinator, Presentable { } // MARK: - Public + func start() { MXLog.debug("[TemplateRoomChatCoordinator] did start.") templateRoomChatViewModel.callback = { [weak self] result in @@ -56,12 +56,11 @@ final class TemplateRoomChatCoordinator: Coordinator, Presentable { switch result { case .done: self.callback?() - break } } } func toPresentable() -> UIViewController { - return self.templateRoomChatHostingController + templateRoomChatHostingController } } diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/MockTemplateRoomChatScreenState.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/MockTemplateRoomChatScreenState.swift index b755cc2fd..8ec8bced0 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/MockTemplateRoomChatScreenState.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/MockTemplateRoomChatScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -56,7 +56,7 @@ enum MockTemplateRoomChatScreenState: MockScreenState, CaseIterable { return ( [service, viewModel], AnyView(TemplateRoomChat(viewModel: viewModel.context) - .addDependency(MockAvatarService.example)) + .addDependency(MockAvatarService.example)) ) } } diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Service/MatrixSDK/TemplateRoomChatService.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Service/MatrixSDK/TemplateRoomChatService.swift index 6019c2535..1428b6f70 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Service/MatrixSDK/TemplateRoomChatService.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Service/MatrixSDK/TemplateRoomChatService.swift @@ -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 TemplateRoomChatService: TemplateRoomChatServiceProtocol { - // MARK: - Properties // MARK: Private @@ -29,22 +28,23 @@ class TemplateRoomChatService: TemplateRoomChatServiceProtocol { private var eventBatch: [MXEvent] private var roomListenerReference: Any? - // MARK: Public + private(set) var chatMessagesSubject: CurrentValueSubject<[TemplateRoomChatMessage], Never> private(set) var roomInitializationStatus: CurrentValueSubject var roomName: String? { - self.room.summary.displayname + room.summary.displayname } + // MARK: - Setup init(room: MXRoom) { self.room = room - self.eventFormatter = EventFormatter(matrixSession: room.mxSession) - self.chatMessagesSubject = CurrentValueSubject([]) - self.roomInitializationStatus = CurrentValueSubject(.notInitialized) - self.eventBatch = [MXEvent]() + eventFormatter = EventFormatter(matrixSession: room.mxSession) + chatMessagesSubject = CurrentValueSubject([]) + roomInitializationStatus = CurrentValueSubject(.notInitialized) + eventBatch = [MXEvent]() initializeRoom() } @@ -54,14 +54,15 @@ class TemplateRoomChatService: TemplateRoomChatServiceProtocol { } // MARK: Public + func send(textMessage: String) { - var localEcho: MXEvent? = nil + var localEcho: MXEvent? room.sendTextMessage(textMessage, threadId: nil, localEcho: &localEcho, completion: { _ in }) } // MARK: Private - private func initializeRoom(){ + private func initializeRoom() { room.liveTimeline { [weak self] timeline in guard let self = self, let timeline = timeline @@ -70,21 +71,20 @@ class TemplateRoomChatService: TemplateRoomChatServiceProtocol { } self.timeline = timeline timeline.resetPagination() - self.roomListenerReference = timeline.listenToEvents([.roomMessage], { [weak self] event, direction, roomState in + self.roomListenerReference = timeline.listenToEvents([.roomMessage]) { [weak self] event, direction, _ in guard let self = self else { return } if direction == .backwards { self.eventBatch.append(event) } else { self.chatMessagesSubject.value += self.mapChatMessages(from: [event]) } - - }) + } timeline.paginate(200, direction: .backwards, onlyFromStore: false) { result in guard result.isSuccess else { self.roomInitializationStatus.value = .failedToInitialize return } - let sortedBatch = self.eventBatch.sorted(by: { $0.originServerTs < $1.originServerTs}) + let sortedBatch = self.eventBatch.sorted(by: { $0.originServerTs < $1.originServerTs }) self.chatMessagesSubject.value = self.mapChatMessages(from: sortedBatch) self.roomInitializationStatus.value = .initialized } @@ -92,15 +92,14 @@ class TemplateRoomChatService: TemplateRoomChatServiceProtocol { } private func mapChatMessages(from events: [MXEvent]) -> [TemplateRoomChatMessage] { - return events - .filter({ event in + events + .filter { event in event.type == kMXEventTypeStringRoomMessage && event.content[kMXMessageTypeKey] as? String == kMXMessageTypeText // TODO: New to our SwiftUI Template? Why not implement another message type like image? - - }) - .compactMap({ event -> TemplateRoomChatMessage? in + } + .compactMap { event -> TemplateRoomChatMessage? in guard let eventId = event.eventId, let body = event.content[kMXMessageBodyKey] as? String, let sender = senderForMessage(event: event) @@ -112,7 +111,7 @@ class TemplateRoomChatService: TemplateRoomChatServiceProtocol { sender: sender, timestamp: Date(timeIntervalSince1970: TimeInterval(event.originServerTs / 1000)) ) - }) + } } private func senderForMessage(event: MXEvent) -> TemplateRoomChatMember? { diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Service/Mock/MockTemplateRoomChatService.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Service/Mock/MockTemplateRoomChatService.swift index d4da0a63e..c920b2a8f 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Service/Mock/MockTemplateRoomChatService.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Service/Mock/MockTemplateRoomChatService.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,39 +14,38 @@ // limitations under the License. // -import Foundation import Combine +import Foundation class MockTemplateRoomChatService: TemplateRoomChatServiceProtocol { - let roomName: String? = "New Vector" static let amadine = TemplateRoomChatMember(id: "@amadine:matrix.org", avatarUrl: "!aaabaa:matrix.org", displayName: "Amadine") static let mathew = TemplateRoomChatMember(id: "@mathew:matrix.org", avatarUrl: "!bbabb:matrix.org", displayName: "Mathew") static let mockMessages = [ - TemplateRoomChatMessage(id: "!0:matrix.org", content: .text(TemplateRoomChatMessageTextContent(body: "Shall I put it live?")) , sender: amadine, timestamp: Date(timeIntervalSinceNow: 60 * -3)), + TemplateRoomChatMessage(id: "!0:matrix.org", content: .text(TemplateRoomChatMessageTextContent(body: "Shall I put it live?")), sender: amadine, timestamp: Date(timeIntervalSinceNow: 60 * -3)), TemplateRoomChatMessage(id: "!1:matrix.org", content: .text(TemplateRoomChatMessageTextContent(body: "Yea go for it! ...and then let's head to the pub")), sender: mathew, timestamp: Date(timeIntervalSinceNow: 60)), TemplateRoomChatMessage(id: "!2:matrix.org", content: .text(TemplateRoomChatMessageTextContent(body: "Deal.")), sender: amadine, timestamp: Date(timeIntervalSinceNow: 60 * -2)), - TemplateRoomChatMessage(id: "!3:matrix.org", content: .text(TemplateRoomChatMessageTextContent(body: "Ok, Done. 🍻")), sender: amadine, timestamp: Date(timeIntervalSinceNow: 60 * -1)), + TemplateRoomChatMessage(id: "!3:matrix.org", content: .text(TemplateRoomChatMessageTextContent(body: "Ok, Done. 🍻")), sender: amadine, timestamp: Date(timeIntervalSinceNow: 60 * -1)) ] var roomInitializationStatus: CurrentValueSubject var chatMessagesSubject: CurrentValueSubject<[TemplateRoomChatMessage], Never> init(messages: [TemplateRoomChatMessage] = mockMessages) { - self.roomInitializationStatus = CurrentValueSubject(.notInitialized) - self.chatMessagesSubject = CurrentValueSubject(messages) + roomInitializationStatus = CurrentValueSubject(.notInitialized) + chatMessagesSubject = CurrentValueSubject(messages) } func send(textMessage: String) { let newMessage = TemplateRoomChatMessage(id: "!\(chatMessagesSubject.value.count):matrix.org", content: .text(TemplateRoomChatMessageTextContent(body: textMessage)), sender: Self.amadine, timestamp: Date()) - self.chatMessagesSubject.value += [newMessage] + chatMessagesSubject.value += [newMessage] } func simulateUpdate(initializationStatus: TemplateRoomChatRoomInitializationStatus) { - self.roomInitializationStatus.value = initializationStatus + roomInitializationStatus.value = initializationStatus } func simulateUpdate(messages: [TemplateRoomChatMessage]) { - self.chatMessagesSubject.value = messages + chatMessagesSubject.value = messages } } diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Service/TemplateRoomChatServiceProtocol.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Service/TemplateRoomChatServiceProtocol.swift index 012c5ab85..a14ee05e3 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Service/TemplateRoomChatServiceProtocol.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Service/TemplateRoomChatServiceProtocol.swift @@ -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 protocol TemplateRoomChatServiceProtocol { var roomInitializationStatus: CurrentValueSubject { get } diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/TemplateRoomChatModels.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/TemplateRoomChatModels.swift index e9aa09141..84f09a068 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/TemplateRoomChatModels.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/TemplateRoomChatModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -88,7 +88,6 @@ enum TemplateRoomChatViewModelAction { case done } - // MARK: - View /// Actions send from the `View` to the `ViewModel`. diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/TemplateRoomChatViewModel.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/TemplateRoomChatViewModel.swift index 609d6a1f6..f0a3ecf3a 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/TemplateRoomChatViewModel.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/TemplateRoomChatViewModel.swift @@ -14,18 +14,18 @@ // limitations under the License. // -import SwiftUI import Combine +import SwiftUI typealias TemplateRoomChatViewModelType = StateStoreViewModel + Never, + TemplateRoomChatViewAction> class TemplateRoomChatViewModel: TemplateRoomChatViewModelType, TemplateRoomChatViewModelProtocol { - enum Constants { - static let maxTimeBeforeNewBubble: TimeInterval = 5*60 + static let maxTimeBeforeNewBubble: TimeInterval = 5 * 60 } + // MARK: - Properties // MARK: Private @@ -70,9 +70,8 @@ class TemplateRoomChatViewModel: TemplateRoomChatViewModelType, TemplateRoomChat } private static func makeBubbles(messages: [TemplateRoomChatMessage]) -> [TemplateRoomChatBubble] { - var bubbleOrder = [String]() - var bubbleMap = [String:TemplateRoomChatBubble]() + var bubbleMap = [String: TemplateRoomChatBubble]() messages.enumerated().forEach { i, message in // New message content @@ -85,9 +84,8 @@ class TemplateRoomChatViewModel: TemplateRoomChatViewModelType, TemplateRoomChat let lastBubbleId = bubbleOrder.last, var lastBubble = bubbleMap[lastBubbleId], lastBubble.sender.id == message.sender.id, - let interveningTime = lastBubble.items.last?.timestamp.timeIntervalSince(message.timestamp), - abs(interveningTime) < Constants.maxTimeBeforeNewBubble - { + let interveningTime = lastBubble.items.last?.timestamp.timeIntervalSince(message.timestamp), + abs(interveningTime) < Constants.maxTimeBeforeNewBubble { // if the last bubble's last message was within // the last 5 minutes append let item = TemplateRoomChatBubbleItem( @@ -108,7 +106,7 @@ class TemplateRoomChatViewModel: TemplateRoomChatViewModelType, TemplateRoomChat bubbleMap[bubble.id] = bubble } } - return bubbleOrder.compactMap({ bubbleMap[$0] }) + return bubbleOrder.compactMap { bubbleMap[$0] } } // MARK: - Public diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/TemplateRoomChatViewModelProtocol.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/TemplateRoomChatViewModelProtocol.swift index 3dd0ad937..4c2799351 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/TemplateRoomChatViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/TemplateRoomChatViewModelProtocol.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Test/UI/TemplateRoomChatUITests.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Test/UI/TemplateRoomChatUITests.swift index 449eddcc0..cf764cb2d 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Test/UI/TemplateRoomChatUITests.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Test/UI/TemplateRoomChatUITests.swift @@ -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 RiotSwiftUI +import XCTest class TemplateRoomChatUITests: MockScreenTestCase { func testInitializingRoom() { @@ -44,12 +44,11 @@ class TemplateRoomChatUITests: MockScreenTestCase { // Verify bubble grouping with: // 3 bubbles - let bubbleCount = app.images.matching(identifier:"bubbleImage").count + let bubbleCount = app.images.matching(identifier: "bubbleImage").count XCTAssertEqual(bubbleCount, 3) // and 4 text items - let bubbleTextItemCount = app.staticTexts.matching(identifier:"bubbleTextContent").count + let bubbleTextItemCount = app.staticTexts.matching(identifier: "bubbleTextContent").count XCTAssertEqual(bubbleTextItemCount, 4) } - } diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Test/Unit/TemplateRoomChatViewModelTests.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Test/Unit/TemplateRoomChatViewModelTests.swift index ea39fe0e8..5a99f0a58 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Test/Unit/TemplateRoomChatViewModelTests.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/Test/Unit/TemplateRoomChatViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,13 +14,12 @@ // limitations under the License. // -import XCTest import Combine +import XCTest @testable import RiotSwiftUI class TemplateRoomChatViewModelTests: XCTestCase { - var service: MockTemplateRoomChatService! var viewModel: TemplateRoomChatViewModel! var context: TemplateRoomChatViewModel.Context! @@ -39,18 +38,17 @@ class TemplateRoomChatViewModelTests: XCTestCase { XCTAssertEqual(context.viewState.roomInitializationStatus, .initialized) } - func testSendMessageUpdatesReceived() throws { let bubblesPublisher: AnyPublisher<[[TemplateRoomChatBubble]], Never> = context.$viewState.map(\.bubbles).removeDuplicates().collect(2).first().eraseToAnyPublisher() let awaitDeferred = xcAwaitDeferred(bubblesPublisher) - let newMessage: String = "Let's Go" + let newMessage = "Let's Go" service.send(textMessage: newMessage) let result: [[TemplateRoomChatBubble]]? = try awaitDeferred() // Test that the update to the messages in turn updates the view's // the last bubble by appending another text item, asserting the body. - guard let item:TemplateRoomChatBubbleItem = result?.last?.last?.items.last, + guard let item: TemplateRoomChatBubbleItem = result?.last?.last?.items.last, case TemplateRoomChatBubbleItemContent.message(let message) = item.content, case let TemplateRoomChatMessageContent.text(text) = message else { XCTFail() diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/View/TemplateRoomChat.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/View/TemplateRoomChat.swift index fb70cf503..029b10715 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/View/TemplateRoomChat.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/View/TemplateRoomChat.swift @@ -14,11 +14,10 @@ // limitations under the License. // -import SwiftUI import Combine +import SwiftUI struct TemplateRoomChat: View { - // MARK: - Properties // MARK: Private @@ -32,7 +31,7 @@ struct TemplateRoomChat: View { var body: some View { VStack { - VStack{ + VStack { roomContent }.frame(maxHeight: .infinity) @@ -51,7 +50,6 @@ struct TemplateRoomChat: View { .animation(.easeOut(duration: 0.25)) .transition(.move(edge: .trailing)) .padding() - } .background(theme.colors.background) .navigationTitle(viewModel.viewState.roomName ?? "Chat") @@ -83,14 +81,14 @@ struct TemplateRoomChat: View { private var bubbleList: some View { ScrollViewReader { reader in - ScrollView{ + ScrollView { LazyVStack { ForEach(viewModel.viewState.bubbles) { bubble in TemplateRoomChatBubbleView(bubble: bubble) .id(bubble.id) } } - .onAppear{ + .onAppear { guard let lastBubbleId = viewModel.viewState.bubbles.last?.id else { return } reader.scrollTo(lastBubbleId, anchor: .bottom) @@ -116,7 +114,7 @@ struct TemplateRoomChat: View { } private var itemCount: Int { - return viewModel.viewState + viewModel.viewState .bubbles .map(\.items) .map(\.count) diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/View/TemplateRoomChatBubbleContentView.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/View/TemplateRoomChatBubbleContentView.swift index 59f4bac29..61ccfb816 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/View/TemplateRoomChatBubbleContentView.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/View/TemplateRoomChatBubbleContentView.swift @@ -17,7 +17,6 @@ import SwiftUI struct TemplateRoomChatBubbleContentView: View { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/View/TemplateRoomChatBubbleImage.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/View/TemplateRoomChatBubbleImage.swift index 9014e8209..5cd791eca 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/View/TemplateRoomChatBubbleImage.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/View/TemplateRoomChatBubbleImage.swift @@ -17,7 +17,6 @@ import SwiftUI struct TemplateRoomChatBubbleImage: View { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/View/TemplateRoomChatBubbleMessage.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/View/TemplateRoomChatBubbleMessage.swift index aa1cb44c6..8732f7452 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/View/TemplateRoomChatBubbleMessage.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/View/TemplateRoomChatBubbleMessage.swift @@ -17,7 +17,6 @@ import SwiftUI struct TemplateRoomChatBubbleMessage: View { - // MARK: - Properties // MARK: Private diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/View/TemplateRoomChatBubbleView.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/View/TemplateRoomChatBubbleView.swift index f7cd4387b..a208559c0 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/View/TemplateRoomChatBubbleView.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomChat/View/TemplateRoomChatBubbleView.swift @@ -17,7 +17,6 @@ import SwiftUI struct TemplateRoomChatBubbleView: View { - // MARK: - Properties // MARK: Private @@ -29,10 +28,10 @@ struct TemplateRoomChatBubbleView: View { let bubble: TemplateRoomChatBubble var body: some View { - HStack(alignment: .top){ + HStack(alignment: .top) { AvatarImage(avatarData: bubble.sender.avatarData, size: .xSmall) .accessibility(identifier: "bubbleImage") - VStack(alignment: .leading){ + VStack(alignment: .leading) { Text(bubble.sender.displayName ?? "") .foregroundColor(theme.userColor(for: bubble.sender.id)) .font(theme.fonts.bodySB) @@ -42,7 +41,7 @@ struct TemplateRoomChatBubbleView: View { } Spacer() } - //add to a style + // add to a style .padding(.horizontal) .padding(.vertical, 8) .frame(maxWidth: .infinity) diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Coordinator/TemplateRoomListCoordinator.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Coordinator/TemplateRoomListCoordinator.swift index 8d08f3de2..9eec68a72 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Coordinator/TemplateRoomListCoordinator.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Coordinator/TemplateRoomListCoordinator.swift @@ -21,7 +21,6 @@ struct TemplateRoomListCoordinatorParameters { } final class TemplateRoomListCoordinator: Coordinator, Presentable { - // MARK: - Properties // MARK: Private @@ -59,12 +58,11 @@ final class TemplateRoomListCoordinator: Coordinator, Presentable { self.callback?(.didSelectRoom(roomId)) case .done: self.callback?(.done) - break } } } func toPresentable() -> UIViewController { - return self.templateRoomListHostingController + templateRoomListHostingController } } diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/MockTemplateRoomListScreenState.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/MockTemplateRoomListScreenState.swift index f0b6b1406..8b8c0e2a3 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/MockTemplateRoomListScreenState.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/MockTemplateRoomListScreenState.swift @@ -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 import SwiftUI - /// Using an enum for the screen allows you define the different state cases with /// the relevant associated data for each case. enum MockTemplateRoomListScreenState: MockScreenState, CaseIterable { diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Service/MatrixSDK/TemplateRoomListService.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Service/MatrixSDK/TemplateRoomListService.swift index 8678e6ddd..f723d0853 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Service/MatrixSDK/TemplateRoomListService.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Service/MatrixSDK/TemplateRoomListService.swift @@ -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 TemplateRoomListService: TemplateRoomListServiceProtocol { - // MARK: - Properties // MARK: Private @@ -27,6 +26,7 @@ class TemplateRoomListService: TemplateRoomListServiceProtocol { private var listenerReference: Any? // MARK: Public + private(set) var roomsSubject: CurrentValueSubject<[TemplateRoomListRoom], Never> // MARK: - Setup @@ -35,15 +35,13 @@ class TemplateRoomListService: TemplateRoomListServiceProtocol { self.session = session let unencryptedRooms = session.rooms - .filter({ !$0.summary.isEncrypted }) + .filter { !$0.summary.isEncrypted } .map(TemplateRoomListRoom.init(mxRoom:)) - self.roomsSubject = CurrentValueSubject(unencryptedRooms) + roomsSubject = CurrentValueSubject(unencryptedRooms) } - } -fileprivate extension TemplateRoomListRoom { - +private extension TemplateRoomListRoom { init(mxRoom: MXRoom) { self.init(id: mxRoom.roomId, avatar: mxRoom.avatarData, displayName: mxRoom.summary.displayname) } diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Service/Mock/MockTemplateRoomListService.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Service/Mock/MockTemplateRoomListService.swift index 1fcd53cb1..064884561 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Service/Mock/MockTemplateRoomListService.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Service/Mock/MockTemplateRoomListService.swift @@ -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 MockTemplateRoomListService: TemplateRoomListServiceProtocol { - static let mockRooms = [ TemplateRoomListRoom(id: "!aaabaa:matrix.org", avatar: MockAvatarInput.example, displayName: "Matrix Discussion"), TemplateRoomListRoom(id: "!zzasds:matrix.org", avatar: MockAvatarInput.example, displayName: "Element Mobile"), @@ -31,6 +30,6 @@ class MockTemplateRoomListService: TemplateRoomListServiceProtocol { } func simulateUpdate(rooms: [TemplateRoomListRoom]) { - self.roomsSubject.send(rooms) + roomsSubject.send(rooms) } } diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Service/TemplateRoomListServiceProtocol.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Service/TemplateRoomListServiceProtocol.swift index ba4248446..2eed29bb5 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Service/TemplateRoomListServiceProtocol.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Service/TemplateRoomListServiceProtocol.swift @@ -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 protocol TemplateRoomListServiceProtocol { var roomsSubject: CurrentValueSubject<[TemplateRoomListRoom], Never> { get } diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/TemplateRoomListModels.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/TemplateRoomListModels.swift index 57452cc1c..6d1c67811 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/TemplateRoomListModels.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/TemplateRoomListModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/TemplateRoomListViewModel.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/TemplateRoomListViewModel.swift index 14c84cc11..acb68aa85 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/TemplateRoomListViewModel.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/TemplateRoomListViewModel.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,15 +14,14 @@ // limitations under the License. // -import SwiftUI import Combine +import SwiftUI typealias TemplateRoomListViewModelType = StateStoreViewModel + Never, + TemplateRoomListViewAction> class TemplateRoomListViewModel: TemplateRoomListViewModelType, TemplateRoomListViewModelProtocol { - // MARK: - Properties // MARK: Private @@ -42,7 +41,7 @@ class TemplateRoomListViewModel: TemplateRoomListViewModelType, TemplateRoomList } private static func defaultState(templateRoomListService: TemplateRoomListServiceProtocol) -> TemplateRoomListViewState { - return TemplateRoomListViewState(rooms: templateRoomListService.roomsSubject.value) + TemplateRoomListViewState(rooms: templateRoomListService.roomsSubject.value) } private func startObservingRooms() { diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/TemplateRoomListViewModelProtocol.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/TemplateRoomListViewModelProtocol.swift index ee9e96060..217155848 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/TemplateRoomListViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/TemplateRoomListViewModelProtocol.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Test/UI/TemplateRoomListUITests.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Test/UI/TemplateRoomListUITests.swift index 8ee0012e2..9535644d4 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Test/UI/TemplateRoomListUITests.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Test/UI/TemplateRoomListUITests.swift @@ -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 RiotSwiftUI +import XCTest class TemplateRoomListUITests: MockScreenTestCase { func testTemplateRoomListNoRooms() { @@ -29,8 +29,7 @@ class TemplateRoomListUITests: MockScreenTestCase { func testTemplateRoomListRooms() { app.goToScreenWithIdentifier(MockTemplateRoomListScreenState.rooms.title) - let displayNameCount = app.buttons.matching(identifier:"roomNameText").count + let displayNameCount = app.buttons.matching(identifier: "roomNameText").count XCTAssertEqual(displayNameCount, 3) } - } diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Test/Unit/TemplateRoomListViewModelTests.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Test/Unit/TemplateRoomListViewModelTests.swift index 8f69bb605..e39303007 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Test/Unit/TemplateRoomListViewModelTests.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/Test/Unit/TemplateRoomListViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,14 +14,14 @@ // limitations under the License. // -import XCTest import Combine +import XCTest @testable import RiotSwiftUI class TemplateRoomListViewModelTests: XCTestCase { - private enum Constants { - } + private enum Constants { } + var service: MockTemplateRoomListService! var viewModel: TemplateRoomListViewModel! var context: TemplateRoomListViewModel.Context! @@ -46,7 +46,7 @@ class TemplateRoomListViewModelTests: XCTestCase { let updatedRooms = Array(MockTemplateRoomListService.mockRooms.dropLast()) let roomsPublisher = context.$viewState.map(\.rooms).removeDuplicates().collect(2).first() let awaitDeferred = xcAwaitDeferred(roomsPublisher) - service.simulateUpdate(rooms: updatedRooms) + service.simulateUpdate(rooms: updatedRooms) XCTAssertEqual(try awaitDeferred(), [MockTemplateRoomListService.mockRooms, updatedRooms]) } } diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/View/TemplateRoomList.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/View/TemplateRoomList.swift index 9ba36a2b4..6ee720a72 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/View/TemplateRoomList.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/View/TemplateRoomList.swift @@ -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 TemplateRoomList: View { - // MARK: - Properties // MARK: Private @@ -47,7 +46,7 @@ struct TemplateRoomList: View { .foregroundColor(theme.colors.primaryContent) .accessibility(identifier: "errorMessage") } else { - ScrollView{ + ScrollView { LazyVStack(spacing: 0) { ForEach(viewModel.viewState.rooms) { room in Button { @@ -66,7 +65,6 @@ struct TemplateRoomList: View { // MARK: - Previews struct TemplateRoomList_Previews: PreviewProvider { - static let stateRenderer = MockTemplateRoomListScreenState.stateRenderer static var previews: some View { stateRenderer.screenGroup(addNavigation: true) diff --git a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/View/TemplateRoomListRow.swift b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/View/TemplateRoomListRow.swift index c7418e635..8e5f50a81 100644 --- a/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/View/TemplateRoomListRow.swift +++ b/RiotSwiftUI/Modules/Template/TemplateAdvancedRoomsExample/TemplateRoomList/View/TemplateRoomListRow.swift @@ -17,7 +17,6 @@ import SwiftUI struct TemplateRoomListRow: View { - // MARK: - Properties // MARK: Private @@ -30,14 +29,14 @@ struct TemplateRoomListRow: View { let displayName: String? var body: some View { - HStack{ + HStack { AvatarImage(avatarData: avatar, size: .medium) Text(displayName ?? "") .foregroundColor(theme.colors.primaryContent) - .accessibility(identifier: "roomNameText") + .accessibility(identifier: "roomNameText") Spacer() } - //add to a style + // add to a style .padding(.horizontal) .padding(.vertical, 8) .frame(maxWidth: .infinity) diff --git a/RiotSwiftUI/Modules/UserSessions/Common/DeviceType.swift b/RiotSwiftUI/Modules/UserSessions/Common/DeviceType.swift index 7410be89a..0f0685778 100644 --- a/RiotSwiftUI/Modules/UserSessions/Common/DeviceType.swift +++ b/RiotSwiftUI/Modules/UserSessions/Common/DeviceType.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/UserSessions/Common/UserSessionInfo.swift b/RiotSwiftUI/Modules/UserSessions/Common/UserSessionInfo.swift index f8679b6df..ba1d18ecd 100644 --- a/RiotSwiftUI/Modules/UserSessions/Common/UserSessionInfo.swift +++ b/RiotSwiftUI/Modules/UserSessions/Common/UserSessionInfo.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,7 +24,7 @@ struct UserSessionInfo: Identifiable { // MARK: - Properties var id: String { - return sessionId + sessionId } /// The session identifier @@ -56,7 +56,6 @@ struct UserSessionInfo: Identifiable { isVerified: Bool, lastSeenIP: String?, lastSeenTimestamp: TimeInterval?) { - self.sessionId = sessionId self.sessionName = sessionName self.deviceType = deviceType diff --git a/RiotSwiftUI/Modules/UserSessions/Common/UserSessionLastActivityFormatter.swift b/RiotSwiftUI/Modules/UserSessions/Common/UserSessionLastActivityFormatter.swift index a3482d466..3c63d13b0 100644 --- a/RiotSwiftUI/Modules/UserSessions/Common/UserSessionLastActivityFormatter.swift +++ b/RiotSwiftUI/Modules/UserSessions/Common/UserSessionLastActivityFormatter.swift @@ -29,7 +29,6 @@ class UserSessionLastActivityFormatter { /// Session last activity string func lastActivityDateString(from lastActivityTimestamp: TimeInterval) -> String { - let date = Date(timeIntervalSince1970: lastActivityTimestamp) return UserSessionLastActivityFormatter.lastActivityDateFormatter.string(from: date) diff --git a/RiotSwiftUI/Modules/UserSessions/Common/UserSessionNameFormatter.swift b/RiotSwiftUI/Modules/UserSessions/Common/UserSessionNameFormatter.swift index 375aa8034..04dbd79f6 100644 --- a/RiotSwiftUI/Modules/UserSessions/Common/UserSessionNameFormatter.swift +++ b/RiotSwiftUI/Modules/UserSessions/Common/UserSessionNameFormatter.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,7 @@ import Foundation /// Enables to build user session name -class UserSessionNameFormatter { +class UserSessionNameFormatter { /// Session name with client name and session display name func sessionName(deviceType: DeviceType, sessionDisplayName: String?) -> String { let sessionName: String diff --git a/RiotSwiftUI/Modules/UserSessions/Common/View/DeviceAvatarView.swift b/RiotSwiftUI/Modules/UserSessions/Common/View/DeviceAvatarView.swift index 24a142619..d9ee4961e 100644 --- a/RiotSwiftUI/Modules/UserSessions/Common/View/DeviceAvatarView.swift +++ b/RiotSwiftUI/Modules/UserSessions/Common/View/DeviceAvatarView.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import SwiftUI import DesignKit +import SwiftUI /// Avatar view for device struct DeviceAvatarView: View { @@ -28,7 +28,6 @@ struct DeviceAvatarView: View { var body: some View { ZStack(alignment: .bottomTrailing) { - // Device image VStack(alignment: .center) { viewData.deviceType.image @@ -40,7 +39,6 @@ struct DeviceAvatarView: View { // Verification badge if let isVerified = viewData.isVerified { - Image(isVerified ? Asset.Images.userSessionVerified.name : Asset.Images.userSessionUnverified.name) .frame(maxWidth: CGFloat(badgeSize), maxHeight: CGFloat(badgeSize)) .shapedBorder(color: theme.colors.system, borderWidth: 1, shape: Circle()) @@ -55,7 +53,7 @@ struct DeviceAvatarView: View { struct DeviceAvatarViewListPreview: View { var viewDataList: [DeviceAvatarViewData] { - return [ + [ DeviceAvatarViewData(deviceType: .desktop, isVerified: true), DeviceAvatarViewData(deviceType: .web, isVerified: true), DeviceAvatarViewData(deviceType: .mobile, isVerified: true), @@ -66,7 +64,7 @@ struct DeviceAvatarViewListPreview: View { var body: some View { HStack { VStack(alignment: .center, spacing: 20) { - DeviceAvatarView(viewData: DeviceAvatarViewData.init(deviceType: .web, isVerified: true)) + DeviceAvatarView(viewData: DeviceAvatarViewData(deviceType: .web, isVerified: true)) DeviceAvatarView(viewData: DeviceAvatarViewData(deviceType: .desktop, isVerified: false)) DeviceAvatarView(viewData: DeviceAvatarViewData(deviceType: .mobile, isVerified: true)) DeviceAvatarView(viewData: DeviceAvatarViewData(deviceType: .unknown, isVerified: false)) diff --git a/RiotSwiftUI/Modules/UserSessions/Common/View/DeviceAvatarViewData.swift b/RiotSwiftUI/Modules/UserSessions/Common/View/DeviceAvatarViewData.swift index e4dd59b26..397e945dc 100644 --- a/RiotSwiftUI/Modules/UserSessions/Common/View/DeviceAvatarViewData.swift +++ b/RiotSwiftUI/Modules/UserSessions/Common/View/DeviceAvatarViewData.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/UserSessions/Common/View/SeparatorLine.swift b/RiotSwiftUI/Modules/UserSessions/Common/View/SeparatorLine.swift index 87d1a47d8..eac45ede2 100644 --- a/RiotSwiftUI/Modules/UserSessions/Common/View/SeparatorLine.swift +++ b/RiotSwiftUI/Modules/UserSessions/Common/View/SeparatorLine.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/UserSessions/Common/View/UserSessionCardView.swift b/RiotSwiftUI/Modules/UserSessions/Common/View/UserSessionCardView.swift index b423f4e7c..ee2255f10 100644 --- a/RiotSwiftUI/Modules/UserSessions/Common/View/UserSessionCardView.swift +++ b/RiotSwiftUI/Modules/UserSessions/Common/View/UserSessionCardView.swift @@ -14,40 +14,40 @@ // limitations under the License. // -import SwiftUI import DesignKit +import SwiftUI struct UserSessionCardView: View { @Environment(\.theme) var theme: ThemeSwiftUI var viewData: UserSessionCardViewData - var onVerifyAction: ((String) -> (Void))? = nil - var onViewDetailsAction: ((String) -> (Void))? = nil - var onLearnMoreAction: (() -> (Void))? = nil + var onVerifyAction: ((String) -> Void)? + var onViewDetailsAction: ((String) -> Void)? + var onLearnMoreAction: (() -> Void)? private var verificationStatusImageName: String { - return viewData.isVerified ? Asset.Images.userSessionVerified.name : Asset.Images.userSessionUnverified.name + viewData.isVerified ? Asset.Images.userSessionVerified.name : Asset.Images.userSessionUnverified.name } private var verificationStatusText: String { - return viewData.isVerified ? VectorL10n.userSessionVerified : VectorL10n.userSessionUnverified + viewData.isVerified ? VectorL10n.userSessionVerified : VectorL10n.userSessionUnverified } private var verificationStatusColor: Color { - return viewData.isVerified ? theme.colors.accent : theme.colors.alert + viewData.isVerified ? theme.colors.accent : theme.colors.alert } private var verificationStatusAdditionalInfoText: String { - return viewData.isVerified ? VectorL10n.userSessionVerifiedAdditionalInfo : VectorL10n.userSessionUnverifiedAdditionalInfo + viewData.isVerified ? VectorL10n.userSessionVerifiedAdditionalInfo : VectorL10n.userSessionUnverifiedAdditionalInfo } private var backgroundShape: RoundedRectangle { - return RoundedRectangle(cornerRadius: 8) + RoundedRectangle(cornerRadius: 8) } private var showExtraInformations: Bool { - return viewData.isCurrentSessionDisplayMode == false && (viewData.lastActivityDateString.isEmptyOrNil == false || viewData.lastSeenIPInfo.isEmptyOrNil == false) + viewData.isCurrentSessionDisplayMode == false && (viewData.lastActivityDateString.isEmptyOrNil == false || viewData.lastSeenIPInfo.isEmptyOrNil == false) } var body: some View { @@ -90,7 +90,7 @@ struct UserSessionCardView: View { .multilineTextAlignment(.center) } - if let lastSeenIPInfo = viewData.lastSeenIPInfo, lastSeenIPInfo.isEmpty == false { + if let lastSeenIPInfo = viewData.lastSeenIPInfo, lastSeenIPInfo.isEmpty == false { Text(lastSeenIPInfo) .font(theme.fonts.footnote) .foregroundColor(theme.colors.secondaryContent) diff --git a/RiotSwiftUI/Modules/UserSessions/Common/View/UserSessionCardViewData.swift b/RiotSwiftUI/Modules/UserSessions/Common/View/UserSessionCardViewData.swift index f36cf0573..f5000095c 100644 --- a/RiotSwiftUI/Modules/UserSessions/Common/View/UserSessionCardViewData.swift +++ b/RiotSwiftUI/Modules/UserSessions/Common/View/UserSessionCardViewData.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,7 +22,7 @@ struct UserSessionCardViewData { private static let lastActivityDateFormatter = UserSessionLastActivityFormatter() var id: String { - return sessionId + sessionId } let sessionId: String diff --git a/RiotSwiftUI/Modules/UserSessions/Coordinator/UserSessionsFlowCoordinator.swift b/RiotSwiftUI/Modules/UserSessions/Coordinator/UserSessionsFlowCoordinator.swift index a032dcfbd..5f2c810c1 100644 --- a/RiotSwiftUI/Modules/UserSessions/Coordinator/UserSessionsFlowCoordinator.swift +++ b/RiotSwiftUI/Modules/UserSessions/Coordinator/UserSessionsFlowCoordinator.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -111,6 +111,6 @@ final class UserSessionsFlowCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return navigationRouter.toPresentable() + navigationRouter.toPresentable() } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Coordinator/UserSessionDetailsCoordinator.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Coordinator/UserSessionDetailsCoordinator.swift index c013711ae..f2302a473 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Coordinator/UserSessionDetailsCoordinator.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Coordinator/UserSessionDetailsCoordinator.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import SwiftUI import CommonKit +import SwiftUI struct UserSessionDetailsCoordinatorParameters { let userSessionInfo: UserSessionInfo @@ -63,6 +63,6 @@ final class UserSessionDetailsCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return userSessionDetailsHostingController + userSessionDetailsHostingController } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/MockUserSessionDetailsScreenState.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/MockUserSessionDetailsScreenState.swift index 3f9a2e634..7c58594fa 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/MockUserSessionDetailsScreenState.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/MockUserSessionDetailsScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,11 +33,11 @@ enum MockUserSessionDetailsScreenState: MockScreenState, CaseIterable { /// A list of screen state definitions static var allCases: [MockUserSessionDetailsScreenState] { // Each of the presence statuses - return [.allSections, .sessionSectionOnly] + [.allSections, .sessionSectionOnly] } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let currentSessionInfo: UserSessionInfo switch self { case .allSections: diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Test/UI/UserSessionDetailsUITests.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Test/UI/UserSessionDetailsUITests.swift index eb9f33e79..6eb573fe9 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Test/UI/UserSessionDetailsUITests.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Test/UI/UserSessionDetailsUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class UserSessionDetailsUITests: MockScreenTestCase { func test_longPressDetailsCell_CopiesValueToClipboard() throws { @@ -30,6 +30,6 @@ class UserSessionDetailsUITests: MockScreenTestCase { app.buttons["Copy"].tap() let clipboard = try XCTUnwrap(UIPasteboard.general.string) - XCTAssertEqual(clipboard,"iOS") + XCTAssertEqual(clipboard, "iOS") } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Test/Unit/UserSessionDetailsViewModelTests.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Test/Unit/UserSessionDetailsViewModelTests.swift index 70026cac0..6e50b6c39 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Test/Unit/UserSessionDetailsViewModelTests.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Test/Unit/UserSessionDetailsViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -96,7 +96,6 @@ class UserSessionDetailsViewModelTests: XCTestCase { isVerified: isVerified, lastSeenIP: lastSeenIP, lastSeenTimestamp: lastSeenTimestamp) - } private func sessionNameItem(sessionName: String) -> UserSessionDetailsSectionItemViewData { diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsModels.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsModels.swift index 0d994add3..456cd5e40 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsModels.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,13 +20,11 @@ import Foundation // MARK: View model -enum UserSessionDetailsViewModelResult { -} +enum UserSessionDetailsViewModelResult { } // MARK: View -enum UserSessionDetailsViewAction { -} +enum UserSessionDetailsViewAction { } struct UserSessionDetailsViewState: BindableState, Equatable { let sections: [UserSessionDetailsSectionViewData] @@ -48,14 +46,14 @@ struct UserSessionDetailsSectionItemViewData: Identifiable { extension UserSessionDetailsSectionViewData: Equatable { static func == (lhs: UserSessionDetailsSectionViewData, rhs: UserSessionDetailsSectionViewData) -> Bool { lhs.header == rhs.header && - lhs.footer == rhs.footer && - lhs.items == rhs.items + lhs.footer == rhs.footer && + lhs.items == rhs.items } } extension UserSessionDetailsSectionItemViewData: Equatable { static func == (lhs: UserSessionDetailsSectionItemViewData, rhs: UserSessionDetailsSectionItemViewData) -> Bool { lhs.title == rhs.title && - lhs.value == rhs.value + lhs.value == rhs.value } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsViewModel.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsViewModel.swift index 3625f7026..91ff61511 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsViewModel.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsViewModel.swift @@ -17,8 +17,8 @@ import Foundation typealias UserSessionDetailsViewModelType = StateStoreViewModel + Never, + UserSessionDetailsViewAction> class UserSessionDetailsViewModel: UserSessionDetailsViewModelType, UserSessionDetailsViewModelProtocol { var completion: ((UserSessionDetailsViewModelResult) -> Void)? diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsViewModelProtocol.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsViewModelProtocol.swift index 0def51625..3fcef2eba 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsViewModelProtocol.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/View/UserSessionDetails.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/View/UserSessionDetails.swift index fb89d2eaf..8801c9ef0 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/View/UserSessionDetails.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/View/UserSessionDetails.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/View/UserSessionDetailsItem.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/View/UserSessionDetailsItem.swift index c484ae35c..80ff02dc5 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/View/UserSessionDetailsItem.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/View/UserSessionDetailsItem.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,7 +28,7 @@ struct UserSessionDetailsItem: View { } var body: some View { - HStack() { + HStack { Text(viewData.title) .font(theme.fonts.subheadline) .foregroundColor(theme.colors.secondaryContent) @@ -59,10 +59,10 @@ struct UserSessionDetailsItem_Previews: PreviewProvider { List { UserSessionDetailsItem(viewData: UserSessionDetailsSectionItemViewData(title: "Session name", value: "Element Web: Firefox on macOS")) - .listRowInsets(EdgeInsets()) + .listRowInsets(EdgeInsets()) UserSessionDetailsItem(viewData: UserSessionDetailsSectionItemViewData(title: "Session ID", value: "76c95352559d-react-7c57680b93db-js-b64dbdce74b0")) - .listRowInsets(EdgeInsets()) + .listRowInsets(EdgeInsets()) } .preferredColorScheme(.light) @@ -70,10 +70,10 @@ struct UserSessionDetailsItem_Previews: PreviewProvider { List { UserSessionDetailsItem(viewData: UserSessionDetailsSectionItemViewData(title: "Session name", value: "Element Web: Firefox on macOS")) - .listRowInsets(EdgeInsets()) + .listRowInsets(EdgeInsets()) UserSessionDetailsItem(viewData: UserSessionDetailsSectionItemViewData(title: "Session ID", value: "76c95352559d-react-7c57680b93db-js-b64dbdce74b0")) - .listRowInsets(EdgeInsets()) + .listRowInsets(EdgeInsets()) } .preferredColorScheme(.dark) .theme(.dark) diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Coordinator/UserSessionOverviewCoordinator.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Coordinator/UserSessionOverviewCoordinator.swift index c7560d5f4..fe236ea94 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Coordinator/UserSessionOverviewCoordinator.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Coordinator/UserSessionOverviewCoordinator.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import SwiftUI import CommonKit +import SwiftUI struct UserSessionOverviewCoordinatorParameters { let userSessionInfo: UserSessionInfo @@ -58,7 +58,7 @@ final class UserSessionOverviewCoordinator: Coordinator, Presentable { MXLog.debug("[UserSessionOverviewCoordinator] UserSessionOverviewViewModel did complete with result: \(result).") switch result { case .verifyCurrentSession: - break // TODO + break // TODO: case let .showSessionDetails(sessionInfo: sessionInfo): self.completion?(.openSessionDetails(session: sessionInfo)) } @@ -66,7 +66,7 @@ final class UserSessionOverviewCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return hostingController + hostingController } // MARK: - Private diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/MockUserSessionOverviewScreenState.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/MockUserSessionOverviewScreenState.swift index 85f22dbd0..00f010d2b 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/MockUserSessionOverviewScreenState.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/MockUserSessionOverviewScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,28 +34,28 @@ enum MockUserSessionOverviewScreenState: MockScreenState, CaseIterable { /// A list of screen state definitions static var allCases: [MockUserSessionOverviewScreenState] { // Each of the presence statuses - return [.currentSession, .otherSession] + [.currentSession, .otherSession] } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { + var screenView: ([Any], AnyView) { let viewModel: UserSessionOverviewViewModel switch self { case .currentSession: let currentSessionInfo = UserSessionInfo(sessionId: "session", - sessionName: "iOS", - deviceType: .mobile, - isVerified: false, - lastSeenIP: "10.0.0.10", - lastSeenTimestamp: Date().timeIntervalSince1970 - 100) + sessionName: "iOS", + deviceType: .mobile, + isVerified: false, + lastSeenIP: "10.0.0.10", + lastSeenTimestamp: Date().timeIntervalSince1970 - 100) viewModel = UserSessionOverviewViewModel(userSessionInfo: currentSessionInfo, isCurrentSession: true) case .otherSession: let currentSessionInfo = UserSessionInfo(sessionId: "session", - sessionName: "Mac", - deviceType: .desktop, - isVerified: true, - lastSeenIP: "10.0.0.10", - lastSeenTimestamp: Date().timeIntervalSince1970 - 100) + sessionName: "Mac", + deviceType: .desktop, + isVerified: true, + lastSeenIP: "10.0.0.10", + lastSeenTimestamp: Date().timeIntervalSince1970 - 100) viewModel = UserSessionOverviewViewModel(userSessionInfo: currentSessionInfo, isCurrentSession: false) } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Test/UI/UserSessionOverviewUITests.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Test/UI/UserSessionOverviewUITests.swift index fa9daf73e..2133c445b 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Test/UI/UserSessionOverviewUITests.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Test/UI/UserSessionOverviewUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class UserSessionOverviewUITests: MockScreenTestCase { func test_whenCurrentSessionSelected_correctNavTittleDisplayed() { diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Test/Unit/UserSessionOverviewViewModelTests.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Test/Unit/UserSessionOverviewViewModelTests.swift index 322b56766..f143f292e 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Test/Unit/UserSessionOverviewViewModelTests.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Test/Unit/UserSessionOverviewViewModelTests.swift @@ -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 @@ -47,10 +47,10 @@ class UserSessionOverviewViewModelTests: XCTestCase { private func createUserSessionInfo() -> UserSessionInfo { UserSessionInfo(sessionId: "session", - sessionName: "iOS", - deviceType: .mobile, - isVerified: false, - lastSeenIP: "10.0.0.10", - lastSeenTimestamp: Date().timeIntervalSince1970 - 100) + sessionName: "iOS", + deviceType: .mobile, + isVerified: false, + lastSeenIP: "10.0.0.10", + lastSeenTimestamp: Date().timeIntervalSince1970 - 100) } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/UserSessionOverviewModels.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/UserSessionOverviewModels.swift index 9283df5c7..e7bf0c271 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/UserSessionOverviewModels.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/UserSessionOverviewModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/UserSessionOverviewViewModel.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/UserSessionOverviewViewModel.swift index 72cd6dc05..afed2b039 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/UserSessionOverviewViewModel.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/UserSessionOverviewViewModel.swift @@ -17,8 +17,8 @@ import SwiftUI typealias UserSessionOverviewViewModelType = StateStoreViewModel + Never, + UserSessionOverviewViewAction> class UserSessionOverviewViewModel: UserSessionOverviewViewModelType, UserSessionOverviewViewModelProtocol { private let userSessionInfo: UserSessionInfo diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/UserSessionOverviewViewModelProtocol.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/UserSessionOverviewViewModelProtocol.swift index 676695c1d..66eed3ba8 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/UserSessionOverviewViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/UserSessionOverviewViewModelProtocol.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverview.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverview.swift index 98a9d4695..b37a2099e 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverview.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverview.swift @@ -25,12 +25,12 @@ struct UserSessionOverview: View { ScrollView { UserSessionCardView(viewData: viewModel.viewState.cardViewData, onVerifyAction: { _ in - viewModel.send(viewAction: .verifyCurrentSession) - }, + viewModel.send(viewAction: .verifyCurrentSession) + }, onViewDetailsAction: { _ in - viewModel.send(viewAction: .viewSessionDetails) - }) - .padding(16) + viewModel.send(viewAction: .viewSessionDetails) + }) + .padding(16) SwiftUI.Section { UserSessionOverviewDisclosureCell(title: VectorL10n.userSessionOverviewSessionDetailsButtonTitle, onBackgroundTap: { viewModel.send(viewAction: .viewSessionDetails) @@ -40,8 +40,8 @@ struct UserSessionOverview: View { .background(theme.colors.system.ignoresSafeArea()) .frame(maxHeight: .infinity) .navigationTitle(viewModel.viewState.isCurrentSession ? - VectorL10n.userSessionOverviewCurrentSessionTitle : - VectorL10n.userSessionOverviewSessionTitle) + VectorL10n.userSessionOverviewCurrentSessionTitle : + VectorL10n.userSessionOverviewSessionTitle) } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverviewDisclosureCell.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverviewDisclosureCell.swift index 027f5f0bd..e4146e9a7 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverviewDisclosureCell.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverviewDisclosureCell.swift @@ -20,13 +20,13 @@ struct UserSessionOverviewDisclosureCell: View { @Environment(\.theme) private var theme: ThemeSwiftUI let title: String - var onBackgroundTap: (() -> (Void))? = nil + var onBackgroundTap: (() -> Void)? var body: some View { - Button(action: { onBackgroundTap?()}) { + Button(action: { onBackgroundTap?() }) { VStack(spacing: 0) { SeparatorLine() - HStack() { + HStack { Text(title) .font(theme.fonts.body) .foregroundColor(theme.colors.primaryContent) diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Coordinator/UserSessionsOverviewCoordinator.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Coordinator/UserSessionsOverviewCoordinator.swift index 74afa6c23..44717d9d0 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Coordinator/UserSessionsOverviewCoordinator.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Coordinator/UserSessionsOverviewCoordinator.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import SwiftUI import CommonKit +import SwiftUI struct UserSessionsOverviewCoordinatorParameters { let session: MXSession @@ -69,7 +69,7 @@ final class UserSessionsOverviewCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return hostingViewController + hostingViewController } // MARK: - Private @@ -88,15 +88,15 @@ final class UserSessionsOverviewCoordinator: Coordinator, Presentable { } private func showAllUnverifiedSessions() { - // TODO + // TODO: } private func showAllInactiveSessions() { - // TODO + // TODO: } private func startVerifyCurrentSession() { - // TODO + // TODO: } private func showCurrentSessionOverview(sessionInfo: UserSessionInfo) { @@ -108,6 +108,6 @@ final class UserSessionsOverviewCoordinator: Coordinator, Presentable { } private func showAllOtherSessions() { - // TODO + // TODO: } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/MockUserSessionsOverviewScreenState.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/MockUserSessionsOverviewScreenState.swift index a0b67dafc..710c54294 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/MockUserSessionsOverviewScreenState.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/MockUserSessionsOverviewScreenState.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,12 +33,12 @@ enum MockUserSessionsOverviewScreenState: MockScreenState, CaseIterable { /// A list of screen state definitions static var allCases: [MockUserSessionsOverviewScreenState] { // Each of the presence statuses - return [.verifiedSession] + [.verifiedSession] } /// Generate the view struct for the screen state. - var screenView: ([Any], AnyView) { - let service: MockUserSessionsOverviewService = MockUserSessionsOverviewService() + var screenView: ([Any], AnyView) { + let service = MockUserSessionsOverviewService() switch self { case .verifiedSession: break diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/MatrixSDK/UserSessionsOverviewService.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/MatrixSDK/UserSessionsOverviewService.swift index 2844b2269..aa387325d 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/MatrixSDK/UserSessionsOverviewService.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/MatrixSDK/UserSessionsOverviewService.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,10 +25,10 @@ class UserSessionsOverviewService: UserSessionsOverviewServiceProtocol { init(mxSession: MXSession) { self.mxSession = mxSession - overviewData = UserSessionsOverviewData(currentSession: nil, - unverifiedSessions: [], - inactiveSessions: [], - otherSessions: []) + overviewData = UserSessionsOverviewData(currentSession: nil, + unverifiedSessions: [], + inactiveSessions: [], + otherSessions: []) setupInitialOverviewData() } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/Mock/MockUserSessionsOverviewService.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/Mock/MockUserSessionsOverviewService.swift index 89b8d3aa3..a70df0cf5 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/Mock/MockUserSessionsOverviewService.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/Mock/MockUserSessionsOverviewService.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,14 +35,14 @@ class MockUserSessionsOverviewService: UserSessionsOverviewServiceProtocol { let inactiveSessionsInfo: [UserSessionInfo] = [] let otherSessionsInfo: [UserSessionInfo] = [ - UserSessionInfo(sessionId: "1", sessionName: "macOS", deviceType: .desktop, isVerified: true, lastSeenIP: "1.0.0.1", lastSeenTimestamp: (Date().timeIntervalSince1970 - 130000)), - UserSessionInfo(sessionId: "2", sessionName: "Firefox on Windows", deviceType: .web, isVerified: true, lastSeenIP: "2.0.0.2", lastSeenTimestamp: (Date().timeIntervalSince1970 - 100)), - UserSessionInfo(sessionId: "3", sessionName: "Android", deviceType: .mobile, isVerified: false, lastSeenIP: "3.0.0.3", lastSeenTimestamp: (Date().timeIntervalSince1970 - 10)) + UserSessionInfo(sessionId: "1", sessionName: "macOS", deviceType: .desktop, isVerified: true, lastSeenIP: "1.0.0.1", lastSeenTimestamp: Date().timeIntervalSince1970 - 130_000), + UserSessionInfo(sessionId: "2", sessionName: "Firefox on Windows", deviceType: .web, isVerified: true, lastSeenIP: "2.0.0.2", lastSeenTimestamp: Date().timeIntervalSince1970 - 100), + UserSessionInfo(sessionId: "3", sessionName: "Android", deviceType: .mobile, isVerified: false, lastSeenIP: "3.0.0.3", lastSeenTimestamp: Date().timeIntervalSince1970 - 10) ] overviewData = UserSessionsOverviewData(currentSession: currentSessionInfo, - unverifiedSessions: unverifiedSessionsInfo, - inactiveSessions: inactiveSessionsInfo, - otherSessions: otherSessionsInfo) + unverifiedSessions: unverifiedSessionsInfo, + inactiveSessions: inactiveSessionsInfo, + otherSessions: otherSessionsInfo) } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/UserSessionsOverviewServiceProtocol.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/UserSessionsOverviewServiceProtocol.swift index 9b3e81706..b1bc5f001 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/UserSessionsOverviewServiceProtocol.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/UserSessionsOverviewServiceProtocol.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Test/UI/UserSessionsOverviewUITests.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Test/UI/UserSessionsOverviewUITests.swift index 136372d89..caede94d6 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Test/UI/UserSessionsOverviewUITests.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Test/UI/UserSessionsOverviewUITests.swift @@ -14,8 +14,8 @@ // limitations under the License. // -import XCTest import RiotSwiftUI +import XCTest class UserSessionsOverviewUITests: MockScreenTestCase { // TODO: diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Test/Unit/UserSessionsOverviewViewModelTests.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Test/Unit/UserSessionsOverviewViewModelTests.swift index d9c2ecb9c..1d24d1586 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Test/Unit/UserSessionsOverviewViewModelTests.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Test/Unit/UserSessionsOverviewViewModelTests.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 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 diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewModels.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewModels.swift index 8e66bd0e2..455a4b72a 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewModels.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewModels.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -44,7 +44,7 @@ struct UserSessionsOverviewViewState: BindableState { var otherSessionsViewData = [UserSessionListItemViewData]() - var showLoadingIndicator: Bool = false + var showLoadingIndicator = false } enum UserSessionsOverviewViewAction { diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewViewModel.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewViewModel.swift index 855cc2e19..ee7a82717 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewViewModel.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewViewModel.swift @@ -17,8 +17,8 @@ import SwiftUI typealias UserSessionsOverviewViewModelType = StateStoreViewModel + Never, + UserSessionsOverviewViewAction> class UserSessionsOverviewViewModel: UserSessionsOverviewViewModelType, UserSessionsOverviewViewModelProtocol { private let userSessionsOverviewService: UserSessionsOverviewServiceProtocol @@ -88,7 +88,7 @@ class UserSessionsOverviewViewModel: UserSessionsOverviewViewModelType, UserSess case .success(let overViewData): self.updateViewState(with: overViewData) case .failure(let error): - // TODO + // TODO: break } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewViewModelProtocol.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewViewModelProtocol.swift index ebbb790a9..01b4b45ba 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewViewModelProtocol.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionListItem.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionListItem.swift index e60a366f3..297998f29 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionListItem.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionListItem.swift @@ -28,7 +28,7 @@ struct UserSessionListItem: View { let viewData: UserSessionListItemViewData - var onBackgroundTap: ((String) -> (Void))? = nil + var onBackgroundTap: ((String) -> Void)? var body: some View { Button { @@ -71,7 +71,7 @@ struct UserSessionListPreview: View { ForEach(userSessionsOverviewService.overviewData.otherSessions) { userSessionInfo in let viewData = UserSessionListItemViewData(userSessionInfo: userSessionInfo) - UserSessionListItem(viewData: viewData, onBackgroundTap: { sessionId in + UserSessionListItem(viewData: viewData, onBackgroundTap: { _ in }) } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionListItemViewData.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionListItemViewData.swift index a682cd8e4..78a5fab53 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionListItemViewData.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionListItemViewData.swift @@ -22,7 +22,7 @@ struct UserSessionListItemViewData: Identifiable { private static let lastActivityDateFormatter = UserSessionLastActivityFormatter() var id: String { - return sessionId + sessionId } let sessionId: String @@ -38,7 +38,6 @@ struct UserSessionListItemViewData: Identifiable { deviceType: DeviceType, isVerified: Bool, lastActivityDate: TimeInterval?) { - self.sessionId = sessionId sessionName = Self.userSessionNameFormatter.sessionName(deviceType: deviceType, sessionDisplayName: sessionDisplayName) sessionDetails = Self.buildSessionDetails(isVerified: isVerified, lastActivityDate: lastActivityDate) diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionsOverview.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionsOverview.swift index 565718d69..0d2c5cabe 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionsOverview.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionsOverview.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2022 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -49,7 +49,6 @@ struct UserSessionsOverview: View { ScrollView { // Security recommendations section if viewModel.viewState.unverifiedSessionsViewData.isEmpty == false || viewModel.viewState.inactiveSessionsViewData.isEmpty == false { - // TODO: } @@ -65,7 +64,7 @@ struct UserSessionsOverview: View { .frame(maxHeight: .infinity) .navigationTitle(VectorL10n.userSessionsOverviewTitle) .activityIndicator(show: viewModel.viewState.showLoadingIndicator) - .onAppear() { + .onAppear { viewModel.send(viewAction: .viewAppeared) } } diff --git a/RiotSwiftUI/RiotSwiftUIApp.swift b/RiotSwiftUI/RiotSwiftUIApp.swift index d63504e2f..04ed5e39c 100644 --- a/RiotSwiftUI/RiotSwiftUIApp.swift +++ b/RiotSwiftUI/RiotSwiftUIApp.swift @@ -1,4 +1,4 @@ -// +// // Copyright 2021 New Vector Ltd // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,7 +39,7 @@ struct RiotSwiftUIApp: App { } class RiotSwiftUIAppDelegate: NSObject, UIApplicationDelegate { - func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { + func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool { if ProcessInfo.processInfo.environment["IS_RUNNING_UI_TESTS"] == "1" { UIView.setAnimationsEnabled(false) } diff --git a/RiotSwiftUI/target.yml b/RiotSwiftUI/target.yml index 428fbbdb2..ed0ebee39 100644 --- a/RiotSwiftUI/target.yml +++ b/RiotSwiftUI/target.yml @@ -66,3 +66,15 @@ targets: configFiles: Debug: Debug.xcconfig Release: Release.xcconfig + + postBuildScripts: + - name: 🧹 SwiftFormat + runOnlyWhenInstalling: false + shell: /bin/sh + script: | + export PATH="$PATH:/opt/homebrew/bin" + if which swiftformat >/dev/null; then + swiftformat --lint --lenient "$PROJECT_DIR" + else + echo "warning: SwiftFormat not installed, download from https://github.com/nicklockwood/SwiftFormat" + fi