Files
bundesmessenger-ios/Riot/Modules/Settings/Security/SecureBackup/SettingsSecureBackupTableViewSection.swift
T
JanNiklas Grabowski b298dedc22 chore: update from foss 1.11.19 (MESSENGER-6656)
Merge commit 'f823ab9aae70e8d15ed7cc079210dd9bbbb6c8e1' into feature/foss_update_1_11_19

* commit 'f823ab9aae70e8d15ed7cc079210dd9bbbb6c8e1':
  finish version++
  version++
  comments
  update submodule
  remove obsolete tests
  removed unused code
  update submodule
  fix
  Libolm removal
  update license macro
  update license
  Prepare for new sprint

# Conflicts:
#	Config/AppVersion.xcconfig
#	IDETemplateMacros.plist
#	LICENSE
#	README.md
#	Riot/Categories/MXSession+Riot.m
#	Riot/Managers/EncryptionKeyManager/EncryptionKeyManager.swift
#	Riot/Managers/KeyValueStorage/Extensions/Keychain.swift
#	Riot/Managers/KeyValueStorage/KeyValueStore.swift
#	Riot/Managers/KeyValueStorage/KeychainStore.swift
#	Riot/Managers/KeyValueStorage/MemoryStore.swift
#	Riot/Managers/PushNotification/PushNotificationService.m
#	Riot/Managers/Settings/RiotSettings.swift
#	Riot/Managers/Settings/Shared/RiotSharedSettings.swift
#	Riot/Modules/Analytics/AnalyticsUIElement.swift
#	Riot/Modules/Application/AppCoordinator.swift
#	Riot/Modules/Application/LegacyAppDelegate.h
#	Riot/Modules/Application/LegacyAppDelegate.m
#	Riot/Modules/Authentication/Legacy/AuthenticationViewController.h
#	Riot/Modules/Authentication/Legacy/AuthenticationViewController.m
#	Riot/Modules/Authentication/Legacy/Views/AuthInputsView.h
#	Riot/Modules/Authentication/Legacy/Views/AuthInputsView.m
#	Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m
#	Riot/Modules/Common/Recents/RecentsViewController.m
#	Riot/Modules/Common/WebViewController/WebViewViewController.m
#	Riot/Modules/Contacts/Details/ContactDetailsViewController.m
#	Riot/Modules/Contacts/Views/ContactTableViewCell.m
#	Riot/Modules/Favorites/FavouritesViewController.h
#	Riot/Modules/Favorites/FavouritesViewController.m
#	Riot/Modules/GlobalSearch/UnifiedSearchViewController.m
#	Riot/Modules/People/PeopleViewController.h
#	Riot/Modules/People/PeopleViewController.m
#	Riot/Modules/Room/ContextualMenu/ReactionsMenu/ReactionsMenuViewModel.swift
#	Riot/Modules/Room/DataSources/RoomDataSource.m
#	Riot/Modules/Room/Files/RoomFilesViewController.m
#	Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m
#	Riot/Modules/Room/Members/RoomParticipantsViewController.m
#	Riot/Modules/Room/RoomViewController.m
#	Riot/Modules/Room/Settings/RoomSettingsViewController.m
#	Riot/Modules/Room/TimelineCells/RoomCreationIntro/RoomCreationIntroCell.swift
#	Riot/Modules/Room/TimelineCells/RoomCreationIntro/RoomCreationIntroCellContentView.swift
#	Riot/Modules/Room/TimelineCells/RoomCreationIntro/RoomCreationIntroViewData.swift
#	Riot/Modules/Room/TimelineCells/RoomTimelineCellIdentifier.h
#	Riot/Modules/Rooms/RoomsViewController.h
#	Riot/Modules/Rooms/ShowDirectory/Cells/Network/DirectoryNetworkTableHeaderFooterView.swift
#	Riot/Modules/Rooms/ShowDirectory/Cells/Room/DirectoryRoomTableViewCell.swift
#	Riot/Modules/Rooms/ShowDirectory/PublicRoomsDirectoryViewModel.swift
#	Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyCoordinator.swift
#	Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyViewController.swift
#	Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseCoordinator.swift
#	Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseViewController.swift
#	Riot/Modules/Secrets/Recover/SecretsRecoveryCoordinator.swift
#	Riot/Modules/SecureBackup/Setup/Intro/SecureBackupSetupIntroViewController.swift
#	Riot/Modules/SecureBackup/Setup/Intro/SecureBackupSetupIntroViewModel.swift
#	Riot/Modules/SecureBackup/Setup/Intro/SecureBackupSetupIntroViewModelType.swift
#	Riot/Modules/SetPinCode/PinCodePreferences.swift
#	Riot/Modules/SetPinCode/SetupBiometrics/BiometricsAuthenticationPresenter.swift
#	Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.m
#	Riot/Modules/Settings/Security/SecurityViewController.m
#	Riot/Modules/Settings/SettingsViewController.m
#	Riot/Modules/SplitView/SplitViewCoordinator.swift
#	Riot/Modules/SplitView/SplitViewCoordinatorType.swift
#	Riot/Modules/StartChat/StartChatViewController.m
#	Riot/Modules/TabBar/MasterTabBarController.h
#	Riot/Modules/TabBar/MasterTabBarController.m
#	Riot/Utils/EventFormatter.m
#	Riot/Utils/HTMLFormatter.swift
#	Riot/Utils/Tools.m
#	RiotNSE/NotificationService.swift
2024-10-18 15:45:54 +02:00

337 lines
14 KiB
Swift

/*
Copyright 2021-2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
*/
import UIKit
@objc protocol SettingsSecureBackupTableViewSectionDelegate: AnyObject {
// Table view rendering
func settingsSecureBackupTableViewSectionDidUpdate(_ settingsSecureBackupTableViewSection: SettingsSecureBackupTableViewSection)
func settingsSecureBackupTableViewSection(_ settingsSecureBackupTableViewSection: SettingsSecureBackupTableViewSection, textCellForRow: Int) -> MXKTableViewCellWithTextView
func settingsSecureBackupTableViewSection(_ settingsSecureBackupTableViewSection: SettingsSecureBackupTableViewSection, buttonCellForRow: Int) -> MXKTableViewCellWithButton
// Secure backup
func settingsSecureBackupTableViewSectionShowSecureBackupReset(_ settingsSecureBackupTableViewSection: SettingsSecureBackupTableViewSection)
// Key backup
func settingsSecureBackupTableViewSectionShowKeyBackupCreate(_ settingsSecureBackupTableViewSection: SettingsSecureBackupTableViewSection)
func settingsSecureBackupTableViewSection(_ settingsSecureBackupTableViewSection: SettingsSecureBackupTableViewSection, showKeyBackupRecover keyBackupVersion: MXKeyBackupVersion)
func settingsSecureBackupTableViewSection(_ settingsSecureBackupTableViewSection: SettingsSecureBackupTableViewSection, showKeyBackupDeleteConfirm keyBackupVersion: MXKeyBackupVersion)
// Life cycle
func settingsSecureBackupTableViewSection(_ settingsSecureBackupTableViewSection: SettingsSecureBackupTableViewSection, showActivityIndicator show: Bool)
func settingsSecureBackupTableViewSection(_ settingsSecureBackupTableViewSection: SettingsSecureBackupTableViewSection, showError error: Error)
}
private enum BackupRows {
case info(text: String)
case createSecureBackupAction
case resetSecureBackupAction
case createKeyBackupAction
case restoreFromKeyBackupAction(keyBackupVersion: MXKeyBackupVersion, title: String)
case deleteKeyBackupAction(keyBackupVersion: MXKeyBackupVersion)
}
/// SettingsSecureBackupTableViewSection provides UITableViewCells to manage secure backup and key backup.
///
/// All states are described in SettingsSecureBackupViewState.
/// All actions in SettingsSecureBackupViewAction.
@objc final class SettingsSecureBackupTableViewSection: NSObject {
// MARK: - Properties
@objc weak var delegate: SettingsSecureBackupTableViewSectionDelegate?
// MARK: Private
// This view class holds the model because the model is in pure Swift
// whereas this class can be used from objC
private var viewModel: SettingsSecureBackupViewModelType!
// Need to know the state to make `cellForRow` deliver cells accordingly
private var viewState: SettingsSecureBackupViewState = .loading {
didSet {
self.updateBackupRows()
}
}
private var userDevice: MXDeviceInfo
private var backupRows: [BackupRows] = []
// MARK: - Public
@objc init(withRecoveryService recoveryService: MXRecoveryService, keyBackup: MXKeyBackup, userDevice: MXDeviceInfo) {
self.viewModel = SettingsSecureBackupViewModel(recoveryService: recoveryService, keyBackup: keyBackup)
self.userDevice = userDevice
super.init()
self.viewModel.viewDelegate = self
self.viewModel.process(viewAction: .load)
}
@objc func numberOfRows() -> Int {
return self.backupRows.count
}
@objc func cellForRow(atRow row: Int) -> UITableViewCell {
let backupRow = self.backupRows[row]
var cell: UITableViewCell
switch backupRow {
case .info(let text):
cell = self.textCell(atRow: row, text: text)
case .createSecureBackupAction:
cell = self.buttonCellForCreateSecureBackup(atRow: row)
case .resetSecureBackupAction:
cell = self.buttonCellForResetSecureBackup(atRow: row)
case .createKeyBackupAction:
cell = self.buttonCellForCreateKeyBackup(atRow: row)
case .restoreFromKeyBackupAction(keyBackupVersion: let keyBackupVersion, let title):
cell = self.buttonCellForRestoreFromKeyBackup(keyBackupVersion: keyBackupVersion, title: title, atRow: row)
case .deleteKeyBackupAction(keyBackupVersion: let keyBackupVersion):
cell = self.buttonCellForDeleteKeyBackup(keyBackupVersion: keyBackupVersion, atRow: row)
}
return cell
}
@objc func reload() {
self.viewModel.process(viewAction: .load)
}
@objc func deleteKeyBackup(keyBackupVersion: MXKeyBackupVersion) {
self.viewModel.process(viewAction: .deleteKeyBackup(keyBackupVersion))
}
// MARK: - Data Computing
private func updateBackupRows() {
let backupRows: [BackupRows]
// bwi 5184: remove:
// .deleteKeyBackupAction(keyBackupVersion: keyBackupVersion),
// .resetSecureBackupAction
// to avoid many confusing if clauses
// same reasoning for text changes
switch self.viewState {
case .loading:
backupRows = [
.info(text: VectorL10n.securitySettingsSecureBackupInfoChecking)
]
case .noSecureBackup(let keyBackupState):
switch keyBackupState {
case .noKeyBackup:
let noBackup = VectorL10n.settingsKeyBackupInfoNone
let signoutWarning = VectorL10n.settingsKeyBackupInfoSignoutWarning
let infoText = [noBackup, signoutWarning].joined(separator: "\n")
backupRows = [
.info(text: infoText),
.createSecureBackupAction
]
case .keyBackup(let keyBackupVersion, _, let progress):
if let progress = progress {
backupRows = [
.info(text: importProgressText(for: progress))
]
} else {
backupRows = [
.info(text: BWIL10n.securitySettingsSecureBackupInfoValid),
.restoreFromKeyBackupAction(keyBackupVersion: keyBackupVersion, title: VectorL10n.securitySettingsSecureBackupRestore)
]
}
case .keyBackupNotTrusted(let keyBackupVersion, _):
backupRows = [
.info(text: BWIL10n.securitySettingsSecureBackupInfoValid),
.restoreFromKeyBackupAction(keyBackupVersion: keyBackupVersion, title: VectorL10n.securitySettingsSecureBackupRestore)
]
}
case .secureBackup(let keyBackupState):
switch keyBackupState {
case .noKeyBackup:
let noBackup = VectorL10n.settingsKeyBackupInfoNone
let signoutWarning = VectorL10n.settingsKeyBackupInfoSignoutWarning
let infoText = [noBackup, signoutWarning].joined(separator: "\n")
backupRows = [
.info(text: infoText),
.createKeyBackupAction
]
case .keyBackup(let keyBackupVersion, _, let progress):
if let progress = progress {
backupRows = [
.info(text: importProgressText(for: progress))
]
} else {
backupRows = [
.info(text: BWIL10n.securitySettingsSecureBackupInfoValid),
.restoreFromKeyBackupAction(keyBackupVersion: keyBackupVersion, title: VectorL10n.securitySettingsSecureBackupRestore)
]
}
case .keyBackupNotTrusted(let keyBackupVersion, _):
backupRows = [
.info(text: BWIL10n.securitySettingsSecureBackupInfoValid),
.restoreFromKeyBackupAction(keyBackupVersion: keyBackupVersion, title: VectorL10n.securitySettingsSecureBackupRestore)
]
}
}
self.backupRows = backupRows
}
private func importProgressText(for progress: Progress) -> String {
let percentage = Int(round(progress.fractionCompleted * 100))
return VectorL10n.keyBackupRecoverFromPrivateKeyInfo + " \(percentage)%"
}
// MARK: - Cells -
private func textCell(atRow row: Int, text: String) -> UITableViewCell {
guard let delegate = self.delegate else {
return UITableViewCell()
}
let cell = delegate.settingsSecureBackupTableViewSection(self, textCellForRow: row)
cell.mxkTextView.text = text
return cell
}
// MARK: - Button cells
private func buttonCellForCreateSecureBackup(atRow row: Int) -> UITableViewCell {
guard let delegate = self.delegate else {
return UITableViewCell()
}
let cell: MXKTableViewCellWithButton = delegate.settingsSecureBackupTableViewSection(self, buttonCellForRow: row)
let btnTitle = VectorL10n.securitySettingsSecureBackupSetup
cell.mxkButton.setTitle(btnTitle, for: .normal)
cell.mxkButton.setTitle(btnTitle, for: .highlighted)
cell.mxkButton.vc_addAction {
self.viewModel.process(viewAction: .createSecureBackup)
}
return cell
}
private func buttonCellForResetSecureBackup(atRow row: Int) -> UITableViewCell {
guard let delegate = self.delegate else {
return UITableViewCell()
}
let cell: MXKTableViewCellWithButton = delegate.settingsSecureBackupTableViewSection(self, buttonCellForRow: row)
let btnTitle = VectorL10n.securitySettingsSecureBackupReset
cell.mxkButton.setTitle(btnTitle, for: .normal)
cell.mxkButton.setTitle(btnTitle, for: .highlighted)
cell.mxkButton.tintColor = ThemeService.shared().theme.warningColor
cell.mxkButton.vc_addAction {
self.viewModel.process(viewAction: .resetSecureBackup)
}
return cell
}
private func buttonCellForCreateKeyBackup(atRow row: Int) -> UITableViewCell {
guard let delegate = self.delegate else {
return UITableViewCell()
}
let cell: MXKTableViewCellWithButton = delegate.settingsSecureBackupTableViewSection(self, buttonCellForRow: row)
let btnTitle = VectorL10n.securitySettingsSecureBackupSetup
cell.mxkButton.setTitle(btnTitle, for: .normal)
cell.mxkButton.setTitle(btnTitle, for: .highlighted)
cell.mxkButton.vc_addAction {
self.viewModel.process(viewAction: .createKeyBackup)
}
return cell
}
private func buttonCellForRestoreFromKeyBackup(keyBackupVersion: MXKeyBackupVersion, title: String, atRow row: Int) -> UITableViewCell {
guard let delegate = self.delegate else {
return UITableViewCell()
}
let cell: MXKTableViewCellWithButton = delegate.settingsSecureBackupTableViewSection(self, buttonCellForRow: row)
cell.mxkButton.setTitle(title, for: .normal)
cell.mxkButton.setTitle(title, for: .highlighted)
cell.mxkButton.vc_addAction {
self.viewModel.process(viewAction: .restoreFromKeyBackup(keyBackupVersion))
}
return cell
}
private func buttonCellForDeleteKeyBackup(keyBackupVersion: MXKeyBackupVersion, atRow row: Int) -> UITableViewCell {
guard let delegate = self.delegate else {
return UITableViewCell()
}
let cell: MXKTableViewCellWithButton = delegate.settingsSecureBackupTableViewSection(self, buttonCellForRow: row)
let btnTitle = BWIL10n.securitySettingsSecureBackupDelete
cell.mxkButton.setTitle(btnTitle, for: .normal)
cell.mxkButton.setTitle(btnTitle, for: .highlighted)
cell.mxkButton.tintColor = ThemeService.shared().theme.warningColor
cell.mxkButton.vc_addAction {
self.viewModel.process(viewAction: .confirmDeleteKeyBackup(keyBackupVersion))
}
return cell
}
}
// MARK: - KeyBackupSetupRecoveryKeyViewModelViewDelegate
extension SettingsSecureBackupTableViewSection: SettingsSecureBackupViewModelViewDelegate {
func settingsSecureBackupViewModel(_ viewModel: SettingsSecureBackupViewModelType, didUpdateViewState viewState: SettingsSecureBackupViewState) {
self.viewState = viewState
// The tableview datasource will call `self.cellForRow()`
self.delegate?.settingsSecureBackupTableViewSectionDidUpdate(self)
}
func settingsSecureBackupViewModel(_ viewModel: SettingsSecureBackupViewModelType, didUpdateNetworkRequestViewState networkRequestViewSate: SettingsSecureBackupNetworkRequestViewState) {
switch networkRequestViewSate {
case .loading:
self.delegate?.settingsSecureBackupTableViewSection(self, showActivityIndicator: true)
case .loaded:
self.delegate?.settingsSecureBackupTableViewSection(self, showActivityIndicator: false)
case .error(let error):
self.delegate?.settingsSecureBackupTableViewSection(self, showError: error)
}
}
func settingsSecureBackupViewModelShowSecureBackupReset(_ viewModel: SettingsSecureBackupViewModelType) {
self.delegate?.settingsSecureBackupTableViewSectionShowSecureBackupReset(self)
}
func settingsSecureBackupViewModelShowKeyBackupCreate(_ viewModel: SettingsSecureBackupViewModelType) {
self.delegate?.settingsSecureBackupTableViewSectionShowKeyBackupCreate(self)
}
func settingsSecureBackupViewModel(_ viewModel: SettingsSecureBackupViewModelType, showKeyBackupRecover keyBackupVersion: MXKeyBackupVersion) {
self.delegate?.settingsSecureBackupTableViewSection(self, showKeyBackupRecover: keyBackupVersion)
}
func settingsSecureBackupViewModel(_ viewModel: SettingsSecureBackupViewModelType, showKeyBackupDeleteConfirm keyBackupVersion: MXKeyBackupVersion) {
self.delegate?.settingsSecureBackupTableViewSection(self, showKeyBackupDeleteConfirm: keyBackupVersion)
}
}