From 148bc1624add920cef17ab5b7e89712804a72d22 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Mon, 26 Sep 2022 18:21:34 +0300 Subject: [PATCH] Cleaned up various things, mostly removed unnecessary `self`s, comments and bad formatting --- .../UserSessions/Common/SeparatorLine.swift | 1 - .../DeviceAvatar/DeviceAvatarView.swift | 3 - .../DeviceAvatar/DeviceAvatarViewData.swift | 2 - .../DeviceType/DeviceType+Element.swift | 58 ---------------- .../UserSessions/DeviceType/DeviceType.swift | 28 ++++++++ .../UserSessionCardView.swift | 11 ++- .../UserSessionCardViewData.swift | 22 +++--- .../UserSessionDetailsCoordinator.swift | 12 ++-- .../Test/UI/UserSessionDetailsUITests.swift | 1 - .../UserSessionDetailsViewModelTests.swift | 1 - .../UserSessionDetailsModels.swift | 3 - .../UserSessionDetailsViewModel.swift | 9 --- .../UserSessionDetailsViewModelProtocol.swift | 1 - .../View/UserSessionDetails.swift | 7 -- .../View/UserSessionDetailsItem.swift | 7 -- .../UserSessionLastActivityFormatter.swift | 5 -- .../UserSessionNameFormatter.swift | 4 +- .../UserSessionInfo/UserSessionInfo.swift | 8 +-- .../UserSessionOverviewCoordinator.swift | 25 +++---- .../MockUserSessionOverviewScreenState.swift | 6 +- .../Test/UI/UserSessionOverviewUITests.swift | 1 - .../UserSessionOverviewViewModelTests.swift | 1 - .../UserSessionOverviewViewModel.swift | 7 -- ...UserSessionOverviewViewModelProtocol.swift | 1 - .../View/UserSessionOverview.swift | 7 -- .../UserSessionOverviewDisclosureCell.swift | 1 - .../UserSessionsFlowCoordinator.swift | 27 +++----- ...ssionsFlowCoordinatorBridgePresenter.swift | 29 ++------ .../UserSessionsOverviewCoordinator.swift | 30 +++----- .../UserSessionsOverviewService.swift | 39 ++++------- .../MockUserSessionsOverviewService.swift | 8 ++- .../UserSessionsOverviewServiceProtocol.swift | 2 - .../UserSessionsOverviewViewModelTests.swift | 1 - .../UserSessionsOverviewModels.swift | 11 ++- .../UserSessionsOverviewViewModel.swift | 68 +++++++------------ ...serSessionsOverviewViewModelProtocol.swift | 1 - .../View/UserSessionListItem.swift | 17 +---- .../View/UserSessionListItemViewData.swift | 17 ++--- .../View/UserSessionsOverview.swift | 9 +-- 39 files changed, 141 insertions(+), 350 deletions(-) delete mode 100644 RiotSwiftUI/Modules/UserSessions/DeviceType/DeviceType+Element.swift diff --git a/RiotSwiftUI/Modules/UserSessions/Common/SeparatorLine.swift b/RiotSwiftUI/Modules/UserSessions/Common/SeparatorLine.swift index a0ae9c043..87d1a47d8 100644 --- a/RiotSwiftUI/Modules/UserSessions/Common/SeparatorLine.swift +++ b/RiotSwiftUI/Modules/UserSessions/Common/SeparatorLine.swift @@ -17,7 +17,6 @@ import SwiftUI struct SeparatorLine: View { - @Environment(\.theme) private var theme: ThemeSwiftUI var body: some View { diff --git a/RiotSwiftUI/Modules/UserSessions/DeviceAvatar/DeviceAvatarView.swift b/RiotSwiftUI/Modules/UserSessions/DeviceAvatar/DeviceAvatarView.swift index a24567171..24a142619 100644 --- a/RiotSwiftUI/Modules/UserSessions/DeviceAvatar/DeviceAvatarView.swift +++ b/RiotSwiftUI/Modules/UserSessions/DeviceAvatar/DeviceAvatarView.swift @@ -19,7 +19,6 @@ import DesignKit /// Avatar view for device struct DeviceAvatarView: View { - @Environment(\.theme) var theme: ThemeSwiftUI var viewData: DeviceAvatarViewData @@ -55,7 +54,6 @@ struct DeviceAvatarView: View { } struct DeviceAvatarViewListPreview: View { - var viewDataList: [DeviceAvatarViewData] { return [ DeviceAvatarViewData(deviceType: .desktop, isVerified: true), @@ -78,7 +76,6 @@ struct DeviceAvatarViewListPreview: View { } struct DeviceAvatarView_Previews: PreviewProvider { - static var previews: some View { Group { DeviceAvatarViewListPreview().theme(.light).preferredColorScheme(.light) diff --git a/RiotSwiftUI/Modules/UserSessions/DeviceAvatar/DeviceAvatarViewData.swift b/RiotSwiftUI/Modules/UserSessions/DeviceAvatar/DeviceAvatarViewData.swift index 19c6cfd1d..e4dd59b26 100644 --- a/RiotSwiftUI/Modules/UserSessions/DeviceAvatar/DeviceAvatarViewData.swift +++ b/RiotSwiftUI/Modules/UserSessions/DeviceAvatar/DeviceAvatarViewData.swift @@ -19,8 +19,6 @@ import SwiftUI /// View data for DeviceAvatarView struct DeviceAvatarViewData { - let deviceType: DeviceType - let isVerified: Bool? } diff --git a/RiotSwiftUI/Modules/UserSessions/DeviceType/DeviceType+Element.swift b/RiotSwiftUI/Modules/UserSessions/DeviceType/DeviceType+Element.swift deleted file mode 100644 index ecbad3537..000000000 --- a/RiotSwiftUI/Modules/UserSessions/DeviceType/DeviceType+Element.swift +++ /dev/null @@ -1,58 +0,0 @@ -// -// Copyright 2022 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation -import SwiftUI - -extension DeviceType { - - var image: Image { - - let image: Image - - switch self { - case .desktop: - image = Image(Asset.Images.deviceTypeDesktop.name) - case .web: - image = Image(Asset.Images.deviceTypeWeb.name) - case .mobile: - image = Image(Asset.Images.deviceTypeMobile.name) - case .unknown: - image = Image(Asset.Images.deviceTypeUnknown.name) - } - - return image - } - - var name: String { - let name: String - - let appName = AppInfo.current.displayName - - switch self { - case .desktop: - name = VectorL10n.deviceNameDesktop(appName) - case .web: - name = VectorL10n.deviceNameWeb(appName) - case .mobile: - name = VectorL10n.deviceNameMobile(appName) - case .unknown: - name = VectorL10n.deviceNameUnknown - } - - return name - } -} diff --git a/RiotSwiftUI/Modules/UserSessions/DeviceType/DeviceType.swift b/RiotSwiftUI/Modules/UserSessions/DeviceType/DeviceType.swift index 1ae053b1a..7410be89a 100644 --- a/RiotSwiftUI/Modules/UserSessions/DeviceType/DeviceType.swift +++ b/RiotSwiftUI/Modules/UserSessions/DeviceType/DeviceType.swift @@ -23,4 +23,32 @@ enum DeviceType { case web case mobile case unknown + + var image: Image { + switch self { + case .desktop: + return Image(Asset.Images.deviceTypeDesktop.name) + case .web: + return Image(Asset.Images.deviceTypeWeb.name) + case .mobile: + return Image(Asset.Images.deviceTypeMobile.name) + case .unknown: + return Image(Asset.Images.deviceTypeUnknown.name) + } + } + + var name: String { + let appName = AppInfo.current.displayName + + switch self { + case .desktop: + return VectorL10n.deviceNameDesktop(appName) + case .web: + return VectorL10n.deviceNameWeb(appName) + case .mobile: + return VectorL10n.deviceNameMobile(appName) + case .unknown: + return VectorL10n.deviceNameUnknown + } + } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionCardView/UserSessionCardView.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionCardView/UserSessionCardView.swift index 7032d5701..b423f4e7c 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionCardView/UserSessionCardView.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionCardView/UserSessionCardView.swift @@ -18,7 +18,6 @@ import SwiftUI import DesignKit struct UserSessionCardView: View { - @Environment(\.theme) var theme: ThemeSwiftUI var viewData: UserSessionCardViewData @@ -82,7 +81,7 @@ struct UserSessionCardView: View { .multilineTextAlignment(.center) } - if self.showExtraInformations { + if showExtraInformations { VStack(spacing: 2) { if let lastActivityDateString = viewData.lastActivityDateString, lastActivityDateString.isEmpty == false { Text(lastActivityDateString) @@ -126,13 +125,12 @@ struct UserSessionCardView: View { .padding(24) .frame(maxWidth: .infinity) .background(theme.colors.background) - .clipShape(self.backgroundShape) - .shapedBorder(color: theme.colors.quinaryContent, borderWidth: 1.0, shape: self.backgroundShape) + .clipShape(backgroundShape) + .shapedBorder(color: theme.colors.quinaryContent, borderWidth: 1.0, shape: backgroundShape) } } struct UserSessionCardViewPreview: View { - @Environment(\.theme) var theme: ThemeSwiftUI let viewData: UserSessionCardViewData @@ -145,7 +143,7 @@ struct UserSessionCardViewPreview: View { var body: some View { VStack { - UserSessionCardView(viewData: self.viewData) + UserSessionCardView(viewData: viewData) } .frame(maxWidth: .infinity) .background(theme.colors.system) @@ -154,7 +152,6 @@ struct UserSessionCardViewPreview: View { } struct UserSessionCardView_Previews: PreviewProvider { - static var previews: some View { Group { UserSessionCardViewPreview(isCurrentSessionInfo: true).theme(.light).preferredColorScheme(.light) diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionCardView/UserSessionCardViewData.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionCardView/UserSessionCardViewData.swift index d63175a0e..f36cf0573 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionCardView/UserSessionCardViewData.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionCardView/UserSessionCardViewData.swift @@ -18,13 +18,8 @@ import Foundation /// View data for UserSessionCardView struct UserSessionCardViewData { - - // MARK: - Constants - private static let userSessionNameFormatter = UserSessionNameFormatter() private static let lastActivityDateFormatter = UserSessionLastActivityFormatter() - - // MARK: - Properties var id: String { return sessionId @@ -45,8 +40,6 @@ struct UserSessionCardViewData { /// Indicate if the current user session is shown and to adpat the layout let isCurrentSessionDisplayMode: Bool - // MARK: - Setup - init(sessionId: String, sessionDisplayName: String?, deviceType: DeviceType, @@ -55,7 +48,7 @@ struct UserSessionCardViewData { lastSeenIP: String?, isCurrentSessionDisplayMode: Bool = false) { self.sessionId = sessionId - self.sessionName = Self.userSessionNameFormatter.sessionName(deviceType: deviceType, sessionDisplayName: sessionDisplayName) + sessionName = Self.userSessionNameFormatter.sessionName(deviceType: deviceType, sessionDisplayName: sessionDisplayName) self.isVerified = isVerified var lastActivityDateString: String? @@ -65,16 +58,21 @@ struct UserSessionCardViewData { } self.lastActivityDateString = lastActivityDateString - self.lastSeenIPInfo = lastSeenIP - self.deviceAvatarViewData = DeviceAvatarViewData(deviceType: deviceType, isVerified: nil) + lastSeenIPInfo = lastSeenIP + deviceAvatarViewData = DeviceAvatarViewData(deviceType: deviceType, isVerified: nil) self.isCurrentSessionDisplayMode = isCurrentSessionDisplayMode } } extension UserSessionCardViewData { - init(userSessionInfo: UserSessionInfo, isCurrentSessionDisplayMode: Bool = false) { - self.init(sessionId: userSessionInfo.sessionId, sessionDisplayName: userSessionInfo.sessionName, deviceType: userSessionInfo.deviceType, isVerified: userSessionInfo.isVerified, lastActivityTimestamp: userSessionInfo.lastSeenTimestamp, lastSeenIP: userSessionInfo.lastSeenIP, isCurrentSessionDisplayMode: isCurrentSessionDisplayMode) + self.init(sessionId: userSessionInfo.sessionId, + sessionDisplayName: userSessionInfo.sessionName, + deviceType: userSessionInfo.deviceType, + isVerified: userSessionInfo.isVerified, + lastActivityTimestamp: userSessionInfo.lastSeenTimestamp, + lastSeenIP: userSessionInfo.lastSeenIP, + isCurrentSessionDisplayMode: isCurrentSessionDisplayMode) } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Coordinator/UserSessionDetailsCoordinator.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Coordinator/UserSessionDetailsCoordinator.swift index 28b16168a..c013711ae 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Coordinator/UserSessionDetailsCoordinator.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Coordinator/UserSessionDetailsCoordinator.swift @@ -22,11 +22,6 @@ struct UserSessionDetailsCoordinatorParameters { } final class UserSessionDetailsCoordinator: Coordinator, Presentable { - - // MARK: - Properties - - // MARK: Private - private let parameters: UserSessionDetailsCoordinatorParameters private let userSessionDetailsHostingController: UIViewController private var userSessionDetailsViewModel: UserSessionDetailsViewModelProtocol @@ -58,13 +53,16 @@ final class UserSessionDetailsCoordinator: Coordinator, Presentable { func start() { MXLog.debug("[UserSessionDetailsCoordinator] did start.") userSessionDetailsViewModel.completion = { [weak self] result in - guard let self = self else { return } + guard let self = self else { + return + } + MXLog.debug("[UserSessionDetailsCoordinator] UserSessionDetailsViewModel did complete with result: \(result).") self.completion?(result) } } func toPresentable() -> UIViewController { - return self.userSessionDetailsHostingController + return userSessionDetailsHostingController } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Test/UI/UserSessionDetailsUITests.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Test/UI/UserSessionDetailsUITests.swift index 60c5308f4..eb9f33e79 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Test/UI/UserSessionDetailsUITests.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Test/UI/UserSessionDetailsUITests.swift @@ -18,7 +18,6 @@ import XCTest import RiotSwiftUI class UserSessionDetailsUITests: MockScreenTestCase { - func test_longPressDetailsCell_CopiesValueToClipboard() throws { app.goToScreenWithIdentifier(MockUserSessionDetailsScreenState.allSections.title) diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Test/Unit/UserSessionDetailsViewModelTests.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Test/Unit/UserSessionDetailsViewModelTests.swift index c5aa629b5..70026cac0 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Test/Unit/UserSessionDetailsViewModelTests.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/Test/Unit/UserSessionDetailsViewModelTests.swift @@ -19,7 +19,6 @@ import XCTest @testable import RiotSwiftUI class UserSessionDetailsViewModelTests: XCTestCase { - func test_whenSessionNameAndLastSeenIPNil_viewStateCorrect() { let userSessionInfo = createUserSessionInfo(sessionId: "session", sessionName: nil, diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsModels.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsModels.swift index 38d4cf31a..0d994add3 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsModels.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsModels.swift @@ -29,7 +29,6 @@ enum UserSessionDetailsViewAction { } struct UserSessionDetailsViewState: BindableState, Equatable { - let sections: [UserSessionDetailsSectionViewData] } @@ -47,7 +46,6 @@ struct UserSessionDetailsSectionItemViewData: Identifiable { } extension UserSessionDetailsSectionViewData: Equatable { - static func == (lhs: UserSessionDetailsSectionViewData, rhs: UserSessionDetailsSectionViewData) -> Bool { lhs.header == rhs.header && lhs.footer == rhs.footer && @@ -56,7 +54,6 @@ extension UserSessionDetailsSectionViewData: Equatable { } extension UserSessionDetailsSectionItemViewData: Equatable { - static func == (lhs: UserSessionDetailsSectionItemViewData, rhs: UserSessionDetailsSectionItemViewData) -> Bool { lhs.title == rhs.title && lhs.value == rhs.value diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsViewModel.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsViewModel.swift index c4b04bfec..3625f7026 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsViewModel.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsViewModel.swift @@ -21,17 +21,8 @@ typealias UserSessionDetailsViewModelType = StateStoreViewModel class UserSessionDetailsViewModel: UserSessionDetailsViewModelType, UserSessionDetailsViewModelProtocol { - - // MARK: - Properties - - // MARK: Private - - // MARK: Public - var completion: ((UserSessionDetailsViewModelResult) -> Void)? - // MARK: - Setup - init(userSessionInfo: UserSessionInfo) { super.init(initialViewState: UserSessionDetailsViewState(sections: [])) updateViewState(userSessionInfo: userSessionInfo) diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsViewModelProtocol.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsViewModelProtocol.swift index 8222cc770..0def51625 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/UserSessionDetailsViewModelProtocol.swift @@ -17,7 +17,6 @@ import Foundation protocol UserSessionDetailsViewModelProtocol { - var completion: ((UserSessionDetailsViewModelResult) -> Void)? { get set } var context: UserSessionDetailsViewModelType.Context { get } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/View/UserSessionDetails.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/View/UserSessionDetails.swift index 3be803271..fb89d2eaf 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/View/UserSessionDetails.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/View/UserSessionDetails.swift @@ -17,11 +17,6 @@ import SwiftUI struct UserSessionDetails: View { - - // MARK: - Properties - - // MARK: Private - private enum LayoutConstants { static let listItemHorizontalPadding: CGFloat = 20 static let sectionVerticalPadding: CGFloat = 8 @@ -29,8 +24,6 @@ struct UserSessionDetails: View { @Environment(\.theme) private var theme: ThemeSwiftUI - // MARK: Public - @ObservedObject var viewModel: UserSessionDetailsViewModel.Context var body: some View { diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/View/UserSessionDetailsItem.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/View/UserSessionDetailsItem.swift index 870ac606a..c484ae35c 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/View/UserSessionDetailsItem.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionDetails/View/UserSessionDetailsItem.swift @@ -17,15 +17,8 @@ import SwiftUI struct UserSessionDetailsItem: View { - - // MARK: - Properties - - // MARK: Private - @Environment(\.theme) private var theme: ThemeSwiftUI - // MARK: Public - let viewData: UserSessionDetailsSectionItemViewData let horizontalPadding: CGFloat diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionFormatters/UserSessionLastActivityFormatter.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionFormatters/UserSessionLastActivityFormatter.swift index 891e0919b..a3482d466 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionFormatters/UserSessionLastActivityFormatter.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionFormatters/UserSessionLastActivityFormatter.swift @@ -18,9 +18,6 @@ import Foundation /// Enables to build last activity date string class UserSessionLastActivityFormatter { - - // MARK: - Constants - private static var lastActivityDateFormatter: DateFormatter = { let dateFormatter = DateFormatter() dateFormatter.locale = Locale.current @@ -30,8 +27,6 @@ class UserSessionLastActivityFormatter { return dateFormatter }() - // MARK: - Public - /// Session last activity string func lastActivityDateString(from lastActivityTimestamp: TimeInterval) -> String { diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionFormatters/UserSessionNameFormatter.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionFormatters/UserSessionNameFormatter.swift index 0aed1082f..375aa8034 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionFormatters/UserSessionNameFormatter.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionFormatters/UserSessionNameFormatter.swift @@ -17,11 +17,9 @@ 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 let clientName = deviceType.name diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionInfo/UserSessionInfo.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionInfo/UserSessionInfo.swift index 6009bfcb2..f8679b6df 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionInfo/UserSessionInfo.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionInfo/UserSessionInfo.swift @@ -18,7 +18,6 @@ import Foundation /// Represents a user session information struct UserSessionInfo: Identifiable { - /// Delay after which session is considered inactive, 90 days static let inactiveSessionDurationTreshold: TimeInterval = 90 * 86400 @@ -67,12 +66,9 @@ struct UserSessionInfo: Identifiable { if let lastSeenTimestamp = lastSeenTimestamp { let elapsedTime = Date().timeIntervalSince1970 - lastSeenTimestamp - - let isSessionInactive = elapsedTime >= Self.inactiveSessionDurationTreshold - - self.isSessionActive = !isSessionInactive + isSessionActive = elapsedTime < Self.inactiveSessionDurationTreshold } else { - self.isSessionActive = true + isSessionActive = true } } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Coordinator/UserSessionOverviewCoordinator.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Coordinator/UserSessionOverviewCoordinator.swift index 0748a7347..c7560d5f4 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Coordinator/UserSessionOverviewCoordinator.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Coordinator/UserSessionOverviewCoordinator.swift @@ -23,14 +23,9 @@ struct UserSessionOverviewCoordinatorParameters { } final class UserSessionOverviewCoordinator: Coordinator, Presentable { - - // MARK: - Properties - - // MARK: Private - private let parameters: UserSessionOverviewCoordinatorParameters - private let userSessionOverviewHostingController: UIViewController - private var userSessionOverviewViewModel: UserSessionOverviewViewModelProtocol + private let hostingController: UIViewController + private var viewModel: UserSessionOverviewViewModelProtocol private var indicatorPresenter: UserIndicatorTypePresenterProtocol private var loadingIndicator: UserIndicator? @@ -45,20 +40,20 @@ final class UserSessionOverviewCoordinator: Coordinator, Presentable { init(parameters: UserSessionOverviewCoordinatorParameters) { self.parameters = parameters - let viewModel = UserSessionOverviewViewModel(userSessionInfo: parameters.userSessionInfo, - isCurrentSession: parameters.isCurrentSession) - let view = UserSessionOverview(viewModel: viewModel.context) - userSessionOverviewViewModel = viewModel - userSessionOverviewHostingController = VectorHostingController(rootView: view) + + viewModel = UserSessionOverviewViewModel(userSessionInfo: parameters.userSessionInfo, + isCurrentSession: parameters.isCurrentSession) - indicatorPresenter = UserIndicatorTypePresenter(presentingViewController: userSessionOverviewHostingController) + hostingController = VectorHostingController(rootView: UserSessionOverview(viewModel: viewModel.context)) + + indicatorPresenter = UserIndicatorTypePresenter(presentingViewController: hostingController) } // MARK: - Public func start() { MXLog.debug("[UserSessionOverviewCoordinator] did start.") - userSessionOverviewViewModel.completion = { [weak self] result in + viewModel.completion = { [weak self] result in guard let self = self else { return } MXLog.debug("[UserSessionOverviewCoordinator] UserSessionOverviewViewModel did complete with result: \(result).") switch result { @@ -71,7 +66,7 @@ final class UserSessionOverviewCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.userSessionOverviewHostingController + return hostingController } // MARK: - Private diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/MockUserSessionOverviewScreenState.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/MockUserSessionOverviewScreenState.swift index a24ea52bb..85f22dbd0 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/MockUserSessionOverviewScreenState.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/MockUserSessionOverviewScreenState.swift @@ -60,10 +60,6 @@ enum MockUserSessionOverviewScreenState: MockScreenState, CaseIterable { } // can simulate service and viewModel actions here if needs be. - - return ( - [viewModel], - AnyView(UserSessionOverview(viewModel: viewModel.context)) - ) + return ([viewModel], AnyView(UserSessionOverview(viewModel: viewModel.context))) } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Test/UI/UserSessionOverviewUITests.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Test/UI/UserSessionOverviewUITests.swift index 192f0a9db..fa9daf73e 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Test/UI/UserSessionOverviewUITests.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Test/UI/UserSessionOverviewUITests.swift @@ -18,7 +18,6 @@ import XCTest import RiotSwiftUI class UserSessionOverviewUITests: MockScreenTestCase { - func test_whenCurrentSessionSelected_correctNavTittleDisplayed() { app.goToScreenWithIdentifier(MockUserSessionOverviewScreenState.currentSession.title) let navTitle = VectorL10n.userSessionOverviewCurrentSessionTitle diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Test/Unit/UserSessionOverviewViewModelTests.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Test/Unit/UserSessionOverviewViewModelTests.swift index f3bfe84a6..322b56766 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Test/Unit/UserSessionOverviewViewModelTests.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/Test/Unit/UserSessionOverviewViewModelTests.swift @@ -20,7 +20,6 @@ import Combine @testable import RiotSwiftUI class UserSessionOverviewViewModelTests: XCTestCase { - var sut: UserSessionOverviewViewModel! func test_whenVerifyCurrentSessionProcessed_completionWithVerifyCurrentSessionCalled() { diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/UserSessionOverviewViewModel.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/UserSessionOverviewViewModel.swift index efb8063dc..72cd6dc05 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/UserSessionOverviewViewModel.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/UserSessionOverviewViewModel.swift @@ -21,17 +21,10 @@ typealias UserSessionOverviewViewModelType = StateStoreViewModel class UserSessionOverviewViewModel: UserSessionOverviewViewModelType, UserSessionOverviewViewModelProtocol { - - // MARK: - Properties - - // MARK: Private private let userSessionInfo: UserSessionInfo - // MARK: Public var completion: ((UserSessionOverviewViewModelResult) -> Void)? - // MARK: - Setup - init(userSessionInfo: UserSessionInfo, isCurrentSession: Bool) { self.userSessionInfo = userSessionInfo diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/UserSessionOverviewViewModelProtocol.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/UserSessionOverviewViewModelProtocol.swift index 014dcd8a7..676695c1d 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/UserSessionOverviewViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/UserSessionOverviewViewModelProtocol.swift @@ -17,7 +17,6 @@ import Foundation protocol UserSessionOverviewViewModelProtocol { - var completion: ((UserSessionOverviewViewModelResult) -> Void)? { get set } var context: UserSessionOverviewViewModelType.Context { get } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverview.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverview.swift index 0590fbfef..98a9d4695 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverview.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverview.swift @@ -17,15 +17,8 @@ import SwiftUI struct UserSessionOverview: View { - - // MARK: - Properties - - // MARK: Private - @Environment(\.theme) private var theme: ThemeSwiftUI - // MARK: Public - @ObservedObject var viewModel: UserSessionOverviewViewModel.Context var body: some View { diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverviewDisclosureCell.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverviewDisclosureCell.swift index b63640ada..027f5f0bd 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverviewDisclosureCell.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionOverview/View/UserSessionOverviewDisclosureCell.swift @@ -17,7 +17,6 @@ import SwiftUI struct UserSessionOverviewDisclosureCell: View { - @Environment(\.theme) private var theme: ThemeSwiftUI let title: String diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsFlow/Coordinator/UserSessionsFlowCoordinator.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsFlow/Coordinator/UserSessionsFlowCoordinator.swift index db751a80f..a032dcfbd 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsFlow/Coordinator/UserSessionsFlowCoordinator.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsFlow/Coordinator/UserSessionsFlowCoordinator.swift @@ -22,33 +22,24 @@ struct UserSessionsFlowCoordinatorParameters { } final class UserSessionsFlowCoordinator: Coordinator, Presentable { - - // MARK: - Properties - - // MARK: Private - private let parameters: UserSessionsFlowCoordinatorParameters private let navigationRouter: NavigationRouterType - // MARK: Public - // Must be used only internally var childCoordinators: [Coordinator] = [] var completion: (() -> Void)? - // MARK: - Setup - init(parameters: UserSessionsFlowCoordinatorParameters) { self.parameters = parameters - - self.navigationRouter = parameters.router ?? NavigationRouter(navigationController: RiotNavigationController()) + navigationRouter = parameters.router ?? NavigationRouter(navigationController: RiotNavigationController()) } // MARK: - Private private 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) }) @@ -56,7 +47,7 @@ final class UserSessionsFlowCoordinator: Coordinator, Presentable { } private func createUserSessionsOverviewCoordinator() -> UserSessionsOverviewCoordinator { - let parameters = UserSessionsOverviewCoordinatorParameters(session: self.parameters.session) + let parameters = UserSessionsOverviewCoordinatorParameters(session: parameters.session) let coordinator = UserSessionsOverviewCoordinator(parameters: parameters) coordinator.completion = { [weak self] result in @@ -104,15 +95,15 @@ final class UserSessionsFlowCoordinator: Coordinator, Presentable { let rootCoordinator = createUserSessionsOverviewCoordinator() 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) self?.completion?() }) } else { - self.navigationRouter.setRootModule(rootCoordinator) { [weak self] in + navigationRouter.setRootModule(rootCoordinator) { [weak self] in self?.remove(childCoordinator: rootCoordinator) self?.completion?() } @@ -120,6 +111,6 @@ final class UserSessionsFlowCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.navigationRouter.toPresentable() + return navigationRouter.toPresentable() } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsFlow/Coordinator/UserSessionsFlowCoordinatorBridgePresenter.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsFlow/Coordinator/UserSessionsFlowCoordinatorBridgePresenter.swift index d2a1a9ff0..a2b256177 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsFlow/Coordinator/UserSessionsFlowCoordinatorBridgePresenter.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsFlow/Coordinator/UserSessionsFlowCoordinatorBridgePresenter.swift @@ -24,22 +24,11 @@ import UIKit /// Each bridge should be removed once the underlying Coordinator has been integrated by another Coordinator. @objcMembers final class UserSessionsFlowCoordinatorBridgePresenter: NSObject { - - // MARK: - Constants - - // MARK: - Properties - - // MARK: Private - private let mxSession: MXSession private var coordinator: UserSessionsFlowCoordinator? - - // MARK: Public - + var completion: (() -> Void)? - // MARK: - Setup - init(mxSession: MXSession) { self.mxSession = mxSession super.init() @@ -48,26 +37,22 @@ final class UserSessionsFlowCoordinatorBridgePresenter: NSObject { // MARK: - Public func push(from navigationController: UINavigationController, animated: Bool) { - - self.startUserSessionsFlow(mxSession: self.mxSession, navigationController: navigationController) + startUserSessionsFlow(mxSession: mxSession, navigationController: navigationController) } // MARK: - Private private func startUserSessionsFlow(mxSession: MXSession, navigationController: UINavigationController?) { - var navigationRouter: NavigationRouterType? if let navigationController = navigationController { navigationRouter = NavigationRouterStore.shared.navigationRouter(for: navigationController) } - let coordinatorParameters = UserSessionsFlowCoordinatorParameters(session: mxSession, router: navigationRouter) + let parameters = UserSessionsFlowCoordinatorParameters(session: mxSession, router: navigationRouter) + let coordinator = UserSessionsFlowCoordinator(parameters: parameters) - let userSessionsFlowCoordinator = UserSessionsFlowCoordinator(parameters: coordinatorParameters) - - userSessionsFlowCoordinator.completion = { [weak self] in - + coordinator.completion = { [weak self] in guard let self = self else { return } @@ -76,8 +61,8 @@ final class UserSessionsFlowCoordinatorBridgePresenter: NSObject { self.coordinator = nil } - userSessionsFlowCoordinator.start() + coordinator.start() - self.coordinator = userSessionsFlowCoordinator + self.coordinator = coordinator } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Coordinator/UserSessionsOverviewCoordinator.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Coordinator/UserSessionsOverviewCoordinator.swift index b98f18fae..74afa6c23 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Coordinator/UserSessionsOverviewCoordinator.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Coordinator/UserSessionsOverviewCoordinator.swift @@ -22,39 +22,24 @@ struct UserSessionsOverviewCoordinatorParameters { } final class UserSessionsOverviewCoordinator: Coordinator, Presentable { - - // MARK: - Properties - - // MARK: Private - private let parameters: UserSessionsOverviewCoordinatorParameters - private let userSessionsOverviewHostingController: UIViewController - private var userSessionsOverviewViewModel: UserSessionsOverviewViewModelProtocol + private let hostingViewController: UIViewController + private var viewModel: UserSessionsOverviewViewModelProtocol private let service: UserSessionsOverviewService private var indicatorPresenter: UserIndicatorTypePresenterProtocol private var loadingIndicator: UserIndicator? - // MARK: Public - // Must be used only internally var childCoordinators: [Coordinator] = [] var completion: ((UserSessionsOverviewCoordinatorResult) -> Void)? - // MARK: - Setup - init(parameters: UserSessionsOverviewCoordinatorParameters) { self.parameters = parameters - let service = UserSessionsOverviewService(mxSession: parameters.session) - self.service = service - let viewModel = UserSessionsOverviewViewModel(userSessionsOverviewService: service) - let view = UserSessionsOverview(viewModel: viewModel.context) - userSessionsOverviewViewModel = viewModel - - let hostingViewController = VectorHostingController(rootView: view) - - userSessionsOverviewHostingController = hostingViewController + service = UserSessionsOverviewService(mxSession: parameters.session) + viewModel = UserSessionsOverviewViewModel(userSessionsOverviewService: service) + hostingViewController = VectorHostingController(rootView: UserSessionsOverview(viewModel: viewModel.context)) indicatorPresenter = UserIndicatorTypePresenter(presentingViewController: hostingViewController) } @@ -62,9 +47,10 @@ final class UserSessionsOverviewCoordinator: Coordinator, Presentable { func start() { MXLog.debug("[UserSessionsOverviewCoordinator] did start.") - userSessionsOverviewViewModel.completion = { [weak self] result in + viewModel.completion = { [weak self] result in guard let self = self else { return } MXLog.debug("[UserSessionsOverviewCoordinator] UserSessionsOverviewViewModel did complete with result: \(result).") + switch result { case .showAllUnverifiedSessions: self.showAllUnverifiedSessions() @@ -83,7 +69,7 @@ final class UserSessionsOverviewCoordinator: Coordinator, Presentable { } func toPresentable() -> UIViewController { - return self.userSessionsOverviewHostingController + return hostingViewController } // MARK: - Private diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/MatrixSDK/UserSessionsOverviewService.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/MatrixSDK/UserSessionsOverviewService.swift index b9efa16e0..ab242d906 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/MatrixSDK/UserSessionsOverviewService.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/MatrixSDK/UserSessionsOverviewService.swift @@ -18,33 +18,25 @@ import Foundation import MatrixSDK class UserSessionsOverviewService: UserSessionsOverviewServiceProtocol { - - // MARK: - Constants - - // MARK: - Properties - - // MARK: Private - private let mxSession: MXSession - // MARK: Public - private(set) var lastOverviewData: UserSessionsOverviewData - // MARK: - Setup - init(mxSession: MXSession) { self.mxSession = mxSession - self.lastOverviewData = UserSessionsOverviewData(currentSessionInfo: nil, unverifiedSessionsInfo: [], inactiveSessionsInfo: [], otherSessionsInfo: []) + lastOverviewData = UserSessionsOverviewData(currentSessionInfo: nil, + unverifiedSessionsInfo: [], + inactiveSessionsInfo: [], + otherSessionsInfo: []) - self.setupInitialOverviewData() + setupInitialOverviewData() } // MARK: - Public func fetchUserSessionsOverviewData(completion: @escaping (Result) -> Void) { - self.mxSession.matrixRestClient.devices { response in + mxSession.matrixRestClient.devices { response in switch response { case .success(let devices): self.lastOverviewData = self.userSessionsOverviewData(from: devices) @@ -62,21 +54,20 @@ class UserSessionsOverviewService: UserSessionsOverviewServiceProtocol { // MARK: - Private private func setupInitialOverviewData() { - let currentSessionInfo = self.getCurrentUserSessionInfoFromCache() + let currentSessionInfo = getCurrentUserSessionInfoFromCache() - self.lastOverviewData = UserSessionsOverviewData(currentSessionInfo: currentSessionInfo, unverifiedSessionsInfo: [], inactiveSessionsInfo: [], otherSessionsInfo: []) + lastOverviewData = UserSessionsOverviewData(currentSessionInfo: currentSessionInfo, unverifiedSessionsInfo: [], inactiveSessionsInfo: [], otherSessionsInfo: []) } private func getCurrentUserSessionInfoFromCache() -> UserSessionInfo? { guard let mainAccount = MXKAccountManager.shared().activeAccounts.first, let device = mainAccount.device else { return nil } - return self.userSessionInfo(from: device) + return userSessionInfo(from: device) } private func userSessionInfo(from device: MXDevice) -> UserSessionInfo { - - let deviceInfo = self.getDeviceInfo(for: device.deviceId) + let deviceInfo = getDeviceInfo(for: device.deviceId) let isSessionVerified = deviceInfo?.trustLevel.isVerified ?? false @@ -95,20 +86,20 @@ class UserSessionsOverviewService: UserSessionsOverviewServiceProtocol { } private func getDeviceInfo(for deviceId: String) -> MXDeviceInfo? { - guard let userId = self.mxSession.myUserId else { + guard let userId = mxSession.myUserId else { return nil } - return self.mxSession.crypto.device(withDeviceId: deviceId, ofUser: userId) + + return mxSession.crypto.device(withDeviceId: deviceId, ofUser: userId) } private func userSessionsOverviewData(from devices: [MXDevice]) -> UserSessionsOverviewData { - let sortedDevices = devices.sorted { device1, device2 in device1.lastSeenTs > device2.lastSeenTs } let allUserSessionInfo = sortedDevices.map { device in - return self.userSessionInfo(from: device) + return userSessionInfo(from: device) } var currentSessionInfo: UserSessionInfo? @@ -118,7 +109,7 @@ class UserSessionsOverviewService: UserSessionsOverviewServiceProtocol { var otherSessionsInfo: [UserSessionInfo] = [] for userSessionInfo in allUserSessionInfo { - if userSessionInfo.sessionId == self.mxSession.myDeviceId { + if userSessionInfo.sessionId == mxSession.myDeviceId { currentSessionInfo = userSessionInfo } else { otherSessionsInfo.append(userSessionInfo) diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/Mock/MockUserSessionsOverviewService.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/Mock/MockUserSessionsOverviewService.swift index d0621cd9c..34d79fe16 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/Mock/MockUserSessionsOverviewService.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/Mock/MockUserSessionsOverviewService.swift @@ -17,11 +17,10 @@ import Foundation class MockUserSessionsOverviewService: UserSessionsOverviewServiceProtocol { - var lastOverviewData: UserSessionsOverviewData func fetchUserSessionsOverviewData(completion: @escaping (Result) -> Void) { - completion(.success(self.lastOverviewData)) + completion(.success(lastOverviewData)) } func getOtherSession(sessionId: String) -> UserSessionInfo? { @@ -41,6 +40,9 @@ class MockUserSessionsOverviewService: UserSessionsOverviewServiceProtocol { UserSessionInfo(sessionId: "3", sessionName: "Android", deviceType: .mobile, isVerified: false, lastSeenIP: "3.0.0.3", lastSeenTimestamp: (Date().timeIntervalSince1970 - 10)) ] - self.lastOverviewData = UserSessionsOverviewData(currentSessionInfo: currentSessionInfo, unverifiedSessionsInfo: unverifiedSessionsInfo, inactiveSessionsInfo: inactiveSessionsInfo, otherSessionsInfo: otherSessionsInfo) + lastOverviewData = UserSessionsOverviewData(currentSessionInfo: currentSessionInfo, + unverifiedSessionsInfo: unverifiedSessionsInfo, + inactiveSessionsInfo: inactiveSessionsInfo, + otherSessionsInfo: otherSessionsInfo) } } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/UserSessionsOverviewServiceProtocol.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/UserSessionsOverviewServiceProtocol.swift index dec3b06df..07478f201 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/UserSessionsOverviewServiceProtocol.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Service/UserSessionsOverviewServiceProtocol.swift @@ -17,7 +17,6 @@ import Foundation struct UserSessionsOverviewData { - let currentSessionInfo: UserSessionInfo? let unverifiedSessionsInfo: [UserSessionInfo] let inactiveSessionsInfo: [UserSessionInfo] @@ -25,7 +24,6 @@ struct UserSessionsOverviewData { } protocol UserSessionsOverviewServiceProtocol { - var lastOverviewData: UserSessionsOverviewData { get } func fetchUserSessionsOverviewData(completion: @escaping (Result) -> Void) -> Void diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Test/Unit/UserSessionsOverviewViewModelTests.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Test/Unit/UserSessionsOverviewViewModelTests.swift index d45804590..d9c2ecb9c 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Test/Unit/UserSessionsOverviewViewModelTests.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/Test/Unit/UserSessionsOverviewViewModelTests.swift @@ -20,7 +20,6 @@ import Combine @testable import RiotSwiftUI class UserSessionsOverviewViewModelTests: XCTestCase { - var service: MockUserSessionsOverviewService! var viewModel: UserSessionsOverviewViewModelProtocol! var context: UserSessionsOverviewViewModelType.Context! diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewModels.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewModels.swift index dd27e0c63..8e66bd0e2 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewModels.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewModels.swift @@ -36,14 +36,13 @@ enum UserSessionsOverviewViewModelResult { // MARK: View struct UserSessionsOverviewViewState: BindableState { - - var unverifiedSessionsViewData: [UserSessionListItemViewData] - - var inactiveSessionsViewData: [UserSessionListItemViewData] - var currentSessionViewData: UserSessionCardViewData? - var otherSessionsViewData: [UserSessionListItemViewData] + var unverifiedSessionsViewData = [UserSessionListItemViewData]() + + var inactiveSessionsViewData = [UserSessionListItemViewData]() + + var otherSessionsViewData = [UserSessionListItemViewData]() var showLoadingIndicator: Bool = false } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewViewModel.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewViewModel.swift index b3e185d86..3d51884fc 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewViewModel.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewViewModel.swift @@ -21,91 +21,63 @@ typealias UserSessionsOverviewViewModelType = StateStoreViewModel class UserSessionsOverviewViewModel: UserSessionsOverviewViewModelType, UserSessionsOverviewViewModelProtocol { - - // MARK: - Properties - - // MARK: Private - private let userSessionsOverviewService: UserSessionsOverviewServiceProtocol - // MARK: Public - var completion: ((UserSessionsOverviewViewModelResult) -> Void)? - // MARK: - Setup - init(userSessionsOverviewService: UserSessionsOverviewServiceProtocol) { self.userSessionsOverviewService = userSessionsOverviewService - let initialViewState = UserSessionsOverviewViewState(unverifiedSessionsViewData: [], inactiveSessionsViewData: [], currentSessionViewData: nil, otherSessionsViewData: []) + super.init(initialViewState: .init()) - super.init(initialViewState: initialViewState) - - self.updateViewState(with: userSessionsOverviewService.lastOverviewData) + updateViewState(with: userSessionsOverviewService.lastOverviewData) } // MARK: - Public - + override func process(viewAction: UserSessionsOverviewViewAction) { switch viewAction { case .viewAppeared: - self.loadData() + loadData() case .verifyCurrentSession: - self.completion?(.verifyCurrentSession) + completion?(.verifyCurrentSession) case .viewCurrentSessionDetails: guard let currentSessionInfo = userSessionsOverviewService.lastOverviewData.currentSessionInfo else { assertionFailure("currentSessionInfo should be present") - return + return } - self.completion?(.showCurrentSessionOverview(sessionInfo: currentSessionInfo)) + completion?(.showCurrentSessionOverview(sessionInfo: currentSessionInfo)) case .viewAllUnverifiedSessions: - self.completion?(.showAllUnverifiedSessions) + completion?(.showAllUnverifiedSessions) case .viewAllInactiveSessions: - self.completion?(.showAllInactiveSessions) + completion?(.showAllInactiveSessions) case .viewAllOtherSessions: - self.completion?(.showAllOtherSessions) + completion?(.showAllOtherSessions) case .tapUserSession(let sessionId): guard let sessionInfo = userSessionsOverviewService.getOtherSession(sessionId: sessionId) else { assertionFailure("missing session info") return } - self.completion?(.showUserSessionOverview(sessionInfo: sessionInfo)) + completion?(.showUserSessionOverview(sessionInfo: sessionInfo)) } } // MARK: - Private private func updateViewState(with userSessionsViewData: UserSessionsOverviewData) { - - let unverifiedSessionsViewData = self.userSessionListItemViewDataList(from: userSessionsViewData.unverifiedSessionsInfo) - let inactiveSessionsViewData = self.userSessionListItemViewDataList(from: userSessionsViewData.inactiveSessionsInfo) - - var currentSessionViewData: UserSessionCardViewData? - - let otherSessionsViewData = self.userSessionListItemViewDataList(from: userSessionsViewData.otherSessionsInfo) - + state.unverifiedSessionsViewData = userSessionsViewData.unverifiedSessionsInfo.asViewData() + state.inactiveSessionsViewData = userSessionsViewData.inactiveSessionsInfo.asViewData() + state.otherSessionsViewData = userSessionsViewData.otherSessionsInfo.asViewData() if let currentSessionInfo = userSessionsViewData.currentSessionInfo { - currentSessionViewData = UserSessionCardViewData(userSessionInfo: currentSessionInfo, isCurrentSessionDisplayMode: true) - } - - self.state.unverifiedSessionsViewData = unverifiedSessionsViewData - self.state.inactiveSessionsViewData = inactiveSessionsViewData - self.state.currentSessionViewData = currentSessionViewData - self.state.otherSessionsViewData = otherSessionsViewData - } - - private func userSessionListItemViewDataList(from userSessionInfoList: [UserSessionInfo]) -> [UserSessionListItemViewData] { - return userSessionInfoList.map { - return UserSessionListItemViewData(userSessionInfo: $0) + state.currentSessionViewData = UserSessionCardViewData(userSessionInfo: currentSessionInfo, isCurrentSessionDisplayMode: true) } } private func loadData() { + state.showLoadingIndicator = true - self.state.showLoadingIndicator = true - - self.userSessionsOverviewService.fetchUserSessionsOverviewData { [weak self] result in + userSessionsOverviewService.fetchUserSessionsOverviewData { [weak self] result in guard let self = self else { return } @@ -122,3 +94,9 @@ class UserSessionsOverviewViewModel: UserSessionsOverviewViewModelType, UserSess } } } + +private extension Collection where Element == UserSessionInfo { + func asViewData() -> [UserSessionListItemViewData] { + map { UserSessionListItemViewData(userSessionInfo: $0) } + } +} diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewViewModelProtocol.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewViewModelProtocol.swift index f416bb16a..ebbb790a9 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewViewModelProtocol.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/UserSessionsOverviewViewModelProtocol.swift @@ -17,7 +17,6 @@ import Foundation protocol UserSessionsOverviewViewModelProtocol { - var completion: ((UserSessionsOverviewViewModelResult) -> Void)? { get set } var context: UserSessionsOverviewViewModelType.Context { get } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionListItem.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionListItem.swift index 7342764c4..f107c85f0 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionListItem.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionListItem.swift @@ -17,9 +17,6 @@ import SwiftUI struct UserSessionListItem: View { - - // MARK: - Constants - private enum LayoutConstants { static let horizontalPadding: CGFloat = 15 static let verticalPadding: CGFloat = 16 @@ -27,23 +24,16 @@ struct UserSessionListItem: View { static let avatarRightMargin: CGFloat = 18 } - // MARK: - Properties - - // MARK: Private - @Environment(\.theme) private var theme: ThemeSwiftUI - // MARK: Public - let viewData: UserSessionListItemViewData var onBackgroundTap: ((String) -> (Void))? = nil - // MARK: - Body - var body: some View { - Button(action: { onBackgroundTap?(self.viewData.sessionId) - }) { + Button { + onBackgroundTap?(viewData.sessionId) + } label: { VStack(alignment: .leading, spacing: LayoutConstants.verticalPadding) { HStack(spacing: LayoutConstants.avatarRightMargin) { DeviceAvatarView(viewData: viewData.deviceAvatarViewData) @@ -74,7 +64,6 @@ struct UserSessionListItem: View { } struct UserSessionListPreview: View { - let userSessionsOverviewService: UserSessionsOverviewServiceProtocol = MockUserSessionsOverviewService() var body: some View { diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionListItemViewData.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionListItemViewData.swift index 4acac069e..a682cd8e4 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionListItemViewData.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionListItemViewData.swift @@ -18,14 +18,9 @@ import Foundation /// View data for UserSessionListItem struct UserSessionListItemViewData: Identifiable { - - // MARK: - Constants - private static let userSessionNameFormatter = UserSessionNameFormatter() private static let lastActivityDateFormatter = UserSessionLastActivityFormatter() - - // MARK: - Properties - + var id: String { return sessionId } @@ -38,8 +33,6 @@ struct UserSessionListItemViewData: Identifiable { let deviceAvatarViewData: DeviceAvatarViewData - // MARK: - Setup - init(sessionId: String, sessionDisplayName: String?, deviceType: DeviceType, @@ -47,15 +40,14 @@ struct UserSessionListItemViewData: Identifiable { lastActivityDate: TimeInterval?) { self.sessionId = sessionId - self.sessionName = Self.userSessionNameFormatter.sessionName(deviceType: deviceType, sessionDisplayName: sessionDisplayName) - self.sessionDetails = Self.buildSessionDetails(isVerified: isVerified, lastActivityDate: lastActivityDate) - self.deviceAvatarViewData = DeviceAvatarViewData(deviceType: deviceType, isVerified: isVerified) + sessionName = Self.userSessionNameFormatter.sessionName(deviceType: deviceType, sessionDisplayName: sessionDisplayName) + sessionDetails = Self.buildSessionDetails(isVerified: isVerified, lastActivityDate: lastActivityDate) + deviceAvatarViewData = DeviceAvatarViewData(deviceType: deviceType, isVerified: isVerified) } // MARK: - Private private static func buildSessionDetails(isVerified: Bool, lastActivityDate: TimeInterval?) -> String { - let sessionDetailsString: String let sessionStatusText = isVerified ? VectorL10n.userSessionVerifiedShort : VectorL10n.userSessionUnverifiedShort @@ -77,7 +69,6 @@ struct UserSessionListItemViewData: Identifiable { } extension UserSessionListItemViewData { - init(userSessionInfo: UserSessionInfo) { self.init(sessionId: userSessionInfo.sessionId, sessionDisplayName: userSessionInfo.sessionName, deviceType: userSessionInfo.deviceType, isVerified: userSessionInfo.isVerified, lastActivityDate: userSessionInfo.lastSeenTimestamp) } diff --git a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionsOverview.swift b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionsOverview.swift index 27601502f..565718d69 100644 --- a/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionsOverview.swift +++ b/RiotSwiftUI/Modules/UserSessions/UserSessionsOverview/View/UserSessionsOverview.swift @@ -17,11 +17,6 @@ import SwiftUI struct UserSessionsOverview: View { - - // MARK: - Properties - - // MARK: Private - @Environment(\.theme) private var theme: ThemeSwiftUI @ViewBuilder @@ -52,7 +47,6 @@ struct UserSessionsOverview: View { var body: some View { ScrollView { - // Security recommendations section if viewModel.viewState.unverifiedSessionsViewData.isEmpty == false || viewModel.viewState.inactiveSessionsViewData.isEmpty == false { @@ -64,7 +58,7 @@ struct UserSessionsOverview: View { // Other sessions section if viewModel.viewState.otherSessionsViewData.isEmpty == false { - self.otherSessionsSection + otherSessionsSection } } .background(theme.colors.system.ignoresSafeArea()) @@ -77,7 +71,6 @@ struct UserSessionsOverview: View { } private var otherSessionsSection: some View { - SwiftUI.Section { // Device list LazyVStack(spacing: 0) {