mirror of
https://github.com/vector-im/element-ios.git
synced 2024-09-29 07:42:40 +00:00
Merge pull request #6609 from vector-im/steve/6585_session_mgmt_empty_screen
Device manager: Add new session management empty screen (PSG-675)
This commit is contained in:
commit
69e70fb670
18 changed files with 642 additions and 0 deletions
|
@ -420,4 +420,8 @@ final class BuildSettings: NSObject {
|
|||
|
||||
// MARK: - New App Layout
|
||||
static let newAppLayoutEnabled = false
|
||||
|
||||
// MARK: - Device manager
|
||||
|
||||
static let deviceManagerEnabled = false
|
||||
}
|
||||
|
|
|
@ -894,6 +894,9 @@ Tap the + to start adding people.";
|
|||
"manage_session_not_trusted" = "Not trusted";
|
||||
"manage_session_sign_out" = "Sign out of this session";
|
||||
|
||||
// User sessions management
|
||||
"user_sessions_settings" = "Manage sessions";
|
||||
|
||||
// AuthenticatedSessionViewControllerFactory
|
||||
"authenticated_session_flow_not_supported" = "This app does not support the authentication mechanism on your homeserver.";
|
||||
|
||||
|
@ -2332,6 +2335,10 @@ To enable access, tap Settings> Location and select Always";
|
|||
"location_sharing_live_lab_promotion_text" = "Please note: this is a labs feature using a temporary implementation that allows the history of your shared location to be permanently visible to other people in the room.";
|
||||
"location_sharing_live_lab_promotion_activation" = "Enable live location sharing";
|
||||
|
||||
// MARK: User sessions management
|
||||
|
||||
"user_sessions_overview_title" = "Sessions";
|
||||
|
||||
// MARK: - MatrixKit
|
||||
|
||||
|
||||
|
|
|
@ -8391,6 +8391,14 @@ public class VectorL10n: NSObject {
|
|||
public static var userIdTitle: String {
|
||||
return VectorL10n.tr("Vector", "user_id_title")
|
||||
}
|
||||
/// Sessions
|
||||
public static var userSessionsOverviewTitle: String {
|
||||
return VectorL10n.tr("Vector", "user_sessions_overview_title")
|
||||
}
|
||||
/// Manage sessions
|
||||
public static var userSessionsSettings: String {
|
||||
return VectorL10n.tr("Vector", "user_sessions_settings")
|
||||
}
|
||||
/// If you didn’t sign in to this session, your account may be compromised.
|
||||
public static var userVerificationSessionDetailsAdditionalInformationUntrustedCurrentUser: String {
|
||||
return VectorL10n.tr("Vector", "user_verification_session_details_additional_information_untrusted_current_user")
|
||||
|
|
|
@ -178,6 +178,7 @@ typedef NS_ENUM(NSUInteger, LABS_ENABLE)
|
|||
typedef NS_ENUM(NSUInteger, SECURITY)
|
||||
{
|
||||
SECURITY_BUTTON_INDEX = 0,
|
||||
DEVICE_MANAGER_INDEX
|
||||
};
|
||||
|
||||
typedef void (^blockSettingsViewController_onReadyToDestroy)(void);
|
||||
|
@ -284,6 +285,7 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
|
|||
|
||||
@property (nonatomic, strong) ThreadsBetaCoordinatorBridgePresenter *threadsBetaBridgePresenter;
|
||||
@property (nonatomic, strong) ChangePasswordCoordinatorBridgePresenter *changePasswordBridgePresenter;
|
||||
@property (nonatomic, strong) UserSessionsFlowCoordinatorBridgePresenter *userSessionsFlowCoordinatorBridgePresenter;
|
||||
|
||||
/**
|
||||
Whether or not to check for contacts access after the user accepts the service terms. The value of this property is
|
||||
|
@ -400,6 +402,13 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
|
|||
|
||||
Section *sectionSecurity = [Section sectionWithTag:SECTION_TAG_SECURITY];
|
||||
[sectionSecurity addRowWithTag:SECURITY_BUTTON_INDEX];
|
||||
|
||||
if (BuildSettings.deviceManagerEnabled)
|
||||
{
|
||||
// NOTE: Add device manager entry point in the security section atm for debug purpose
|
||||
[sectionSecurity addRowWithTag:DEVICE_MANAGER_INDEX];
|
||||
}
|
||||
|
||||
sectionSecurity.headerTitle = [VectorL10n settingsSecurity];
|
||||
[tmpSections addObject:sectionSecurity];
|
||||
|
||||
|
@ -2533,6 +2542,11 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
|
|||
cell.textLabel.text = [VectorL10n securitySettingsTitle];
|
||||
[cell vc_setAccessoryDisclosureIndicatorWithCurrentTheme];
|
||||
break;
|
||||
case DEVICE_MANAGER_INDEX:
|
||||
cell = [self getDefaultTableViewCell:tableView];
|
||||
cell.textLabel.text = [VectorL10n userSessionsSettings];
|
||||
[cell vc_setAccessoryDisclosureIndicatorWithCurrentTheme];
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (section == SECTION_TAG_DEACTIVATE_ACCOUNT)
|
||||
|
@ -2885,6 +2899,11 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
|
|||
[self pushViewController:securityViewController];
|
||||
break;
|
||||
}
|
||||
case DEVICE_MANAGER_INDEX:
|
||||
{
|
||||
[self showUserSessionsFlow];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (section == SECTION_TAG_NOTIFICATIONS)
|
||||
|
@ -4523,4 +4542,35 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
|
|||
self.changePasswordBridgePresenter = nil;
|
||||
}
|
||||
|
||||
#pragma mark - User sessions management
|
||||
|
||||
- (void)showUserSessionsFlow
|
||||
{
|
||||
if (!self.mainSession)
|
||||
{
|
||||
MXLogError(@"[SettingsViewController] Cannot show user sessions flow, no user session available");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self.navigationController)
|
||||
{
|
||||
MXLogError(@"[SettingsViewController] Cannot show user sessions flow, no navigation controller available");
|
||||
return;
|
||||
}
|
||||
|
||||
UserSessionsFlowCoordinatorBridgePresenter *userSessionsFlowCoordinatorBridgePresenter = [[UserSessionsFlowCoordinatorBridgePresenter alloc] initWithMxSession:self.mainSession];
|
||||
|
||||
MXWeakify(self);
|
||||
|
||||
userSessionsFlowCoordinatorBridgePresenter.completion = ^{
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
self.userSessionsFlowCoordinatorBridgePresenter = nil;
|
||||
};
|
||||
|
||||
self.userSessionsFlowCoordinatorBridgePresenter = userSessionsFlowCoordinatorBridgePresenter;
|
||||
|
||||
[self.userSessionsFlowCoordinatorBridgePresenter pushFrom:self.navigationController animated:YES];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
//
|
||||
// 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 CommonKit
|
||||
|
||||
struct UserSessionsFlowCoordinatorParameters {
|
||||
let session: MXSession
|
||||
let router: NavigationRouterType?
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func start() {
|
||||
MXLog.debug("[UserSessionsFlowCoordinator] did start.")
|
||||
|
||||
let rootCoordinatorParameters = UserSessionsOverviewCoordinatorParameters(session: self.parameters.session)
|
||||
|
||||
let rootCoordinator = UserSessionsOverviewCoordinator(parameters: rootCoordinatorParameters)
|
||||
|
||||
rootCoordinator.start()
|
||||
|
||||
self.add(childCoordinator: rootCoordinator)
|
||||
|
||||
if self.navigationRouter.modules.isEmpty == false {
|
||||
self.navigationRouter.push(rootCoordinator, animated: true, popCompletion: { [weak self] in
|
||||
self?.remove(childCoordinator: rootCoordinator)
|
||||
self?.completion?()
|
||||
})
|
||||
} else {
|
||||
self.navigationRouter.setRootModule(rootCoordinator) { [weak self] in
|
||||
self?.remove(childCoordinator: rootCoordinator)
|
||||
self?.completion?()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func toPresentable() -> UIViewController {
|
||||
return self.navigationRouter.toPresentable()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
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 MatrixSDK
|
||||
import UIKit
|
||||
|
||||
/// UserSessionsFlowCoordinatorBridgePresenter enables to start UserSessionsFlowCoordinator from a view controller.
|
||||
/// This bridge is used while waiting for global usage of coordinator pattern.
|
||||
/// **WARNING**: This class breaks the Coordinator abstraction and it has been introduced for **Objective-C compatibility only** (mainly for integration in legacy view controllers).
|
||||
/// 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()
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func push(from navigationController: UINavigationController, animated: Bool) {
|
||||
|
||||
self.startUserSessionsFlow(mxSession: self.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 userSessionsFlowCoordinator = UserSessionsFlowCoordinator(parameters: coordinatorParameters)
|
||||
|
||||
userSessionsFlowCoordinator.completion = { [weak self] in
|
||||
|
||||
guard let self = self else {
|
||||
return
|
||||
}
|
||||
|
||||
self.completion?()
|
||||
self.coordinator = nil
|
||||
}
|
||||
|
||||
userSessionsFlowCoordinator.start()
|
||||
|
||||
self.coordinator = userSessionsFlowCoordinator
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
//
|
||||
// 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 SwiftUI
|
||||
import CommonKit
|
||||
|
||||
struct UserSessionsOverviewCoordinatorParameters {
|
||||
let session: MXSession
|
||||
}
|
||||
|
||||
final class UserSessionsOverviewCoordinator: Coordinator, Presentable {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let parameters: UserSessionsOverviewCoordinatorParameters
|
||||
private let userSessionsOverviewHostingController: UIViewController
|
||||
private var userSessionsOverviewViewModel: UserSessionsOverviewViewModelProtocol
|
||||
|
||||
// MARK: Public
|
||||
|
||||
// Must be used only internally
|
||||
var childCoordinators: [Coordinator] = []
|
||||
var completion: (() -> Void)?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(parameters: UserSessionsOverviewCoordinatorParameters) {
|
||||
self.parameters = parameters
|
||||
let viewModel = UserSessionsOverviewViewModel(userSessionsOverviewService: UserSessionsOverviewService())
|
||||
let view = UserSessionsOverview(viewModel: viewModel.context)
|
||||
userSessionsOverviewViewModel = viewModel
|
||||
userSessionsOverviewHostingController = VectorHostingController(rootView: view)
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func start() {
|
||||
MXLog.debug("[UserSessionsOverviewCoordinator] did start.")
|
||||
userSessionsOverviewViewModel.completion = { [weak self] result in
|
||||
guard let self = self else { return }
|
||||
MXLog.debug("[UserSessionsOverviewCoordinator] UserSessionsOverviewViewModel did complete with result: \(result).")
|
||||
switch result {
|
||||
case .done:
|
||||
self.completion?()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func toPresentable() -> UIViewController {
|
||||
return self.userSessionsOverviewHostingController
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// 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
|
||||
|
||||
/// Using an enum for the screen allows you define the different state cases with
|
||||
/// the relevant associated data for each case.
|
||||
enum MockUserSessionsOverviewScreenState: MockScreenState, CaseIterable {
|
||||
// A case for each state you want to represent
|
||||
// with specific, minimal associated data that will allow you
|
||||
// mock that screen.
|
||||
case verifiedSession
|
||||
|
||||
/// The associated screen
|
||||
var screenType: Any.Type {
|
||||
UserSessionsOverview.self
|
||||
}
|
||||
|
||||
/// A list of screen state definitions
|
||||
static var allCases: [MockUserSessionsOverviewScreenState] {
|
||||
// Each of the presence statuses
|
||||
return [.verifiedSession]
|
||||
}
|
||||
|
||||
/// Generate the view struct for the screen state.
|
||||
var screenView: ([Any], AnyView) {
|
||||
let service: MockUserSessionsOverviewService = MockUserSessionsOverviewService()
|
||||
switch self {
|
||||
case .verifiedSession:
|
||||
break
|
||||
}
|
||||
|
||||
let viewModel = UserSessionsOverviewViewModel(userSessionsOverviewService: service)
|
||||
|
||||
// can simulate service and viewModel actions here if needs be.
|
||||
|
||||
return (
|
||||
[service, viewModel],
|
||||
AnyView(UserSessionsOverview(viewModel: viewModel.context)
|
||||
.addDependency(MockAvatarService.example))
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// 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
|
||||
|
||||
class UserSessionsOverviewService: UserSessionsOverviewServiceProtocol {
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// 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
|
||||
|
||||
class MockUserSessionsOverviewService: UserSessionsOverviewServiceProtocol {
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// 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
|
||||
|
||||
protocol UserSessionsOverviewServiceProtocol {
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// 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 XCTest
|
||||
import RiotSwiftUI
|
||||
|
||||
class UserSessionsOverviewUITests: MockScreenTestCase {
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// 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 XCTest
|
||||
import Combine
|
||||
|
||||
@testable import RiotSwiftUI
|
||||
|
||||
class UserSessionsOverviewViewModelTests: XCTestCase {
|
||||
|
||||
var service: MockUserSessionsOverviewService!
|
||||
var viewModel: UserSessionsOverviewViewModelProtocol!
|
||||
var context: UserSessionsOverviewViewModelType.Context!
|
||||
|
||||
override func setUpWithError() throws {
|
||||
service = MockUserSessionsOverviewService()
|
||||
viewModel = UserSessionsOverviewViewModel(userSessionsOverviewService: service)
|
||||
context = viewModel.context
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// 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
|
||||
|
||||
// MARK: - Coordinator
|
||||
|
||||
// MARK: View model
|
||||
|
||||
enum UserSessionsOverviewViewModelResult {
|
||||
case done
|
||||
}
|
||||
|
||||
// MARK: View
|
||||
|
||||
struct UserSessionsOverviewViewState: BindableState {
|
||||
}
|
||||
|
||||
enum UserSessionsOverviewViewAction {
|
||||
case verifyCurrentSession
|
||||
case viewCurrentSessionDetails
|
||||
case viewAllUnverifiedSessions
|
||||
case viewAllInactiveSessions
|
||||
case viewAllOtherSessions
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
//
|
||||
// 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 SwiftUI
|
||||
|
||||
typealias UserSessionsOverviewViewModelType = StateStoreViewModel<UserSessionsOverviewViewState,
|
||||
Never,
|
||||
UserSessionsOverviewViewAction>
|
||||
|
||||
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 viewState = UserSessionsOverviewViewState()
|
||||
|
||||
super.init(initialViewState: viewState)
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
override func process(viewAction: UserSessionsOverviewViewAction) {
|
||||
switch viewAction {
|
||||
case .verifyCurrentSession:
|
||||
break
|
||||
case .viewCurrentSessionDetails:
|
||||
break
|
||||
case .viewAllUnverifiedSessions:
|
||||
break
|
||||
case .viewAllInactiveSessions:
|
||||
break
|
||||
case .viewAllOtherSessions:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
//
|
||||
// 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
|
||||
|
||||
protocol UserSessionsOverviewViewModelProtocol {
|
||||
|
||||
var completion: ((UserSessionsOverviewViewModelResult) -> Void)? { get set }
|
||||
|
||||
var context: UserSessionsOverviewViewModelType.Context { get }
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
//
|
||||
// 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 SwiftUI
|
||||
|
||||
struct UserSessionsOverview: View {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
@Environment(\.theme) private var theme: ThemeSwiftUI
|
||||
|
||||
// MARK: Public
|
||||
|
||||
@ObservedObject var viewModel: UserSessionsOverviewViewModel.Context
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
}
|
||||
.background(theme.colors.background)
|
||||
.frame(maxHeight: .infinity)
|
||||
.navigationTitle(VectorL10n.userSessionsOverviewTitle)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Previews
|
||||
|
||||
struct UserSessionsOverview_Previews: PreviewProvider {
|
||||
static let stateRenderer = MockUserSessionsOverviewScreenState.stateRenderer
|
||||
static var previews: some View {
|
||||
stateRenderer.screenGroup()
|
||||
}
|
||||
}
|
1
changelog.d/6585.wip
Normal file
1
changelog.d/6585.wip
Normal file
|
@ -0,0 +1 @@
|
|||
Device manager: Add new session management screen.
|
Loading…
Reference in a new issue