Merge branch 'develop' into riot_3296
|
@ -8,6 +8,8 @@ Improvements:
|
|||
* Timeline: Hide encrypted history (pre-invite) (#3239).
|
||||
* Complete security: Add recovery from 4S (#3304).
|
||||
* Key backup: Connect/restore backup created with SSSS (#3124).
|
||||
* E2E by default: Disable it if the HS admin disabled it (#3305).
|
||||
* Key backup: Add secure backup creation flow (#3344).
|
||||
|
||||
Bug fix:
|
||||
* CallVC: Declined calls now properly reset call view controller, thanks to @Legi429 (#2877).
|
||||
|
|
|
@ -249,6 +249,15 @@
|
|||
B157FAA523264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B157FA9D23264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsViewModel.swift */; };
|
||||
B157FAA623264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B157FA9E23264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsViewController.swift */; };
|
||||
B157FAA823264BED00EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinatorBridgePresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B157FAA723264BED00EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinatorBridgePresenter.swift */; };
|
||||
B15F076924A0FBA7005E26A1 /* SecretsSetupRecoveryPassphraseViewAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B15F076124A0FBA3005E26A1 /* SecretsSetupRecoveryPassphraseViewAction.swift */; };
|
||||
B15F076A24A0FBA7005E26A1 /* SecretsSetupRecoveryPassphraseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B15F076224A0FBA4005E26A1 /* SecretsSetupRecoveryPassphraseViewController.swift */; };
|
||||
B15F076B24A0FBA7005E26A1 /* SecretsSetupRecoveryPassphraseViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B15F076324A0FBA4005E26A1 /* SecretsSetupRecoveryPassphraseViewController.storyboard */; };
|
||||
B15F076C24A0FBA7005E26A1 /* SecretsSetupRecoveryPassphraseCoordinatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B15F076424A0FBA4005E26A1 /* SecretsSetupRecoveryPassphraseCoordinatorType.swift */; };
|
||||
B15F076D24A0FBA7005E26A1 /* SecretsSetupRecoveryPassphraseViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B15F076524A0FBA5005E26A1 /* SecretsSetupRecoveryPassphraseViewState.swift */; };
|
||||
B15F076E24A0FBA7005E26A1 /* SecretsSetupRecoveryPassphraseViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B15F076624A0FBA5005E26A1 /* SecretsSetupRecoveryPassphraseViewModel.swift */; };
|
||||
B15F076F24A0FBA7005E26A1 /* SecretsSetupRecoveryPassphraseViewModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B15F076724A0FBA6005E26A1 /* SecretsSetupRecoveryPassphraseViewModelType.swift */; };
|
||||
B15F077024A0FBA7005E26A1 /* SecretsSetupRecoveryPassphraseCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B15F076824A0FBA6005E26A1 /* SecretsSetupRecoveryPassphraseCoordinator.swift */; };
|
||||
B15F077224A1F315005E26A1 /* SecretsSetupRecoveryPassphraseInputMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = B15F077124A1F314005E26A1 /* SecretsSetupRecoveryPassphraseInputMode.swift */; };
|
||||
B1664BC520F4E67600808783 /* FallbackViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = B1664BAD20F4E67500808783 /* FallbackViewController.xib */; };
|
||||
B1664BC620F4E67600808783 /* FallbackViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1664BAE20F4E67500808783 /* FallbackViewController.m */; };
|
||||
B1664BC720F4E67600808783 /* SharePresentingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1664BB220F4E67500808783 /* SharePresentingViewController.m */; };
|
||||
|
@ -293,6 +302,7 @@
|
|||
B183226623F55D6B0035B2E8 /* CameraAccessManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B183226523F55D6B0035B2E8 /* CameraAccessManager.swift */; };
|
||||
B183226823F561380035B2E8 /* CameraAccessAlertPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B183226723F561380035B2E8 /* CameraAccessAlertPresenter.swift */; };
|
||||
B183226C23F59F810035B2E8 /* CloseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B183226B23F59F810035B2E8 /* CloseButton.swift */; };
|
||||
B185AF4F24A2672D00EE7D30 /* SecretsRecoveryCoordinatorBridgePresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B185AF4E24A2672D00EE7D30 /* SecretsRecoveryCoordinatorBridgePresenter.swift */; };
|
||||
B18DEDD4243377C10075FEF7 /* KeyVerificationSelfVerifyWaitViewModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B18DEDCC243377C00075FEF7 /* KeyVerificationSelfVerifyWaitViewModelType.swift */; };
|
||||
B18DEDD5243377C10075FEF7 /* KeyVerificationSelfVerifyWaitViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B18DEDCD243377C00075FEF7 /* KeyVerificationSelfVerifyWaitViewModel.swift */; };
|
||||
B18DEDD6243377C10075FEF7 /* KeyVerificationSelfVerifyWaitCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B18DEDCE243377C00075FEF7 /* KeyVerificationSelfVerifyWaitCoordinator.swift */; };
|
||||
|
@ -662,7 +672,6 @@
|
|||
B1C960F02458308D00C5704B /* RoundedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1C960EF2458308D00C5704B /* RoundedButton.swift */; };
|
||||
B1CA3A2721EF6914000D1D89 /* UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1CA3A2621EF6913000D1D89 /* UIViewController.swift */; };
|
||||
B1CA3A2921EF692B000D1D89 /* UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1CA3A2821EF692B000D1D89 /* UIView.swift */; };
|
||||
B1CA93742493BDDF00575122 /* SecretsRecoveryCoordinatorBridgePresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1CA93732493BDDF00575122 /* SecretsRecoveryCoordinatorBridgePresenter.swift */; };
|
||||
B1CA93762493CBF200575122 /* MXRecoveryService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1CA93752493CBF200575122 /* MXRecoveryService.swift */; };
|
||||
B1CE83B62422812100D07506 /* KeyVerificationCoordinatorBridgePresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1CE83B52422812000D07506 /* KeyVerificationCoordinatorBridgePresenter.swift */; };
|
||||
B1CE83B92422815C00D07506 /* KeyVerificationKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1CE83B72422815900D07506 /* KeyVerificationKind.swift */; };
|
||||
|
@ -730,6 +739,21 @@
|
|||
B1DCC63922E85E9A00625807 /* EmojiMartStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1DCC63822E85E9A00625807 /* EmojiMartStore.swift */; };
|
||||
B1DCC63B22E85EF800625807 /* EmojiMartCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1DCC63A22E85EF800625807 /* EmojiMartCategory.swift */; };
|
||||
B1DCC63F22E9A3AE00625807 /* EmojiItem+EmojiMart.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1DCC63E22E9A3AE00625807 /* EmojiItem+EmojiMart.swift */; };
|
||||
B1DE85E7249A5733006454AF /* SecureKeyBackupSetupCoordinatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1DE85E4249A5732006454AF /* SecureKeyBackupSetupCoordinatorType.swift */; };
|
||||
B1DE85E8249A5733006454AF /* SecureKeyBackupSetupCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1DE85E5249A5732006454AF /* SecureKeyBackupSetupCoordinator.swift */; };
|
||||
B1DE85E9249A5733006454AF /* SecureKeyBackupSetupCoordinatorBridgePresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1DE85E6249A5732006454AF /* SecureKeyBackupSetupCoordinatorBridgePresenter.swift */; };
|
||||
B1DE85EC249A5819006454AF /* SecureKeyBackupSetupIntroViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1DE85EB249A5819006454AF /* SecureKeyBackupSetupIntroViewController.swift */; };
|
||||
B1DE85EE249A5981006454AF /* SecureKeyBackupSetupIntroViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B1DE85ED249A5981006454AF /* SecureKeyBackupSetupIntroViewController.storyboard */; };
|
||||
B1DE8608249A5C4B006454AF /* SecretsSetupRecoveryKeyViewAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1DE8600249A5C4A006454AF /* SecretsSetupRecoveryKeyViewAction.swift */; };
|
||||
B1DE8609249A5C4B006454AF /* SecretsSetupRecoveryKeyViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1DE8601249A5C4A006454AF /* SecretsSetupRecoveryKeyViewState.swift */; };
|
||||
B1DE860A249A5C4B006454AF /* SecretsSetupRecoveryKeyCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1DE8602249A5C4A006454AF /* SecretsSetupRecoveryKeyCoordinator.swift */; };
|
||||
B1DE860B249A5C4B006454AF /* SecretsSetupRecoveryKeyCoordinatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1DE8603249A5C4A006454AF /* SecretsSetupRecoveryKeyCoordinatorType.swift */; };
|
||||
B1DE860C249A5C4B006454AF /* SecretsSetupRecoveryKeyViewModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1DE8604249A5C4A006454AF /* SecretsSetupRecoveryKeyViewModelType.swift */; };
|
||||
B1DE860D249A5C4B006454AF /* SecretsSetupRecoveryKeyViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1DE8605249A5C4B006454AF /* SecretsSetupRecoveryKeyViewModel.swift */; };
|
||||
B1DE860E249A5C4B006454AF /* SecretsSetupRecoveryKeyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1DE8606249A5C4B006454AF /* SecretsSetupRecoveryKeyViewController.swift */; };
|
||||
B1DE860F249A5C4B006454AF /* SecretsSetupRecoveryKeyViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B1DE8607249A5C4B006454AF /* SecretsSetupRecoveryKeyViewController.storyboard */; };
|
||||
B1DE8611249BB448006454AF /* SecureKeyBackupSetupIntroCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1DE8610249BB448006454AF /* SecureKeyBackupSetupIntroCell.swift */; };
|
||||
B1DE8613249BB470006454AF /* SecureKeyBackupSetupIntroCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B1DE8612249BB470006454AF /* SecureKeyBackupSetupIntroCell.xib */; };
|
||||
B1E5368921FB1E20001F3AFF /* UIButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1E5368821FB1E20001F3AFF /* UIButton.swift */; };
|
||||
B1E5368D21FB7245001F3AFF /* KeyBackupRecoverFromPassphraseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1E5368C21FB7245001F3AFF /* KeyBackupRecoverFromPassphraseViewController.swift */; };
|
||||
B1E5368F21FB7258001F3AFF /* KeyBackupRecoverFromPassphraseViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B1E5368E21FB7258001F3AFF /* KeyBackupRecoverFromPassphraseViewController.storyboard */; };
|
||||
|
@ -1076,6 +1100,15 @@
|
|||
B157FA9D23264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsDiscoveryThreePidDetailsViewModel.swift; sourceTree = "<group>"; };
|
||||
B157FA9E23264AE800EBFBD4 /* SettingsDiscoveryThreePidDetailsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsDiscoveryThreePidDetailsViewController.swift; sourceTree = "<group>"; };
|
||||
B157FAA723264BED00EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinatorBridgePresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsDiscoveryThreePidDetailsCoordinatorBridgePresenter.swift; sourceTree = "<group>"; };
|
||||
B15F076124A0FBA3005E26A1 /* SecretsSetupRecoveryPassphraseViewAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretsSetupRecoveryPassphraseViewAction.swift; sourceTree = "<group>"; };
|
||||
B15F076224A0FBA4005E26A1 /* SecretsSetupRecoveryPassphraseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretsSetupRecoveryPassphraseViewController.swift; sourceTree = "<group>"; };
|
||||
B15F076324A0FBA4005E26A1 /* SecretsSetupRecoveryPassphraseViewController.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = SecretsSetupRecoveryPassphraseViewController.storyboard; sourceTree = "<group>"; };
|
||||
B15F076424A0FBA4005E26A1 /* SecretsSetupRecoveryPassphraseCoordinatorType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretsSetupRecoveryPassphraseCoordinatorType.swift; sourceTree = "<group>"; };
|
||||
B15F076524A0FBA5005E26A1 /* SecretsSetupRecoveryPassphraseViewState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretsSetupRecoveryPassphraseViewState.swift; sourceTree = "<group>"; };
|
||||
B15F076624A0FBA5005E26A1 /* SecretsSetupRecoveryPassphraseViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretsSetupRecoveryPassphraseViewModel.swift; sourceTree = "<group>"; };
|
||||
B15F076724A0FBA6005E26A1 /* SecretsSetupRecoveryPassphraseViewModelType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretsSetupRecoveryPassphraseViewModelType.swift; sourceTree = "<group>"; };
|
||||
B15F076824A0FBA6005E26A1 /* SecretsSetupRecoveryPassphraseCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretsSetupRecoveryPassphraseCoordinator.swift; sourceTree = "<group>"; };
|
||||
B15F077124A1F314005E26A1 /* SecretsSetupRecoveryPassphraseInputMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecretsSetupRecoveryPassphraseInputMode.swift; sourceTree = "<group>"; };
|
||||
B1664BAD20F4E67500808783 /* FallbackViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = FallbackViewController.xib; sourceTree = "<group>"; };
|
||||
B1664BAE20F4E67500808783 /* FallbackViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FallbackViewController.m; sourceTree = "<group>"; };
|
||||
B1664BAF20F4E67500808783 /* FallbackViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FallbackViewController.h; sourceTree = "<group>"; };
|
||||
|
@ -1168,6 +1201,7 @@
|
|||
B183226523F55D6B0035B2E8 /* CameraAccessManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraAccessManager.swift; sourceTree = "<group>"; };
|
||||
B183226723F561380035B2E8 /* CameraAccessAlertPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraAccessAlertPresenter.swift; sourceTree = "<group>"; };
|
||||
B183226B23F59F810035B2E8 /* CloseButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloseButton.swift; sourceTree = "<group>"; };
|
||||
B185AF4E24A2672D00EE7D30 /* SecretsRecoveryCoordinatorBridgePresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretsRecoveryCoordinatorBridgePresenter.swift; sourceTree = "<group>"; };
|
||||
B18DEDCC243377C00075FEF7 /* KeyVerificationSelfVerifyWaitViewModelType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyVerificationSelfVerifyWaitViewModelType.swift; sourceTree = "<group>"; };
|
||||
B18DEDCD243377C00075FEF7 /* KeyVerificationSelfVerifyWaitViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyVerificationSelfVerifyWaitViewModel.swift; sourceTree = "<group>"; };
|
||||
B18DEDCE243377C00075FEF7 /* KeyVerificationSelfVerifyWaitCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyVerificationSelfVerifyWaitCoordinator.swift; sourceTree = "<group>"; };
|
||||
|
@ -1677,7 +1711,6 @@
|
|||
B1C960EF2458308D00C5704B /* RoundedButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedButton.swift; sourceTree = "<group>"; };
|
||||
B1CA3A2621EF6913000D1D89 /* UIViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewController.swift; sourceTree = "<group>"; };
|
||||
B1CA3A2821EF692B000D1D89 /* UIView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIView.swift; sourceTree = "<group>"; };
|
||||
B1CA93732493BDDF00575122 /* SecretsRecoveryCoordinatorBridgePresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecretsRecoveryCoordinatorBridgePresenter.swift; sourceTree = "<group>"; };
|
||||
B1CA93752493CBF200575122 /* MXRecoveryService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXRecoveryService.swift; sourceTree = "<group>"; };
|
||||
B1CE83B52422812000D07506 /* KeyVerificationCoordinatorBridgePresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyVerificationCoordinatorBridgePresenter.swift; sourceTree = "<group>"; };
|
||||
B1CE83B72422815900D07506 /* KeyVerificationKind.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyVerificationKind.swift; sourceTree = "<group>"; };
|
||||
|
@ -1742,6 +1775,21 @@
|
|||
B1DCC63822E85E9A00625807 /* EmojiMartStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiMartStore.swift; sourceTree = "<group>"; };
|
||||
B1DCC63A22E85EF800625807 /* EmojiMartCategory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiMartCategory.swift; sourceTree = "<group>"; };
|
||||
B1DCC63E22E9A3AE00625807 /* EmojiItem+EmojiMart.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EmojiItem+EmojiMart.swift"; sourceTree = "<group>"; };
|
||||
B1DE85E4249A5732006454AF /* SecureKeyBackupSetupCoordinatorType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecureKeyBackupSetupCoordinatorType.swift; sourceTree = "<group>"; };
|
||||
B1DE85E5249A5732006454AF /* SecureKeyBackupSetupCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecureKeyBackupSetupCoordinator.swift; sourceTree = "<group>"; };
|
||||
B1DE85E6249A5732006454AF /* SecureKeyBackupSetupCoordinatorBridgePresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecureKeyBackupSetupCoordinatorBridgePresenter.swift; sourceTree = "<group>"; };
|
||||
B1DE85EB249A5819006454AF /* SecureKeyBackupSetupIntroViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureKeyBackupSetupIntroViewController.swift; sourceTree = "<group>"; };
|
||||
B1DE85ED249A5981006454AF /* SecureKeyBackupSetupIntroViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = SecureKeyBackupSetupIntroViewController.storyboard; sourceTree = "<group>"; };
|
||||
B1DE8600249A5C4A006454AF /* SecretsSetupRecoveryKeyViewAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretsSetupRecoveryKeyViewAction.swift; sourceTree = "<group>"; };
|
||||
B1DE8601249A5C4A006454AF /* SecretsSetupRecoveryKeyViewState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretsSetupRecoveryKeyViewState.swift; sourceTree = "<group>"; };
|
||||
B1DE8602249A5C4A006454AF /* SecretsSetupRecoveryKeyCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretsSetupRecoveryKeyCoordinator.swift; sourceTree = "<group>"; };
|
||||
B1DE8603249A5C4A006454AF /* SecretsSetupRecoveryKeyCoordinatorType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretsSetupRecoveryKeyCoordinatorType.swift; sourceTree = "<group>"; };
|
||||
B1DE8604249A5C4A006454AF /* SecretsSetupRecoveryKeyViewModelType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretsSetupRecoveryKeyViewModelType.swift; sourceTree = "<group>"; };
|
||||
B1DE8605249A5C4B006454AF /* SecretsSetupRecoveryKeyViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretsSetupRecoveryKeyViewModel.swift; sourceTree = "<group>"; };
|
||||
B1DE8606249A5C4B006454AF /* SecretsSetupRecoveryKeyViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretsSetupRecoveryKeyViewController.swift; sourceTree = "<group>"; };
|
||||
B1DE8607249A5C4B006454AF /* SecretsSetupRecoveryKeyViewController.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = SecretsSetupRecoveryKeyViewController.storyboard; sourceTree = "<group>"; };
|
||||
B1DE8610249BB448006454AF /* SecureKeyBackupSetupIntroCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureKeyBackupSetupIntroCell.swift; sourceTree = "<group>"; };
|
||||
B1DE8612249BB470006454AF /* SecureKeyBackupSetupIntroCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SecureKeyBackupSetupIntroCell.xib; sourceTree = "<group>"; };
|
||||
B1E5368821FB1E20001F3AFF /* UIButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIButton.swift; sourceTree = "<group>"; };
|
||||
B1E5368C21FB7245001F3AFF /* KeyBackupRecoverFromPassphraseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverFromPassphraseViewController.swift; sourceTree = "<group>"; };
|
||||
B1E5368E21FB7258001F3AFF /* KeyBackupRecoverFromPassphraseViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = KeyBackupRecoverFromPassphraseViewController.storyboard; sourceTree = "<group>"; };
|
||||
|
@ -2251,6 +2299,7 @@
|
|||
B1098BE921ECFE64000DDA48 /* KeyBackup */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B1DE85E3249A51F7006454AF /* SecureSetup */,
|
||||
B1098C0221ECFEAF000DDA48 /* Setup */,
|
||||
B1FDF56421F726AD00BA3834 /* Recover */,
|
||||
B1107ECB2201BE800038014B /* Banners */,
|
||||
|
@ -2506,6 +2555,22 @@
|
|||
path = ThreePidDetails;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B15F075C24A0A196005E26A1 /* RecoveryPassphrase */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B15F077124A1F314005E26A1 /* SecretsSetupRecoveryPassphraseInputMode.swift */,
|
||||
B15F076424A0FBA4005E26A1 /* SecretsSetupRecoveryPassphraseCoordinatorType.swift */,
|
||||
B15F076824A0FBA6005E26A1 /* SecretsSetupRecoveryPassphraseCoordinator.swift */,
|
||||
B15F076124A0FBA3005E26A1 /* SecretsSetupRecoveryPassphraseViewAction.swift */,
|
||||
B15F076524A0FBA5005E26A1 /* SecretsSetupRecoveryPassphraseViewState.swift */,
|
||||
B15F076724A0FBA6005E26A1 /* SecretsSetupRecoveryPassphraseViewModelType.swift */,
|
||||
B15F076624A0FBA5005E26A1 /* SecretsSetupRecoveryPassphraseViewModel.swift */,
|
||||
B15F076224A0FBA4005E26A1 /* SecretsSetupRecoveryPassphraseViewController.swift */,
|
||||
B15F076324A0FBA4005E26A1 /* SecretsSetupRecoveryPassphraseViewController.storyboard */,
|
||||
);
|
||||
path = RecoveryPassphrase;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B1664BAB20F4E67500808783 /* Modules */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -2818,18 +2883,13 @@
|
|||
path = Riot/Modules/Common/CollectionView;
|
||||
sourceTree = SOURCE_ROOT;
|
||||
};
|
||||
B19C4E6A248E98B9009A423F /* SecretsRecovery */ = {
|
||||
B19C4E6A248E98B9009A423F /* Secrets */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B1CA93732493BDDF00575122 /* SecretsRecoveryCoordinatorBridgePresenter.swift */,
|
||||
B19C4E6D248F79EE009A423F /* SecretsRecoveryCoordinatorType.swift */,
|
||||
B19C4E6E248F79EF009A423F /* SecretsRecoveryCoordinator.swift */,
|
||||
B19C4E9324922403009A423F /* SecretsRecoveryMode.swift */,
|
||||
B19C4E91249223D0009A423F /* SecretsRecoveryGoal.swift */,
|
||||
B19C4E6B248E993F009A423F /* RecoverWithPassphrase */,
|
||||
B19C4E6C248E994D009A423F /* RecoverWithKey */,
|
||||
B1DE85E1249A5007006454AF /* Setup */,
|
||||
B1B408EE249A4F39004A331C /* Recover */,
|
||||
);
|
||||
path = SecretsRecovery;
|
||||
path = Secrets;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B19C4E6B248E993F009A423F /* RecoverWithPassphrase */ = {
|
||||
|
@ -2937,6 +2997,20 @@
|
|||
path = SelfVerifyStart;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B1B408EE249A4F39004A331C /* Recover */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B185AF4E24A2672D00EE7D30 /* SecretsRecoveryCoordinatorBridgePresenter.swift */,
|
||||
B19C4E6D248F79EE009A423F /* SecretsRecoveryCoordinatorType.swift */,
|
||||
B19C4E6E248F79EF009A423F /* SecretsRecoveryCoordinator.swift */,
|
||||
B19C4E9324922403009A423F /* SecretsRecoveryMode.swift */,
|
||||
B19C4E91249223D0009A423F /* SecretsRecoveryGoal.swift */,
|
||||
B19C4E6B248E993F009A423F /* RecoverWithPassphrase */,
|
||||
B19C4E6C248E994D009A423F /* RecoverWithKey */,
|
||||
);
|
||||
path = Recover;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B1B5567620EE6C4C00210D55 /* Modules */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -2965,7 +3039,7 @@
|
|||
B1B556B020EE6C4C00210D55 /* BugReport */,
|
||||
B1098BE921ECFE64000DDA48 /* KeyBackup */,
|
||||
B1550FCF242148FA00CE097B /* KeyVerification */,
|
||||
B19C4E6A248E98B9009A423F /* SecretsRecovery */,
|
||||
B19C4E6A248E98B9009A423F /* Secrets */,
|
||||
B1A6C10523881ECB002882FD /* SlidingModal */,
|
||||
32DB556722FDADE50016329E /* ServiceTerms */,
|
||||
B1550FC52420E8F400CE097B /* QRCode */,
|
||||
|
@ -4289,6 +4363,52 @@
|
|||
path = Store;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B1DE85E1249A5007006454AF /* Setup */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B1DE85E2249A5034006454AF /* RecoveryKey */,
|
||||
B15F075C24A0A196005E26A1 /* RecoveryPassphrase */,
|
||||
);
|
||||
path = Setup;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B1DE85E2249A5034006454AF /* RecoveryKey */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B1DE8603249A5C4A006454AF /* SecretsSetupRecoveryKeyCoordinatorType.swift */,
|
||||
B1DE8602249A5C4A006454AF /* SecretsSetupRecoveryKeyCoordinator.swift */,
|
||||
B1DE8600249A5C4A006454AF /* SecretsSetupRecoveryKeyViewAction.swift */,
|
||||
B1DE8601249A5C4A006454AF /* SecretsSetupRecoveryKeyViewState.swift */,
|
||||
B1DE8604249A5C4A006454AF /* SecretsSetupRecoveryKeyViewModelType.swift */,
|
||||
B1DE8605249A5C4B006454AF /* SecretsSetupRecoveryKeyViewModel.swift */,
|
||||
B1DE8606249A5C4B006454AF /* SecretsSetupRecoveryKeyViewController.swift */,
|
||||
B1DE8607249A5C4B006454AF /* SecretsSetupRecoveryKeyViewController.storyboard */,
|
||||
);
|
||||
path = RecoveryKey;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B1DE85E3249A51F7006454AF /* SecureSetup */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B1DE85E6249A5732006454AF /* SecureKeyBackupSetupCoordinatorBridgePresenter.swift */,
|
||||
B1DE85E4249A5732006454AF /* SecureKeyBackupSetupCoordinatorType.swift */,
|
||||
B1DE85E5249A5732006454AF /* SecureKeyBackupSetupCoordinator.swift */,
|
||||
B1DE85EA249A5737006454AF /* Intro */,
|
||||
);
|
||||
path = SecureSetup;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B1DE85EA249A5737006454AF /* Intro */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B1DE85EB249A5819006454AF /* SecureKeyBackupSetupIntroViewController.swift */,
|
||||
B1DE85ED249A5981006454AF /* SecureKeyBackupSetupIntroViewController.storyboard */,
|
||||
B1DE8610249BB448006454AF /* SecureKeyBackupSetupIntroCell.swift */,
|
||||
B1DE8612249BB470006454AF /* SecureKeyBackupSetupIntroCell.xib */,
|
||||
);
|
||||
path = Intro;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B1E5368A21FB6FC0001F3AFF /* Passphrase */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -4767,10 +4887,12 @@
|
|||
F083BDF21E7009ED00A9B29C /* GoogleService-Info.plist in Resources */,
|
||||
329E746622CD02EA006F9797 /* BubbleReactionActionViewCell.xib in Resources */,
|
||||
B1B558E320EF768F00210D55 /* RoomEmptyBubbleCell.xib in Resources */,
|
||||
B1DE85EE249A5981006454AF /* SecureKeyBackupSetupIntroViewController.storyboard in Resources */,
|
||||
B1E5368F21FB7258001F3AFF /* KeyBackupRecoverFromPassphraseViewController.storyboard in Resources */,
|
||||
B1B5590420EF768F00210D55 /* RoomOutgoingAttachmentBubbleCell.xib in Resources */,
|
||||
B1B558F120EF768F00210D55 /* RoomIncomingAttachmentWithPaginationTitleBubbleCell.xib in Resources */,
|
||||
B1B557CB20EF5D8000210D55 /* DirectoryServerTableViewCell.xib in Resources */,
|
||||
B1DE860F249A5C4B006454AF /* SecretsSetupRecoveryKeyViewController.storyboard in Resources */,
|
||||
B1B558EC20EF768F00210D55 /* RoomMembershipCollapsedBubbleCell.xib in Resources */,
|
||||
B1B558D720EF768F00210D55 /* RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.xib in Resources */,
|
||||
B1B5590820EF768F00210D55 /* RoomMembershipWithPaginationTitleBubbleCell.xib in Resources */,
|
||||
|
@ -4817,6 +4939,7 @@
|
|||
F083BE061E7009ED00A9B29C /* Riot-Defaults.plist in Resources */,
|
||||
B1B558D120EF768F00210D55 /* RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.xib in Resources */,
|
||||
B1B558FE20EF768F00210D55 /* RoomMembershipExpandedWithPaginationTitleBubbleCell.xib in Resources */,
|
||||
B15F076B24A0FBA7005E26A1 /* SecretsSetupRecoveryPassphraseViewController.storyboard in Resources */,
|
||||
B1B5581D20EF625800210D55 /* RoomAvatarTitleView.xib in Resources */,
|
||||
B1BEE74923E093260003A4CB /* UserVerificationSessionStatusViewController.storyboard in Resources */,
|
||||
B1B5590B20EF768F00210D55 /* RoomMembershipExpandedBubbleCell.xib in Resources */,
|
||||
|
@ -4855,6 +4978,7 @@
|
|||
B105778F2213052A00334B1E /* KeyBackupSetupSuccessFromRecoveryKeyViewController.storyboard in Resources */,
|
||||
B19C4E90248F7A0E009A423F /* SecretsRecoveryWithPassphraseViewController.storyboard in Resources */,
|
||||
B1B5590F20EF782800210D55 /* TableViewCellWithPhoneNumberTextField.xib in Resources */,
|
||||
B1DE8613249BB470006454AF /* SecureKeyBackupSetupIntroCell.xib in Resources */,
|
||||
B19C4E80248F79FD009A423F /* SecretsRecoveryWithKeyViewController.storyboard in Resources */,
|
||||
B1B5578520EF564900210D55 /* GroupTableViewCellWithSwitch.xib in Resources */,
|
||||
B1B557B320EF5AEF00210D55 /* EventDetailsView.xib in Resources */,
|
||||
|
@ -5084,6 +5208,7 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B1DE8611249BB448006454AF /* SecureKeyBackupSetupIntroCell.swift in Sources */,
|
||||
B1B557D120EF5E3500210D55 /* MediaAlbumTableCell.m in Sources */,
|
||||
32607D71243E0A55006674CC /* KeyBackupRecoverFromPrivateKeyViewState.swift in Sources */,
|
||||
324A2053225FC571004FE8B0 /* DeviceVerificationIncomingViewModel.swift in Sources */,
|
||||
|
@ -5109,6 +5234,7 @@
|
|||
B1B5581C20EF625800210D55 /* RoomAvatarTitleView.m in Sources */,
|
||||
B169330820F3CA0E00746532 /* ContactsDataSource.m in Sources */,
|
||||
B1B5574B20EE6C4D00210D55 /* MediaAlbumContentViewController.m in Sources */,
|
||||
B1DE85E9249A5733006454AF /* SecureKeyBackupSetupCoordinatorBridgePresenter.swift in Sources */,
|
||||
B1B5598820EFC3E000210D55 /* WidgetManager.m in Sources */,
|
||||
B1DB4F0E22316FFF0065DBFA /* UserNameColorGenerator.swift in Sources */,
|
||||
6E6F1CB524506FA40068B78B /* UITableView.swift in Sources */,
|
||||
|
@ -5143,6 +5269,7 @@
|
|||
B1B558E820EF768F00210D55 /* RoomIncomingAttachmentWithPaginationTitleBubbleCell.m in Sources */,
|
||||
B1B558F320EF768F00210D55 /* RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m in Sources */,
|
||||
B12D79FE23E2462200FACEDC /* UserVerificationStartViewController.swift in Sources */,
|
||||
B15F077224A1F315005E26A1 /* SecretsSetupRecoveryPassphraseInputMode.swift in Sources */,
|
||||
32607D73243E0A55006674CC /* KeyBackupRecoverFromPrivateKeyCoordinator.swift in Sources */,
|
||||
B1B557BD20EF5B4500210D55 /* KeyboardGrowingTextView.m in Sources */,
|
||||
B1A68593229E807A00D6C09A /* RoomBubbleCellLayout.swift in Sources */,
|
||||
|
@ -5156,6 +5283,7 @@
|
|||
B1C960F02458308D00C5704B /* RoundedButton.swift in Sources */,
|
||||
B1CE83D52422817200D07506 /* KeyVerificationVerifyByScanningViewController.swift in Sources */,
|
||||
B19C4E8C248F7A0E009A423F /* SecretsRecoveryWithPassphraseViewState.swift in Sources */,
|
||||
B1DE860C249A5C4B006454AF /* SecretsSetupRecoveryKeyViewModelType.swift in Sources */,
|
||||
3232ABA3225730E100AD6A5C /* DeviceVerificationStartCoordinatorType.swift in Sources */,
|
||||
3232AB4D2256558300AD6A5C /* TemplateScreenCoordinatorType.swift in Sources */,
|
||||
B1B5581720EF625800210D55 /* PreviewRoomTitleView.m in Sources */,
|
||||
|
@ -5173,6 +5301,7 @@
|
|||
B1B558CB20EF768F00210D55 /* RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.m in Sources */,
|
||||
B11291EA238D35590077B478 /* SlidingModalPresentable.swift in Sources */,
|
||||
B157FAA823264BED00EBFBD4 /* SettingsDiscoveryThreePidDetailsCoordinatorBridgePresenter.swift in Sources */,
|
||||
B1DE85E8249A5733006454AF /* SecureKeyBackupSetupCoordinator.swift in Sources */,
|
||||
B169330B20F3CA3A00746532 /* Contact.m in Sources */,
|
||||
B1A5B33E227ADF2A004CBA85 /* UIImage.swift in Sources */,
|
||||
6E6F1CB324506EC50068B78B /* UITableViewCell.swift in Sources */,
|
||||
|
@ -5193,6 +5322,7 @@
|
|||
B1CE83DC2422817200D07506 /* KeyVerificationVerifyByScanningViewState.swift in Sources */,
|
||||
B139C21B21FE5B9200BB68EC /* KeyBackupRecoverFromPassphraseViewModel.swift in Sources */,
|
||||
B1C45A8C232A8C2600165425 /* SettingsIdentityServerViewAction.swift in Sources */,
|
||||
B1DE85E7249A5733006454AF /* SecureKeyBackupSetupCoordinatorType.swift in Sources */,
|
||||
32A6001E22C661100042C1D9 /* EditHistoryCoordinatorBridgePresenter.swift in Sources */,
|
||||
B1B5574A20EE6C4D00210D55 /* MediaPickerViewController.m in Sources */,
|
||||
B1BEE74623E093260003A4CB /* UserVerificationSessionStatusViewState.swift in Sources */,
|
||||
|
@ -5215,6 +5345,7 @@
|
|||
B157A7BA2445BD86008A5504 /* KeyVerificationScanConfirmationCoordinator.swift in Sources */,
|
||||
B125FE1D231D5DE400B72806 /* SettingsDiscoveryViewModel.swift in Sources */,
|
||||
32863A5A2384070300D07C4A /* RiotSharedSettings.swift in Sources */,
|
||||
B1DE860E249A5C4B006454AF /* SecretsSetupRecoveryKeyViewController.swift in Sources */,
|
||||
B1B5594720EF7BD000210D55 /* RoomCollectionViewCell.m in Sources */,
|
||||
B14B17652462C69000C2751E /* KeyVerificationManuallyVerifyViewModel.swift in Sources */,
|
||||
B14B17662462C69000C2751E /* KeyVerificationManuallyVerifyCoordinatorType.swift in Sources */,
|
||||
|
@ -5222,6 +5353,7 @@
|
|||
B1A6C10B23882B6C002882FD /* SlidingModalPresentationAnimator.swift in Sources */,
|
||||
B1B558C120EF768F00210D55 /* RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.m in Sources */,
|
||||
B1B5573E20EE6C4D00210D55 /* RiotNavigationController.m in Sources */,
|
||||
B15F076C24A0FBA7005E26A1 /* SecretsSetupRecoveryPassphraseCoordinatorType.swift in Sources */,
|
||||
B1B5593B20EF7BAC00210D55 /* TableViewCellWithCheckBoxAndLabel.m in Sources */,
|
||||
B1B5581A20EF625800210D55 /* ExpandedRoomTitleView.m in Sources */,
|
||||
B1107EC82200B0720038014B /* KeyBackupRecoverSuccessViewController.swift in Sources */,
|
||||
|
@ -5241,6 +5373,7 @@
|
|||
32DB557F22FDADE50016329E /* ServiceTermsModalScreenCoordinator.swift in Sources */,
|
||||
B157A7B72445BD86008A5504 /* KeyVerificationScanConfirmationViewModel.swift in Sources */,
|
||||
B1098C1121ED07E4000DDA48 /* NavigationRouterType.swift in Sources */,
|
||||
B1DE860D249A5C4B006454AF /* SecretsSetupRecoveryKeyViewModel.swift in Sources */,
|
||||
B1B5573D20EE6C4D00210D55 /* WebViewViewController.m in Sources */,
|
||||
3209451221F1C1430088CAA2 /* BlackTheme.swift in Sources */,
|
||||
B1B5572720EE6C4D00210D55 /* RoomSearchViewController.m in Sources */,
|
||||
|
@ -5271,7 +5404,6 @@
|
|||
3232ABC2225B996200AD6A5C /* Themable.swift in Sources */,
|
||||
32A6001B22C661100042C1D9 /* EditHistoryViewAction.swift in Sources */,
|
||||
3232ABA7225730E100AD6A5C /* DeviceVerificationStartCoordinator.swift in Sources */,
|
||||
B1CA93742493BDDF00575122 /* SecretsRecoveryCoordinatorBridgePresenter.swift in Sources */,
|
||||
6E75C3E32458797D00AF497D /* UniversalLink.m in Sources */,
|
||||
B1D4752721EE4E630067973F /* KeyboardAvoider.swift in Sources */,
|
||||
B1D4752821EE4E630067973F /* KeyboardNotification.swift in Sources */,
|
||||
|
@ -5292,6 +5424,7 @@
|
|||
B1B558E420EF768F00210D55 /* RoomMembershipWithPaginationTitleBubbleCell.m in Sources */,
|
||||
B18DEDD8243377C10075FEF7 /* KeyVerificationSelfVerifyWaitCoordinatorType.swift in Sources */,
|
||||
B1B5573620EE6C4D00210D55 /* GroupsViewController.m in Sources */,
|
||||
B15F077024A0FBA7005E26A1 /* SecretsSetupRecoveryPassphraseCoordinator.swift in Sources */,
|
||||
B125FE21231D5E1D00B72806 /* SettingsDiscoveryViewAction.swift in Sources */,
|
||||
B108932323AB908A00802670 /* KeyVerificationRequestStatusViewData.swift in Sources */,
|
||||
B19C4E70248F79EF009A423F /* SecretsRecoveryCoordinator.swift in Sources */,
|
||||
|
@ -5311,6 +5444,7 @@
|
|||
B12D7A0123E2462200FACEDC /* UserVerificationStartViewModel.swift in Sources */,
|
||||
B12C56EF2396CB5E00FAC6DE /* RoomMessageURLParser.swift in Sources */,
|
||||
B1BEE73623DF44A60003A4CB /* UserVerificationSessionsStatusCoordinatorType.swift in Sources */,
|
||||
B1DE8608249A5C4B006454AF /* SecretsSetupRecoveryKeyViewAction.swift in Sources */,
|
||||
B1C45A86232A8C2600165425 /* SettingsIdentityServerViewModelType.swift in Sources */,
|
||||
F083BE031E7009ED00A9B29C /* EventFormatter.m in Sources */,
|
||||
B157FAA623264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsViewController.swift in Sources */,
|
||||
|
@ -5334,12 +5468,14 @@
|
|||
F0D2ADA11F6AA5FD00A7097D /* MXRoomSummary+Riot.m in Sources */,
|
||||
B19C4E7C248F79FD009A423F /* SecretsRecoveryWithKeyViewModel.swift in Sources */,
|
||||
B1CE83B92422815C00D07506 /* KeyVerificationKind.swift in Sources */,
|
||||
B15F076E24A0FBA7005E26A1 /* SecretsSetupRecoveryPassphraseViewModel.swift in Sources */,
|
||||
B1BEE71423DF2ACF0003A4CB /* UserVerificationCoordinatorType.swift in Sources */,
|
||||
B1B5596F20EFA85D00210D55 /* EncryptionInfoView.m in Sources */,
|
||||
B1B5573820EE6C4D00210D55 /* GroupParticipantsViewController.m in Sources */,
|
||||
3232ABAB225730E100AD6A5C /* KeyVerificationCoordinator.swift in Sources */,
|
||||
B1BEE73B23DF44A60003A4CB /* UserVerificationSessionsStatusCoordinator.swift in Sources */,
|
||||
B1B5583E20EF6E7F00210D55 /* GroupRoomTableViewCell.m in Sources */,
|
||||
B15F076924A0FBA7005E26A1 /* SecretsSetupRecoveryPassphraseViewAction.swift in Sources */,
|
||||
B14F143522144F6500FA0595 /* KeyBackupRecoverFromRecoveryKeyViewController.swift in Sources */,
|
||||
B1DCC61E22E5E17100625807 /* EmojiPickerViewModel.swift in Sources */,
|
||||
B1B5574F20EE6C4D00210D55 /* RoomsViewController.m in Sources */,
|
||||
|
@ -5358,6 +5494,7 @@
|
|||
B183226623F55D6B0035B2E8 /* CameraAccessManager.swift in Sources */,
|
||||
B1B5571D20EE6C4D00210D55 /* HomeViewController.m in Sources */,
|
||||
B1CE83DD2422817200D07506 /* KeyVerificationVerifyBySASViewAction.swift in Sources */,
|
||||
B185AF4F24A2672D00EE7D30 /* SecretsRecoveryCoordinatorBridgePresenter.swift in Sources */,
|
||||
B1C45A84232A8C2600165425 /* SettingsIdentityServerCoordinatorType.swift in Sources */,
|
||||
B1DCC63722E8541700625807 /* EmojiStore.swift in Sources */,
|
||||
3232ABA6225730E100AD6A5C /* DeviceVerificationStartViewController.swift in Sources */,
|
||||
|
@ -5454,6 +5591,7 @@
|
|||
32607D6E243E0A55006674CC /* KeyBackupRecoverFromPrivateKeyViewModelType.swift in Sources */,
|
||||
B1B558D020EF768F00210D55 /* RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */,
|
||||
B1B558CF20EF768F00210D55 /* RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.m in Sources */,
|
||||
B1DE8609249A5C4B006454AF /* SecretsSetupRecoveryKeyViewState.swift in Sources */,
|
||||
B140B4A221F87F7100E3F5FE /* OperationQueue.swift in Sources */,
|
||||
B14B17612462C69000C2751E /* KeyVerificationManuallyVerifyCoordinator.swift in Sources */,
|
||||
B183226C23F59F810035B2E8 /* CloseButton.swift in Sources */,
|
||||
|
@ -5500,6 +5638,7 @@
|
|||
B1098BFF21ECFE65000DDA48 /* PasswordStrengthView.swift in Sources */,
|
||||
B1B558D220EF768F00210D55 /* RoomEncryptedDataBubbleCell.m in Sources */,
|
||||
B1B558FA20EF768F00210D55 /* RoomMembershipBubbleCell.m in Sources */,
|
||||
B1DE860B249A5C4B006454AF /* SecretsSetupRecoveryKeyCoordinatorType.swift in Sources */,
|
||||
B157FAA223264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsViewAction.swift in Sources */,
|
||||
B1CE83D72422817200D07506 /* KeyVerificationVerifyByScanningViewModelType.swift in Sources */,
|
||||
3232ABA1225730E100AD6A5C /* KeyVerificationCoordinatorType.swift in Sources */,
|
||||
|
@ -5520,6 +5659,7 @@
|
|||
324A2050225FC571004FE8B0 /* DeviceVerificationIncomingViewController.swift in Sources */,
|
||||
B1098C0D21ED07E4000DDA48 /* NavigationRouter.swift in Sources */,
|
||||
B110872321F098F0003554A5 /* ActivityIndicatorPresenterType.swift in Sources */,
|
||||
B1DE860A249A5C4B006454AF /* SecretsSetupRecoveryKeyCoordinator.swift in Sources */,
|
||||
B139C22321FF01B200BB68EC /* KeyBackupRecoverFromPassphraseCoordinatorType.swift in Sources */,
|
||||
B14084CE23BFA0990010F692 /* KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.swift in Sources */,
|
||||
B14F143222144F6500FA0595 /* KeyBackupRecoverFromRecoveryKeyCoordinator.swift in Sources */,
|
||||
|
@ -5527,6 +5667,7 @@
|
|||
B1CE83E02422817200D07506 /* KeyVerificationVerifyBySASViewController.swift in Sources */,
|
||||
B19EFA3921F8BB2C00FC070E /* KeyBackupRecoverCoordinatorType.swift in Sources */,
|
||||
B1C3360322F1ED600021BA8D /* MediaPickerCoordinator.swift in Sources */,
|
||||
B15F076D24A0FBA7005E26A1 /* SecretsSetupRecoveryPassphraseViewState.swift in Sources */,
|
||||
B1E5368D21FB7245001F3AFF /* KeyBackupRecoverFromPassphraseViewController.swift in Sources */,
|
||||
B1963B3822933BC800CBA17F /* AutosizedCollectionView.swift in Sources */,
|
||||
B12D79FB23E2462200FACEDC /* UserVerificationStartCoordinator.swift in Sources */,
|
||||
|
@ -5590,6 +5731,7 @@
|
|||
B1CE83DA2422817200D07506 /* KeyVerificationVerifyByScanningViewModel.swift in Sources */,
|
||||
32242F0921E8B05F00725742 /* UIColor.swift in Sources */,
|
||||
B16932E720F3C37100746532 /* HomeMessagesSearchDataSource.m in Sources */,
|
||||
B1DE85EC249A5819006454AF /* SecureKeyBackupSetupIntroViewController.swift in Sources */,
|
||||
B12D79FF23E2462200FACEDC /* UserVerificationStartViewState.swift in Sources */,
|
||||
B1B558CE20EF768F00210D55 /* RoomOutgoingEncryptedAttachmentBubbleCell.m in Sources */,
|
||||
B14B17672462C69000C2751E /* KeyVerificationManuallyVerifyViewState.swift in Sources */,
|
||||
|
@ -5608,11 +5750,13 @@
|
|||
B1B9DEEE22EB34EF0065E677 /* ReactionHistoryViewAction.swift in Sources */,
|
||||
B1C543A4239E98E400DCA1FA /* KeyVerificationCellInnerContentView.swift in Sources */,
|
||||
B1CE83B62422812100D07506 /* KeyVerificationCoordinatorBridgePresenter.swift in Sources */,
|
||||
B15F076F24A0FBA7005E26A1 /* SecretsSetupRecoveryPassphraseViewModelType.swift in Sources */,
|
||||
32B94DFA228EC26400716A26 /* ReactionsMenuButton.swift in Sources */,
|
||||
B1B9DEEC22EB34EF0065E677 /* ReactionHistoryViewModelType.swift in Sources */,
|
||||
B157FAA523264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsViewModel.swift in Sources */,
|
||||
B1C562E8228C7CF20037F12A /* ContextualMenuItemView.swift in Sources */,
|
||||
B14F143022144F6500FA0595 /* KeyBackupRecoverFromRecoveryKeyCoordinatorType.swift in Sources */,
|
||||
B15F076A24A0FBA7005E26A1 /* SecretsSetupRecoveryPassphraseViewController.swift in Sources */,
|
||||
B1E5368921FB1E20001F3AFF /* UIButton.swift in Sources */,
|
||||
B1DCC63422E72C1B00625807 /* UISearchBar.swift in Sources */,
|
||||
32A6001622C661100042C1D9 /* EditHistoryViewState.swift in Sources */,
|
||||
|
|
|
@ -2962,7 +2962,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
|||
}
|
||||
};
|
||||
|
||||
[mxSession canEnableE2EByDefaultInNewRoomWithUsers:invite success:^(BOOL canEnableE2E) {
|
||||
[mxSession riot_canEnableE2EByDefaultInNewRoomWithUsers:invite success:^(BOOL canEnableE2E) {
|
||||
|
||||
MXRoomCreationParameters *roomCreationParameters = [MXRoomCreationParameters new];
|
||||
roomCreationParameters.visibility = kMXRoomDirectoryVisibilityPrivate;
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
6
Riot/Assets/Images.xcassets/Secrets/Setup/Contents.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
23
Riot/Assets/Images.xcassets/Secrets/Setup/secrets_setup_key.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "secrets_setup_key.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "secrets_setup_key@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "secrets_setup_key@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
Riot/Assets/Images.xcassets/Secrets/Setup/secrets_setup_key.imageset/secrets_setup_key.png
vendored
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
Riot/Assets/Images.xcassets/Secrets/Setup/secrets_setup_key.imageset/secrets_setup_key@2x.png
vendored
Normal file
After Width: | Height: | Size: 7.3 KiB |
BIN
Riot/Assets/Images.xcassets/Secrets/Setup/secrets_setup_key.imageset/secrets_setup_key@3x.png
vendored
Normal file
After Width: | Height: | Size: 3.8 KiB |
23
Riot/Assets/Images.xcassets/Secrets/Setup/secrets_setup_passphrase.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "secrets_setup_passphrase.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "secrets_setup_passphrase@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "secrets_setup_passphrase@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 3.9 KiB |
|
@ -381,7 +381,7 @@
|
|||
"room_details_advanced_enable_e2e_encryption" = "Включване на шифроване (не може да се изключи в последствие!)";
|
||||
"room_details_advanced_e2e_encryption_enabled" = "Шифроването е включено в тази стая";
|
||||
"room_details_advanced_e2e_encryption_disabled" = "Шифроването не е включено в тази стая.";
|
||||
"room_details_advanced_e2e_encryption_blacklist_unverified_devices" = "Шифроване само за потвърдени устройства";
|
||||
"room_details_advanced_e2e_encryption_blacklist_unverified_devices" = "Шифроване само за потвърдени сесии";
|
||||
"room_details_advanced_e2e_encryption_prompt_message" = "Шифроване от край до край е експериментално и може да не е надеждно.\n\nВсе още не трябва да се доверявате на това, че ще защити Вашите данни.\n\nУстройства все още не могат да разшифроват история от преди присъединяването към стая.\n\nВеднъж включено, шифроването в стаята не може да бъде изключено (за сега).\n\nШифровани съобщения не са видими за клиенти, които все още не поддържат шифроване.";
|
||||
"room_details_fail_to_update_avatar" = "Неуспешно обновяване на снимката на стаята";
|
||||
"room_details_fail_to_update_room_name" = "Неуспешно обновяване на името на стаята";
|
||||
|
@ -457,8 +457,8 @@
|
|||
// Call
|
||||
"call_incoming_voice_prompt" = "Входящо гласово повикване от %@";
|
||||
"call_incoming_video_prompt" = "Входящо видео повикване от %@";
|
||||
"call_incoming_voice" = "Входящо повикване...";
|
||||
"call_incoming_video" = "Входящо видео повикване...";
|
||||
"call_incoming_voice" = "Входящо повикване…";
|
||||
"call_incoming_video" = "Входящо видео повикване…";
|
||||
"call_already_displayed" = "В момента тече разговор.";
|
||||
"call_jitsi_error" = "Неуспешно присъединяване към групов разговор.";
|
||||
// No VoIP support
|
||||
|
@ -477,7 +477,7 @@
|
|||
"google_analytics_use_prompt" = "Искате ли да помогнете за подобрението на %@ като анонимно изпращате съобщения за грешки и данни за използване?";
|
||||
// Crypto
|
||||
"e2e_enabling_on_app_update" = "Riot поддържа шифроване от край до край, но за да го включите трябва да влезете в профила си отново.\n\nМоже да го направите сега или по-късно от настройките на приложението.";
|
||||
"e2e_need_log_in_again" = "Трябва да влезете обратно в профила си, за да се създадат ключове за шифроване от край до край за това устройство и да се изпрати публичния ключ към Home сървъра.\nТова е еднократно. Извинете за неудобството.";
|
||||
"e2e_need_log_in_again" = "Трябва да влезете обратно в профила си, за да се създадат ключове за шифроване от-край-до-край за тази сесия и да се изпрати публичния ключ към Home сървъра.\nТова е еднократно. Извинете за неудобството.";
|
||||
"bug_crash_report_description" = "Моля, опишете какво правихте преди да възникне грешката:";
|
||||
"bug_report_logs_description" = "За да се диагностицират проблемите, логовете от този клиент ще бъдат изпратени с този доклад за грешки. Ако предпочитате да изпратите само текста по-горе, моля, премахнете отметката:";
|
||||
// Widget
|
||||
|
@ -499,9 +499,9 @@
|
|||
"share_extension_failed_to_encrypt" = "Неуспешно изпращане. Проверете ключовете за шифроване за тази стая в главното приложение";
|
||||
// Room key request dialog
|
||||
"e2e_room_key_request_title" = "Заявка за ключ за шифроване";
|
||||
"e2e_room_key_request_message_new_device" = "Добавихте ново устройство '%@', което изисква ключове за шифроване.";
|
||||
"e2e_room_key_request_message" = "Вашето непотвърдено устройство '%@' изисква ключове за шифроване.";
|
||||
"e2e_room_key_request_start_verification" = "Започни потвърждението...";
|
||||
"e2e_room_key_request_message_new_device" = "Добавихте нова сесия '%@', която изисква ключове за шифроване.";
|
||||
"e2e_room_key_request_message" = "Вашата непотвърдена сесия '%@' изисква ключове за шифроване.";
|
||||
"e2e_room_key_request_start_verification" = "Започни потвърждението…";
|
||||
"e2e_room_key_request_share_without_verifying" = "Сподели без потвърждение";
|
||||
"e2e_room_key_request_ignore_request" = "Игнорирай поканата";
|
||||
"room_warning_about_encryption" = "Шифроване от край до край е в бета версия и може да не е надеждно.\n\nВсе още не трябва да се доверявате на това, че ще защити Вашите данни.\n\nУстройства все още не могат да разшифроват история от преди присъединяването към стая.\n\nШифровани съобщения не са видими за клиенти, които все още не поддържат шифроване.";
|
||||
|
@ -532,10 +532,10 @@
|
|||
"deactivate_account_password_alert_title" = "Деактивиране на акаунт";
|
||||
"deactivate_account_password_alert_message" = "За да продължите, моля въведете паролата си";
|
||||
"event_formatter_rerequest_keys_part1_link" = "Изисквай повторно ключове за шифроване";
|
||||
"event_formatter_rerequest_keys_part2" = " от другите ми устройства.";
|
||||
"event_formatter_rerequest_keys_part2" = " от другите ми сесии.";
|
||||
// Re-request confirmation dialog
|
||||
"rerequest_keys_alert_title" = "Заявката е изпратена";
|
||||
"rerequest_keys_alert_message" = "Моля стартирайте Riot на друго устройство можещо да разшифрова съобщението, за да може то да изпрати ключовете до това устройство.";
|
||||
"rerequest_keys_alert_message" = "Моля стартирайте Riot на друго устройство можещо да разшифрова съобщението, за да може то да изпрати ключовете до тази сесия.";
|
||||
"room_message_reply_to_placeholder" = "Изпрати отговор (нешифрован)…";
|
||||
"encrypted_room_message_reply_to_placeholder" = "Изпрати шифрован отговор…";
|
||||
"room_message_reply_to_short_placeholder" = "Изпрати отговор…";
|
||||
|
@ -684,27 +684,27 @@
|
|||
"settings_labs_message_reaction" = "Реагирай на съобщения с емоджи";
|
||||
"settings_key_backup_button_connect" = "Свържи сесията към резервно копие на ключове";
|
||||
"key_backup_setup_intro_setup_connect_action_with_existing_backup" = "Свържи устройството към резервно копие на ключове";
|
||||
"key_backup_recover_connent_banner_subtitle" = "Свържи устройството към резервно копие на ключове";
|
||||
"key_backup_recover_connent_banner_subtitle" = "Свържи сесията към резервно копие на ключове";
|
||||
// MARK: - Device Verification
|
||||
"device_verification_title" = "Потвърждение на устройство";
|
||||
"device_verification_security_advice" = "За максимална сигурност, препоръчваме да правите това на живо или използвайки друг защитен начин за комуникация";
|
||||
"device_verification_cancelled" = "Отсрещната страна отказа потвърждението.";
|
||||
"device_verification_cancelled_by_me" = "Потвърждението беше отказано. Причина: %@";
|
||||
"device_verification_error_cannot_load_device" = "Неуспешно зареждане на информация за устройството.";
|
||||
"device_verification_error_cannot_load_device" = "Неуспешно зареждане на информация за сесията.";
|
||||
// Mark: Incoming
|
||||
"device_verification_incoming_title" = "Входяща заявка за потвърждение";
|
||||
"device_verification_incoming_description_1" = "Потвърдете това устройство за да го маркирате като доверено. Доверяването на устройства на партньори Ви дава допълнително спокойствие когато използвате шифроване от-край-до-край.";
|
||||
"device_verification_incoming_description_2" = "Потвърждаването на устройството ще го маркира като доверено и ще маркира Вашето като доверено при партньора.";
|
||||
"device_verification_incoming_description_1" = "Потвърдете тази сесия за да я маркирате като доверена. Доверяването на сесии на партньори ви дава допълнително спокойствие когато използвате шифроване от-край-до-край.";
|
||||
"device_verification_incoming_description_2" = "Потвърждаването на сесията ще я маркира като доверена и ще маркира вашето като доверена при партньора.";
|
||||
// MARK: Start
|
||||
"device_verification_start_title" = "Потвърждение чрез сравняване на кратък текст";
|
||||
"device_verification_start_wait_partner" = "Изчакване на партньора да приеме...";
|
||||
"device_verification_start_wait_partner" = "Изчакване на партньора да приеме…";
|
||||
"device_verification_start_use_legacy" = "Не се показва нищо? Засега не всички клиенти поддържат интерактивно потвърждение. Използвайте стария метод за потвърждение.";
|
||||
"device_verification_start_verify_button" = "Започни потвърждение";
|
||||
"device_verification_start_use_legacy_action" = "Потвърди по стария метод";
|
||||
// MARK: Verify
|
||||
"device_verification_verify_title_emoji" = "Потвърдете това устройство като се уверите че следните емоджита се повяват на екрана на партньора";
|
||||
"device_verification_verify_title_number" = "Потвърдете това устройство като се уверите че следните числа се повяват на екрана на партньора";
|
||||
"device_verification_verify_wait_partner" = "Изчакване на потвърждение от партньора...";
|
||||
"device_verification_verify_wait_partner" = "Изчакване на потвърждение от партньора…";
|
||||
// MARK: Verified
|
||||
"device_verification_verified_title" = "Потвърдено!";
|
||||
"device_verification_verified_description_1" = "Успешно потвърдихте това устройство.";
|
||||
|
@ -927,7 +927,7 @@
|
|||
"accessibility_checkbox_label" = "отметка";
|
||||
"settings_labs_dm_key_verification" = "Потвърждение на ключ чрез директно съобщение";
|
||||
"settings_labs_cross_signing" = "Кръстосано-подписване";
|
||||
"widget_picker_manage_integrations" = "Управление на интеграциите...";
|
||||
"widget_picker_manage_integrations" = "Управление на интеграциите…";
|
||||
// Room widget permissions
|
||||
"room_widget_permission_title" = "Зареждане на приспособление";
|
||||
"room_widget_permission_creator_info_title" = "Приспособлението беше добавено от:";
|
||||
|
@ -966,3 +966,151 @@
|
|||
"room_member_power_level_short_admin" = "Админ";
|
||||
"room_member_power_level_short_moderator" = "Модератор";
|
||||
"room_member_power_level_short_custom" = "Собствен";
|
||||
"room_participants_action_security_status_complete_security" = "Завършете сигурността";
|
||||
"security_settings_crypto_sessions_description" = "Доверете се на сесии за да им дадете достъп до съобщенията шифровани от-край-до-край. Ако не разпознавате дадена сесия, променете паролата си и нулирайте паролата за съобщения използваща се за резервни копия на съобщенията.";
|
||||
"security_settings_backup" = "РЕЗЕРВНИ КОПИЯ НА СЪОБЩЕНИЯ";
|
||||
"security_settings_crosssigning" = "КРЪСТОСАНО-ПОДПИСВАНЕ";
|
||||
"security_settings_crosssigning_info_not_bootstrapped" = "Кръстосаното-подписване все още не е настроено.";
|
||||
"security_settings_crosssigning_info_exists" = "Профилът ви има идентичност за кръстосано-подписване, но все още не е доверена от тази сесия. Завършете сигурността за тази сесия.";
|
||||
"security_settings_crosssigning_info_trusted" = "Кръстосаното-подписване е включено. Можете да се доверявате на други потребители и други сесии на базата на кръстосано-подписване, но не можете да подписвате от тази сесия, защото нямате частни ключове за кръстосано подписване. Завършете сигурността за тази сесия.";
|
||||
"security_settings_crosssigning_info_ok" = "Кръстосаното-подписване е включено.";
|
||||
"security_settings_crosssigning_bootstrap" = "Настрой кръстосано-подписване";
|
||||
"security_settings_crosssigning_reset" = "Нулирай кръстосаното-подписване";
|
||||
"security_settings_crosssigning_complete_security" = "Завърши сигурността";
|
||||
"security_settings_cryptography" = "КРИПТОГРАФИЯ";
|
||||
"security_settings_export_keys_manually" = "Експортирай ключовете ръчно";
|
||||
"security_settings_advanced" = "РАЗШИРЕНИ";
|
||||
"security_settings_blacklist_unverified_devices" = "Никога не изпращай съобщения към недоверени сесии";
|
||||
"security_settings_blacklist_unverified_devices_description" = "Потвърждаване на всички потребителски сесии за да бъдат маркирани като доверени и да се изпращат съобщения до тях.";
|
||||
"security_settings_complete_security_alert_title" = "Завършване на сигурността";
|
||||
"security_settings_complete_security_alert_message" = "Първо трябва да завършите сигурността на текущата си сесия.";
|
||||
"security_settings_coming_soon" = "Извинете. Това действие все още не е налично в Riot-iOS. Моля използвайте друг Matrix клиент за да го настройте. Riot-iOS ще го използва след това.";
|
||||
// Manage session
|
||||
"manage_session_title" = "Управление на сесията";
|
||||
"manage_session_info" = "СЕСИЙНА ИНФОРМАЦИЯ";
|
||||
"manage_session_name" = "Име на сесия";
|
||||
"manage_session_trusted" = "Доверена от вас";
|
||||
"manage_session_not_trusted" = "Недоверена";
|
||||
"manage_session_sign_out" = "Излез от тази сесия";
|
||||
// Recover from private key
|
||||
"key_backup_recover_from_private_key_info" = "Възстановяване на резервно копие…";
|
||||
// MARK: - Device Verification
|
||||
"key_verification_other_session_title" = "Потвърждаване на сесия";
|
||||
"key_verification_new_session_title" = "Потвърждаване на новата ви сесия";
|
||||
"key_verification_this_session_title" = "Потвърждаване на тази сесия";
|
||||
"key_verification_user_title" = "Потвърждение";
|
||||
"device_verification_security_advice_emoji" = "Сравнете уникалните емоджита, подсигурявайки, че се появяват в същата последователност.";
|
||||
"device_verification_security_advice_number" = "Сравнете числата, подсигурявайки, че се появяват в същата последователност.";
|
||||
// New login
|
||||
"device_verification_self_verify_alert_title" = "Нов вход. Вие ли бяхте?";
|
||||
"device_verification_self_verify_alert_message" = "Потвърдете входа достъпващ профила ви: %@";
|
||||
"device_verification_self_verify_alert_validate_action" = "Потвърди";
|
||||
"device_verification_self_verify_start_verify_action" = "Започни потвърждение";
|
||||
"device_verification_self_verify_start_information" = "Използвайте тази сесия за да потвърдите новата, давайки й достъп до шифрованите съобщения.";
|
||||
"device_verification_self_verify_start_waiting" = "Изчакване…";
|
||||
"key_verification_self_verify_current_session_alert_title" = "Потвърждение на тази сесия";
|
||||
"key_verification_self_verify_current_session_alert_message" = "Други потребители може да не й се доверяват.";
|
||||
"key_verification_self_verify_current_session_alert_validate_action" = "Потвърди";
|
||||
"key_verification_self_verify_unverified_sessions_alert_title" = "Преглед на входовете";
|
||||
"key_verification_self_verify_unverified_sessions_alert_message" = "Потвърдете всичките си сесии за да подсигурите че профила и съобщенията ви са защитени.";
|
||||
"key_verification_self_verify_unverified_sessions_alert_validate_action" = "Прегледай";
|
||||
"device_verification_self_verify_wait_title" = "Завършване на сигурността";
|
||||
"device_verification_self_verify_wait_new_sign_in_title" = "Потвърждение на вход";
|
||||
"device_verification_self_verify_wait_information" = "Потвърдете тази сесия от някоя от другите ви сесии, така че да й дадете достъп до шифрованите съобщения.\n\nИзползвайте най-новия Riot на другите си устройства:";
|
||||
"device_verification_self_verify_wait_additional_information" = "или друг Matrix клиент поддържащ кръстосано-подписване";
|
||||
"device_verification_self_verify_wait_recover_secrets_without_passphrase" = "Използвай ключ за възстановяване";
|
||||
"device_verification_self_verify_wait_recover_secrets_with_passphrase" = "Използвай парола или ключ за възстановяване";
|
||||
"device_verification_self_verify_wait_recover_secrets_additional_information" = "Ако не можете да достъпите съществуваща сесия";
|
||||
"key_verification_verify_sas_title_emoji" = "Сравнение на емоджита";
|
||||
"key_verification_verify_sas_title_number" = "Сравнение на числа";
|
||||
"key_verification_verify_sas_cancel_action" = "Не съвпадат";
|
||||
"key_verification_verify_sas_validate_action" = "Съвпадат";
|
||||
"key_verification_verify_sas_additional_information" = "За най-добра сигурност, използвайте друг доверен начин за комуникация или направете това на живо.";
|
||||
"key_verification_manually_verify_device_title" = "Ръчно потвърждение чрез текстово съобщение";
|
||||
"key_verification_manually_verify_device_instruction" = "Потвърдете, чрез сравнение на следното в Настройки в другата ви сесия:";
|
||||
"key_verification_manually_verify_device_name_title" = "Име на сесия";
|
||||
"key_verification_manually_verify_device_id_title" = "Идентификатор на сесия";
|
||||
"key_verification_manually_verify_device_key_title" = "Ключ на сесия";
|
||||
"key_verification_manually_verify_device_additional_information" = "Ако не съвпадат, сигурността на комуникацията ви може да е компрометирана.";
|
||||
"key_verification_manually_verify_device_validate_action" = "Потвърди";
|
||||
"key_verification_verified_new_session_title" = "Новата сесия беше потвърдена!";
|
||||
"key_verification_verified_other_session_information" = "Вече може да четете защитени съобщения в другата сесия, а други потребители ще знаят да й се доверяват.";
|
||||
"key_verification_verified_new_session_information" = "Вече може да четете защитени съобщения на новото си устройство, а други потребители ще знаят да му се доверяват.";
|
||||
"key_verification_verified_this_session_information" = "Вече може да четете защитени съобщения на това устройство, а други потребители ще знаят да му се доверяват.";
|
||||
"key_verification_verified_user_information" = "Съобщенията с този потребител са шифровани от-край-до-край и не могат да бъдат прочетени от трети страни.";
|
||||
"key_verification_bootstrap_not_setup_title" = "Грешка";
|
||||
"key_verification_bootstrap_not_setup_message" = "Първо трябва да настройте кръстосано-подписване.";
|
||||
"key_verification_tile_request_incoming_title" = "Заявка за потвърждение";
|
||||
"key_verification_tile_request_outgoing_title" = "Потвърждението беше изпратено";
|
||||
"key_verification_tile_request_status_data_loading" = "Зареждане на данни…";
|
||||
"key_verification_tile_request_status_waiting" = "Изчакване…";
|
||||
"key_verification_tile_request_status_expired" = "Изтекло";
|
||||
"key_verification_tile_request_status_cancelled_by_me" = "Отказахте";
|
||||
"key_verification_tile_request_status_cancelled" = "%@ отказа";
|
||||
"key_verification_tile_request_status_accepted" = "Приехте";
|
||||
"key_verification_tile_request_incoming_approval_accept" = "Приеми";
|
||||
"key_verification_tile_request_incoming_approval_decline" = "Откажи";
|
||||
"key_verification_tile_conclusion_done_title" = "Потвърдено";
|
||||
"key_verification_tile_conclusion_warning_title" = "Недоверен вход";
|
||||
"key_verification_incoming_request_incoming_alert_message" = "%@ иска да извърши потвърждение";
|
||||
"key_verification_verify_qr_code_title" = "Потвърждение чрез сканиране";
|
||||
"key_verification_verify_qr_code_information" = "Сканирайте този код за да потвърдите по сигурен начин един друг.";
|
||||
"key_verification_verify_qr_code_information_other_device" = "Сканирайте кода по-долу за да потвърдите:";
|
||||
"key_verification_verify_qr_code_emoji_information" = "Потвърждение чрез сравняване на уникални емоджита.";
|
||||
"key_verification_verify_qr_code_scan_code_action" = "Сканирайте кода им";
|
||||
"key_verification_verify_qr_code_cannot_scan_action" = "Не можете да сканирате?";
|
||||
"key_verification_verify_qr_code_start_emoji_action" = "Потвърждение чрез емоджи";
|
||||
"key_verification_verify_qr_code_other_scan_my_code_title" = "Другия потребител сканира ли успешно QR кода?";
|
||||
"key_verification_verify_qr_code_scan_other_code_success_title" = "Кодът беше валидиран!";
|
||||
"key_verification_verify_qr_code_scan_other_code_success_message" = "QR кодът беше валидиран успешно.";
|
||||
// Scanning
|
||||
"key_verification_scan_confirmation_scanning_title" = "Почти приключихте! Изчакване на потвърждение…";
|
||||
"key_verification_scan_confirmation_scanning_user_waiting_other" = "Изчакване на %@…";
|
||||
"key_verification_scan_confirmation_scanning_device_waiting_other" = "Изчакване на другото устройство…";
|
||||
// Scanned
|
||||
"key_verification_scan_confirmation_scanned_title" = "Почти приключихте!";
|
||||
"key_verification_scan_confirmation_scanned_user_information" = "Показва ли се същия щит при %@?";
|
||||
"key_verification_scan_confirmation_scanned_device_information" = "Показва ли се същия щит на другото устройство?";
|
||||
"user_verification_start_verify_action" = "Започнете потвърждение";
|
||||
"user_verification_start_information_part1" = "За допълнителна сигурност, потвърдете ";
|
||||
"user_verification_start_information_part2" = " чрез проверяване на еднократен код на двете устройства.";
|
||||
"user_verification_start_waiting_partner" = "Изчакване на %@…";
|
||||
"user_verification_start_additional_information" = "За да е сигурно, направете това на живо или чрез използване на друг начин за комуникация.";
|
||||
"user_verification_sessions_list_user_trust_level_trusted_title" = "Доверено";
|
||||
"user_verification_sessions_list_user_trust_level_warning_title" = "Внимание";
|
||||
"user_verification_sessions_list_user_trust_level_unknown_title" = "Непознато";
|
||||
"user_verification_sessions_list_information" = "Съобщенията с този потребител в тази стая са шифровани от-край-до-край и не могат да бъдат прочетени от трети страни.";
|
||||
"user_verification_sessions_list_table_title" = "Сесии";
|
||||
"user_verification_sessions_list_session_trusted" = "Доверена";
|
||||
"user_verification_sessions_list_session_untrusted" = "Недоверена";
|
||||
"user_verification_session_details_trusted_title" = "Доверена";
|
||||
"user_verification_session_details_untrusted_title" = "Недоверена";
|
||||
"user_verification_session_details_information_trusted_current_user" = "Тази сесия е доверена за сигурна комуникация, защото сте я потвърдили:";
|
||||
"user_verification_session_details_information_trusted_other_user_part1" = "Тази сесия е доверена за сигурна комуникация, защото ";
|
||||
"user_verification_session_details_information_trusted_other_user_part2" = " я е потвърдил:";
|
||||
"user_verification_session_details_information_untrusted_current_user" = "Потвърдете тази сесия за да я маркирате като доверена и да й дадете достъп до шифрованите съобщения:";
|
||||
"user_verification_session_details_information_untrusted_other_user" = " влезе използвайки нова сесия:";
|
||||
"user_verification_session_details_additional_information_untrusted_other_user" = "Докато този потребител се довери на тази сесия, съобщенията изпратени от и към нея ще бъдат маркирани с предупреждения. Друго решение е да я потвърдите ръчно.";
|
||||
"user_verification_session_details_additional_information_untrusted_current_user" = "Ако не сте се вписвали в тази сесия, профилът ви може да е бил компрометиран.";
|
||||
"user_verification_session_details_verify_action_current_user" = "Потвърди интерактивно";
|
||||
"user_verification_session_details_verify_action_current_user_manually" = "Потвърди ръчно чрез текстово съобщение";
|
||||
"user_verification_session_details_verify_action_other_user" = "Потвърди ръчно";
|
||||
"secrets_recovery_with_passphrase_title" = "Парола за възстановяване";
|
||||
"secrets_recovery_with_passphrase_information_default" = "Достъпете защитената история на съобщенията и идентичността си за кръстосано-подписване (за потвърждение на други сесии), чрез въвеждане на паролата за възстановяване.";
|
||||
"secrets_recovery_with_passphrase_information_verify_device" = "Използвайте паролата за възстановяване за да потвърдите това устройство.";
|
||||
"secrets_recovery_with_passphrase_passphrase_title" = "Въвеждане";
|
||||
"secrets_recovery_with_passphrase_passphrase_placeholder" = "Въведете паролата за възстановяване";
|
||||
"secrets_recovery_with_passphrase_recover_action" = "Използвай парола";
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part1" = "Не знаете паролата си за възстановяване? Можете да ";
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part2" = "използвате ключа за възстановяване";
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part3" = ".";
|
||||
"secrets_recovery_with_passphrase_invalid_passphrase_title" = "Неуспешен достъп до секретното складиране";
|
||||
"secrets_recovery_with_passphrase_invalid_passphrase_message" = "Потвърдете, че сте въвели правилната парола за възстановяване.";
|
||||
"secrets_recovery_with_key_title" = "Ключ за възстановяване";
|
||||
"secrets_recovery_with_key_information_default" = "Достъпете защитената история на съобщенията и самоличността за кръстосано-подписване (за потвърждение на други сесии), чрез въвеждане на ключа за възстановяване.";
|
||||
"secrets_recovery_with_key_information_verify_device" = "Използвайте ключа за възстановяване за потвърждение на това устройство.";
|
||||
"secrets_recovery_with_key_recovery_key_title" = "Въвеждане";
|
||||
"secrets_recovery_with_key_recovery_key_placeholder" = "Въвеждане на ключ за възстановяване";
|
||||
"secrets_recovery_with_key_recover_action" = "Използвай ключа";
|
||||
"secrets_recovery_with_key_invalid_recovery_key_title" = "Неуспешно достъпване на секретното складиране";
|
||||
"secrets_recovery_with_key_invalid_recovery_key_message" = "Потвърдете, че сте въвели правилния ключ за възстановяване.";
|
||||
|
|
|
@ -961,7 +961,7 @@
|
|||
"key_verification_tile_request_status_waiting" = "Warten…";
|
||||
"key_verification_tile_request_status_expired" = "Abgelaufen";
|
||||
"key_verification_tile_request_status_cancelled_by_me" = "Du hast abgebrochen";
|
||||
"key_verification_tile_request_status_cancelled" = "%s brach ab";
|
||||
"key_verification_tile_request_status_cancelled" = "%@ brach ab";
|
||||
"key_verification_tile_request_status_accepted" = "Du hast akzeptiert";
|
||||
"key_verification_tile_request_incoming_approval_accept" = "Akzeptieren";
|
||||
"key_verification_tile_request_incoming_approval_decline" = "Ablehnen";
|
||||
|
|
|
@ -919,6 +919,25 @@
|
|||
"rerequest_keys_alert_title" = "Request Sent";
|
||||
"rerequest_keys_alert_message" = "Please launch Riot on another device that can decrypt the message so it can send the keys to this session.";
|
||||
|
||||
// MARK: Secure Key backup setup
|
||||
|
||||
// Intro
|
||||
|
||||
"secure_key_backup_setup_intro_title" = "Secure Backup";
|
||||
"secure_key_backup_setup_intro_info" = "Safeguard against losing access to encrypted messages & data by backing up encryption keys on your server.";
|
||||
|
||||
"secure_key_backup_setup_intro_use_security_key_title" = "Use a Security Key";
|
||||
"secure_key_backup_setup_intro_use_security_key_info" = "Generate a security key to store somewhere safe like a password manager or a safe.";
|
||||
|
||||
"secure_key_backup_setup_intro_use_security_passphrase_title" = "Use a Security Passphrase";
|
||||
"secure_key_backup_setup_intro_use_security_passphrase_info" = "Enter a secret phrase only you know, and generate a key for backup.";
|
||||
|
||||
// Cancel
|
||||
|
||||
"secure_key_backup_setup_cancel_alert_title" = "Are your sure?";
|
||||
"secure_key_backup_setup_cancel_alert_message" = "If you cancel now, you may lose encrypted messages & data if you lose access to your logins.\n\nYou can also set up Secure Backup & manage your keys in Settings.";
|
||||
|
||||
|
||||
// MARK: Key backup setup
|
||||
|
||||
"key_backup_setup_title" = "Key Backup";
|
||||
|
@ -1342,3 +1361,31 @@
|
|||
|
||||
"secrets_recovery_with_key_invalid_recovery_key_title" = "Unable to access secret storage";
|
||||
"secrets_recovery_with_key_invalid_recovery_key_message" = "Please verify that you entered the correct recovery key.";
|
||||
|
||||
// MARK: - Secrets set up
|
||||
|
||||
// Recovery Key
|
||||
|
||||
"secrets_setup_recovery_key_title" = "Save your Security Key";
|
||||
"secrets_setup_recovery_key_information" = "Store your Recovery Key somewhere safe. It can be used to unlock your encrypted messages & data.";
|
||||
"secrets_setup_recovery_key_loading" = "Loading…";
|
||||
"secrets_setup_recovery_key_export_action" = "Save";
|
||||
"secrets_setup_recovery_key_done_action" = "Done";
|
||||
|
||||
"secrets_setup_recovery_key_storage_alert_title" = "Keep it safe";
|
||||
"secrets_setup_recovery_key_storage_alert_message" = "✓ Print it and store it somewhere safe\n✓ Save it on a USB key or backup drive\n✓ Copy it to your personal cloud storage";
|
||||
|
||||
// Recovery passphrase
|
||||
|
||||
"secrets_setup_recovery_passphrase_title" = "Set a Security Phrase";
|
||||
"secrets_setup_recovery_passphrase_information" = "Enter a security phrase only you know, used to secure secrets on your server.";
|
||||
"secrets_setup_recovery_passphrase_additional_information" = "Don't use your account password.";
|
||||
"secrets_setup_recovery_passphrase_validate_action" = "Done";
|
||||
|
||||
"secrets_setup_recovery_passphrase_confirm_information" = "Enter your Security Phrase again to confirm it.";
|
||||
"secrets_setup_recovery_passphrase_confirm_passphrase_title" = "Confirm";
|
||||
"secrets_setup_recovery_passphrase_confirm_passphrase_placeholder" = "Confirm passphrase";
|
||||
|
||||
"key_backup_setup_passphrase_confirm_passphrase_valid" = "Great!";
|
||||
"key_backup_setup_passphrase_confirm_passphrase_invalid" = "Passphrase doesn’t match";
|
||||
|
||||
|
|
|
@ -1086,3 +1086,25 @@
|
|||
"key_verification_verify_qr_code_emoji_information" = "Egiaztatu emoji bakanak konparatuz.";
|
||||
"key_verification_verify_qr_code_start_emoji_action" = "Egiaztatu emoji bidez";
|
||||
"user_verification_session_details_verify_action_current_user_manually" = "Egiaztatu eskuz testu bidez";
|
||||
"device_verification_self_verify_wait_recover_secrets_without_passphrase" = "Erabili berreskuratze gakoa";
|
||||
"device_verification_self_verify_wait_recover_secrets_with_passphrase" = "Erabili berreskuratze pasa-esaldia edo gakoa";
|
||||
"device_verification_self_verify_wait_recover_secrets_additional_information" = "Ezin baduzu dagoen saio bat erabili";
|
||||
"secrets_recovery_with_passphrase_title" = "Berreskuratze pasa-esaldia";
|
||||
"secrets_recovery_with_passphrase_information_default" = "Atzitu zure mezu seguruen historiala eta zeharkako sinatzerako identitatea beste saioak egiaztatzeko zure berreskuratze pasa-esaldia sartuz.";
|
||||
"secrets_recovery_with_passphrase_information_verify_device" = "Erabili berreskuratze pasa-esaldia gailu hau egiaztatzeko.";
|
||||
"secrets_recovery_with_passphrase_passphrase_title" = "Sartu";
|
||||
"secrets_recovery_with_passphrase_passphrase_placeholder" = "Sartu berreskuratze pasa-esaldia";
|
||||
"secrets_recovery_with_passphrase_recover_action" = "Erabili pasa-esaldia";
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part1" = "Ez duzu berreskuratze pasa-esaldia gogoratzen? ";
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part2" = "erabili berreskuratze-gakoa";
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part3" = ".";
|
||||
"secrets_recovery_with_passphrase_invalid_passphrase_title" = "Ezin izan da biltegi sekretua atzitu";
|
||||
"secrets_recovery_with_passphrase_invalid_passphrase_message" = "Egiaztatu berreskuratze pasa-esaldi zuzena sartu duzula.";
|
||||
"secrets_recovery_with_key_title" = "Berreskuratze gakoa";
|
||||
"secrets_recovery_with_key_information_default" = "Atzitu zure mezu seguruen historiala eta zeharkako sinatzerako identitatea beste saioak egiaztatzeko zure berreskuratze gakoa sartuz.";
|
||||
"secrets_recovery_with_key_information_verify_device" = "Erabili berreskuratze gakoa gailu hau egiaztatzeko.";
|
||||
"secrets_recovery_with_key_recovery_key_title" = "Sartu";
|
||||
"secrets_recovery_with_key_recovery_key_placeholder" = "Sartu berreskuratze-gakoa";
|
||||
"secrets_recovery_with_key_recover_action" = "Erabili gakoa";
|
||||
"secrets_recovery_with_key_invalid_recovery_key_title" = "Ezin izan da biltegi sekretua atzitu";
|
||||
"secrets_recovery_with_key_invalid_recovery_key_message" = "Egiaztatu berreskuratze gako zuzena sartu duzula.";
|
||||
|
|
|
@ -1101,3 +1101,25 @@
|
|||
"key_verification_manually_verify_device_additional_information" = "S’ils ne correspondent pas, la sécurité de vos communications est peut-être compromise.";
|
||||
"key_verification_manually_verify_device_validate_action" = "Vérifier";
|
||||
"user_verification_session_details_verify_action_current_user_manually" = "Vérifier manuellement avec un texte";
|
||||
"device_verification_self_verify_wait_recover_secrets_without_passphrase" = "Utiliser la clé de récupération";
|
||||
"device_verification_self_verify_wait_recover_secrets_with_passphrase" = "Utiliser la phrase secrète ou la clé de récupération";
|
||||
"device_verification_self_verify_wait_recover_secrets_additional_information" = "Si vous ne pouvez pas accéder à une session existante";
|
||||
"secrets_recovery_with_passphrase_title" = "Phrase secrète de récupération";
|
||||
"secrets_recovery_with_passphrase_information_default" = "Accédez à l’historique de vos messages sécurisés et à votre identité de signature croisée pour vérifier d’autres sessions en saisissant votre phrase secrète de récupération.";
|
||||
"secrets_recovery_with_passphrase_information_verify_device" = "Utilisez votre phrase secrète de récupération pour vérifier cet appareil.";
|
||||
"secrets_recovery_with_passphrase_passphrase_title" = "Saisir";
|
||||
"secrets_recovery_with_passphrase_passphrase_placeholder" = "Saisir la phrase secrète de récupération";
|
||||
"secrets_recovery_with_passphrase_recover_action" = "Utiliser la phrase secrète";
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part1" = "Vous ne connaissez pas votre phrase secrète de récupération ? Vous pouvez ";
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part2" = "utiliser votre clé de récupération";
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part3" = ".";
|
||||
"secrets_recovery_with_passphrase_invalid_passphrase_title" = "Impossible d’accéder au coffre secret";
|
||||
"secrets_recovery_with_passphrase_invalid_passphrase_message" = "Vérifiez que vous avez saisi la bonne phrase secrète de récupération.";
|
||||
"secrets_recovery_with_key_title" = "Clé de récupération";
|
||||
"secrets_recovery_with_key_information_default" = "Accédez à l’historique de vos messages sécurisés et à votre identité de signature croisée pour vérifier d’autres sessions en renseignant votre clé de récupération.";
|
||||
"secrets_recovery_with_key_information_verify_device" = "Utilisez votre clé de récupération pour vérifier cet appareil.";
|
||||
"secrets_recovery_with_key_recovery_key_title" = "Saisir";
|
||||
"secrets_recovery_with_key_recovery_key_placeholder" = "Saisir la clé de récupération";
|
||||
"secrets_recovery_with_key_recover_action" = "Utiliser la clé";
|
||||
"secrets_recovery_with_key_invalid_recovery_key_title" = "Impossible d’accéder au coffre secret";
|
||||
"secrets_recovery_with_key_invalid_recovery_key_message" = "Vérifiez que vous avez saisi la bonne clé de récupération.";
|
||||
|
|
|
@ -1103,3 +1103,25 @@
|
|||
"key_verification_manually_verify_device_additional_information" = "Ha nem egyeznek akkor a kommunikációtok biztonsága veszélyben lehet.";
|
||||
"key_verification_manually_verify_device_validate_action" = "Ellenőriz";
|
||||
"user_verification_session_details_verify_action_current_user_manually" = "Manuális szöveges ellenőrzés";
|
||||
"device_verification_self_verify_wait_recover_secrets_without_passphrase" = "Használd a Visszaállítási Kulcsot";
|
||||
"device_verification_self_verify_wait_recover_secrets_with_passphrase" = "Használd a Visszaállítási Jelmondatot vagy Kulcsot";
|
||||
"device_verification_self_verify_wait_recover_secrets_additional_information" = "Ha nem érsz el létező munkamenetet";
|
||||
"secrets_recovery_with_passphrase_title" = "Visszaállítási Jelmondat";
|
||||
"secrets_recovery_with_passphrase_information_default" = "A visszaállítási jelmondat megadásával hozzáférhetsz a titkosított üzeneteidhez és az eszközök közötti aláírásnál használt személyazonosságodhoz hogy más munkameneteket ellenőrizhess.";
|
||||
"secrets_recovery_with_passphrase_information_verify_device" = "Használd a visszaállítási jelmondatot az eszköz ellenőrzésére.";
|
||||
"secrets_recovery_with_passphrase_passphrase_title" = "Bevitel";
|
||||
"secrets_recovery_with_passphrase_passphrase_placeholder" = "Visszaállítási jelmondat megadása";
|
||||
"secrets_recovery_with_passphrase_recover_action" = "Használd a jelmondatot";
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part1" = "Nem emlékszel a visszaállítási jelmondatodra? Használhatod a ";
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part2" = "visszaállítási kulcs használata";
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part3" = ".";
|
||||
"secrets_recovery_with_passphrase_invalid_passphrase_title" = "A biztonsági tárolót nem sikerült elérni";
|
||||
"secrets_recovery_with_passphrase_invalid_passphrase_message" = "Kérlek ellenőrizd, hogy a visszaállítási jelmondatot helyesen írtad be.";
|
||||
"secrets_recovery_with_key_title" = "Visszaállítási Kulcs";
|
||||
"secrets_recovery_with_key_information_default" = "A visszaállítási kulcs megadásával hozzáférhetsz a biztonságos üzeneteidhez és az eszközök közötti hitelesítéshez használt személyazonosságodhoz, hogy más munkameneteket hitelesíthess.";
|
||||
"secrets_recovery_with_key_information_verify_device" = "Használd a visszaállítási kulcsot az eszköz ellenőrzésére.";
|
||||
"secrets_recovery_with_key_recovery_key_title" = "Bevitel";
|
||||
"secrets_recovery_with_key_recovery_key_placeholder" = "Visszaállítási Kulcs megadása";
|
||||
"secrets_recovery_with_key_recover_action" = "Használd a kulcsot";
|
||||
"secrets_recovery_with_key_invalid_recovery_key_title" = "A biztonsági tárolót nem sikerült elérni";
|
||||
"secrets_recovery_with_key_invalid_recovery_key_message" = "Kérlek ellenőrizd, hogy a visszaállítási kulcsot helyesen írtad be.";
|
||||
|
|
|
@ -1075,3 +1075,25 @@
|
|||
"key_verification_manually_verify_device_additional_information" = "Se non corrispondono, la sicurezza delle tue comunicazioni potrebbe essere compromessa.";
|
||||
"key_verification_manually_verify_device_validate_action" = "Verifica";
|
||||
"user_verification_session_details_verify_action_current_user_manually" = "Verifica manualmente con testo";
|
||||
"device_verification_self_verify_wait_recover_secrets_without_passphrase" = "Usa chiave di recupero";
|
||||
"device_verification_self_verify_wait_recover_secrets_with_passphrase" = "Usa password o chiave di recupero";
|
||||
"device_verification_self_verify_wait_recover_secrets_additional_information" = "Se non puoi accedere a una sessione esistente";
|
||||
"secrets_recovery_with_passphrase_title" = "Password di recupero";
|
||||
"secrets_recovery_with_passphrase_information_default" = "Accedi alla tua cronologia dei messaggi sicuri e all'identità della firma incrociata per verificare altre sessioni inserendo la password di recupero.";
|
||||
"secrets_recovery_with_passphrase_information_verify_device" = "Usa la password di recupero per verificare questo dispositivo.";
|
||||
"secrets_recovery_with_passphrase_passphrase_title" = "Inserisci";
|
||||
"secrets_recovery_with_passphrase_passphrase_placeholder" = "Inserisci la password di recupero";
|
||||
"secrets_recovery_with_passphrase_recover_action" = "Usa password";
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part1" = "Non conosci la tua password di recupero? Puoi ";
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part2" = "usare la chiave di recupero";
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part3" = ".";
|
||||
"secrets_recovery_with_passphrase_invalid_passphrase_title" = "Impossibile accedere all'archivio segreto";
|
||||
"secrets_recovery_with_passphrase_invalid_passphrase_message" = "Controlla di avere inserito la password di recupero corretta.";
|
||||
"secrets_recovery_with_key_title" = "Chiave di recupero";
|
||||
"secrets_recovery_with_key_information_default" = "Accedi alla tua cronologia dei messaggi sicuri e all'identità della firma incrociata per verificare altre sessioni inserendo la chiave di recupero.";
|
||||
"secrets_recovery_with_key_information_verify_device" = "Usa la chiave di recupero per verificare questo dispositivo.";
|
||||
"secrets_recovery_with_key_recovery_key_title" = "Inserisci";
|
||||
"secrets_recovery_with_key_recovery_key_placeholder" = "Inserisci chiave di recupero";
|
||||
"secrets_recovery_with_key_recover_action" = "Usa chiave";
|
||||
"secrets_recovery_with_key_invalid_recovery_key_title" = "Impossibile accedere all'archivio segreto";
|
||||
"secrets_recovery_with_key_invalid_recovery_key_message" = "Controlla di avere inserito la chiave di recupero corretta.";
|
||||
|
|
|
@ -1091,3 +1091,17 @@
|
|||
"key_verification_manually_verify_device_additional_information" = "Nëse s’përputhen, siguria e komunikimeve tuaja mund të jetë komprometuar.";
|
||||
"key_verification_manually_verify_device_validate_action" = "Verifikoje";
|
||||
"user_verification_session_details_verify_action_current_user_manually" = "Verifikojeni Dorazi përmes Teksti";
|
||||
"device_verification_self_verify_wait_recover_secrets_without_passphrase" = "Përdor Kyç Rimarrjesh";
|
||||
"device_verification_self_verify_wait_recover_secrets_with_passphrase" = "Përdor Frazëkalim ose Kyç Rimarrjesh";
|
||||
"device_verification_self_verify_wait_recover_secrets_additional_information" = "Nëse s’hyni dot në një sesion ekzistues";
|
||||
"secrets_recovery_with_passphrase_title" = "Frazëkalim Rimarrjesh";
|
||||
"secrets_recovery_with_passphrase_information_default" = "Hyni në historikun tuaj të mesazheve të sigurt dhe përdorni identitetin tuaj “cross-signing” për të verifikuar sesione të tjerë duke dhënë frazëkalimin tuaj të rimarrjeve.";
|
||||
"secrets_recovery_with_passphrase_information_verify_device" = "Që të verifikoni këtë pajisje, përdorni Frazëkalimin tuaj të Rimarrjeve.";
|
||||
"secrets_recovery_with_passphrase_passphrase_placeholder" = "Jepni Frazëkalim Rimarrjesh";
|
||||
"secrets_recovery_with_passphrase_recover_action" = "Përdor Frazëkalim";
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part1" = "S’e din frazëkalimin tuaj të rimarrjeve? Mundeni të ";
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part2" = "përdorni kyçin tuaj të rimarrjeve";
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part3" = ".";
|
||||
"secrets_recovery_with_passphrase_invalid_passphrase_title" = "S’arrihet të hyhet në depo të fshehtë";
|
||||
"secrets_recovery_with_passphrase_invalid_passphrase_message" = "Ju lutemi, verifikoni që keni dhënë frazëkalimin e saktë të rimarrjeve.";
|
||||
"secrets_recovery_with_key_title" = "Kyç Rimarrjesh";
|
||||
|
|
|
@ -298,7 +298,7 @@
|
|||
"settings_password_updated" = "您的密码已经更新";
|
||||
"settings_crypto_device_name" = "会话名称: ";
|
||||
"settings_crypto_device_id" = "\n会话ID: ";
|
||||
"settings_crypto_device_key" = "\n会话密钥:\n";
|
||||
"settings_crypto_device_key" = "\n会话密钥:\n";
|
||||
"settings_crypto_export" = "导出密钥";
|
||||
"settings_crypto_blacklist_unverified_devices" = "只加密到已验证的会话";
|
||||
// Room Details
|
||||
|
@ -841,7 +841,7 @@
|
|||
"key_backup_recover_connent_banner_subtitle" = "关联此会话到“密钥备份”";
|
||||
// MARK: - Device Verification
|
||||
"device_verification_title" = "验证会话";
|
||||
"key_verification_user_title" = "验证用户";
|
||||
"key_verification_user_title" = "验证它们";
|
||||
"device_verification_security_advice" = "为了最大化安全性,我们建议你们当面或者使用其他可信任的通讯手段来进行此操作";
|
||||
"device_verification_cancelled" = "另一方取消了验证。";
|
||||
"device_verification_cancelled_by_me" = "此验证被取消。原因:%@";
|
||||
|
@ -976,7 +976,7 @@
|
|||
"user_verification_sessions_list_session_trusted" = "已信任";
|
||||
"user_verification_sessions_list_session_untrusted" = "不信任";
|
||||
"user_verification_session_details_trusted_title" = "已信任";
|
||||
"user_verification_session_details_untrusted_title" = "警告";
|
||||
"user_verification_session_details_untrusted_title" = "不受信任";
|
||||
"user_verification_session_details_information_trusted_current_user" = "此会话已被信任用于安全消息,因为你已经验证过它:";
|
||||
"user_verification_session_details_information_trusted_other_user_part1" = "此会话已被信任用于安全消息,因为: ";
|
||||
"user_verification_session_details_information_trusted_other_user_part2" = " 已验证过它:";
|
||||
|
@ -984,7 +984,7 @@
|
|||
"user_verification_session_details_information_untrusted_other_user" = " 用新会话登录:";
|
||||
"user_verification_session_details_additional_information_untrusted_other_user" = "在此用户信任这个会话之前,发往和收到它的消息会有警告标签。或者,你可以手动验证它。";
|
||||
"user_verification_session_details_additional_information_untrusted_current_user" = "如果你没有登录到这个会话,你的账号可能在被盗用。";
|
||||
"user_verification_session_details_verify_action_current_user" = "验证";
|
||||
"user_verification_session_details_verify_action_current_user" = "交互式验证";
|
||||
"user_verification_session_details_verify_action_other_user" = "手动验证";
|
||||
// MARK: Clients
|
||||
"client_desktop_name" = "Riot 桌面版";
|
||||
|
@ -1000,3 +1000,100 @@
|
|||
"security_settings_crosssigning" = "交叉签名";
|
||||
"security_settings_crosssigning_info_not_bootstrapped" = "交叉签名还没有被设置。";
|
||||
"security_settings_crosssigning_info_exists" = "您的帐户有一个交叉签名身份,但是还没有被这个会话信任。完全安全的会话。";
|
||||
"skip" = "跳过";
|
||||
"room_member_power_level_custom_in" = "自定义(%@) 到%@";
|
||||
"room_member_power_level_short_custom" = "自定义";
|
||||
"security_settings_crosssigning_info_trusted" = "已启用交叉签名。您可以基于交叉签名信任其他用户和其他会话,但不能从此会话交叉签名,因为它没有交叉签名私钥。此会话完全安全。";
|
||||
"security_settings_crosssigning_info_ok" = "交叉签名还没有被设置。";
|
||||
"security_settings_crosssigning_bootstrap" = "引导交叉签名";
|
||||
"security_settings_crosssigning_reset" = "重置交叉签名";
|
||||
"security_settings_crosssigning_complete_security" = "完整安全性";
|
||||
"security_settings_cryptography" = "加密";
|
||||
"security_settings_complete_security_alert_title" = "绝对安全";
|
||||
"security_settings_complete_security_alert_message" = "您应该先完成当前会话的安全防护。";
|
||||
"security_settings_coming_soon" = "抱歉的。Riot-iOS上尚未提供此操作。请使用其他Matrix客户端进行设置。Riot-iOS将使用它。";
|
||||
// Recover from private key
|
||||
"key_backup_recover_from_private_key_info" = "备份恢复中…";
|
||||
// MARK: - Device Verification
|
||||
"key_verification_other_session_title" = "验证会话";
|
||||
"key_verification_new_session_title" = "验证你的新会话";
|
||||
"key_verification_this_session_title" = "验证此会话";
|
||||
"device_verification_security_advice_emoji" = "比较独特的emoji,确保它们以相同的顺序出现。";
|
||||
"device_verification_security_advice_number" = "比较数字,确保它们以相同的顺序出现。";
|
||||
// New login
|
||||
"device_verification_self_verify_alert_title" = "新登录。这是你吗?";
|
||||
"device_verification_self_verify_alert_message" = "验证访问您的帐户的新登录名:%@";
|
||||
"device_verification_self_verify_alert_validate_action" = "验证";
|
||||
"device_verification_self_verify_start_verify_action" = "开始验证";
|
||||
"device_verification_self_verify_start_information" = "使用此会话验证您的新会话,并授予其访问加密信息的权限。";
|
||||
"device_verification_self_verify_start_waiting" = "等待中……";
|
||||
"key_verification_self_verify_current_session_alert_title" = "验证此会话";
|
||||
"key_verification_self_verify_current_session_alert_message" = "其他用户可能不信任它。";
|
||||
"key_verification_self_verify_current_session_alert_validate_action" = "验证";
|
||||
"key_verification_self_verify_unverified_sessions_alert_title" = "查看您的登陆位置";
|
||||
"key_verification_self_verify_unverified_sessions_alert_message" = "验证您的所有会话以确保您的帐户和消息的安全。";
|
||||
"key_verification_self_verify_unverified_sessions_alert_validate_action" = "检查";
|
||||
"device_verification_self_verify_wait_title" = "绝对安全";
|
||||
"device_verification_self_verify_wait_new_sign_in_title" = "验证此登录名";
|
||||
"device_verification_self_verify_wait_information" = "从您的其他会话之一验证此会话,并授予其对加密信息的访问权限。\n\n在您的其他设备上使用最新的Riot:";
|
||||
"device_verification_self_verify_wait_additional_information" = "或另一个支持交叉签名的Matrix客户端";
|
||||
"device_verification_self_verify_wait_recover_secrets_without_passphrase" = "使用恢复密钥";
|
||||
"device_verification_self_verify_wait_recover_secrets_with_passphrase" = "使用恢复密码或密钥";
|
||||
"device_verification_self_verify_wait_recover_secrets_additional_information" = "如果您无法访问现有会话";
|
||||
"key_verification_verify_sas_title_emoji" = "比较emoji";
|
||||
"key_verification_verify_sas_title_number" = "比较数字";
|
||||
"key_verification_verify_sas_cancel_action" = "它们不相配";
|
||||
"key_verification_verify_sas_validate_action" = "它们相配";
|
||||
"key_verification_verify_sas_additional_information" = "为了最终的安全,请使用另一种可信的通信方式或亲自执行此操作。";
|
||||
"key_verification_manually_verify_device_title" = "通过文本手动验证";
|
||||
"key_verification_manually_verify_device_instruction" = "通过将以下设置与其他会话中的用户设置进行比较来确认:";
|
||||
"key_verification_manually_verify_device_name_title" = "会话名称";
|
||||
"key_verification_manually_verify_device_id_title" = "会话 ID";
|
||||
"key_verification_manually_verify_device_key_title" = "会话密钥";
|
||||
"key_verification_manually_verify_device_additional_information" = "如果它们不匹配,您的通信安全可能会受到威胁。";
|
||||
"key_verification_manually_verify_device_validate_action" = "验证";
|
||||
"key_verification_verified_new_session_title" = "新会话已验证!";
|
||||
"key_verification_verified_other_session_information" = "您现在可以阅读其他会话上的安全信息,其他用户将知道他们可以信任它。";
|
||||
"key_verification_verified_new_session_information" = "您现在可以在新设备上阅读安全信息,其他用户将知道他们可以信任它。";
|
||||
"key_verification_verified_this_session_information" = "您现在可以在此设备上阅读安全信息,其他用户将知道他们可以信任它。";
|
||||
"key_verification_verified_user_information" = "此用户的信息是端到端加密的,第三方无法读取。";
|
||||
"key_verification_bootstrap_not_setup_title" = "错误";
|
||||
"key_verification_bootstrap_not_setup_message" = "您需要先启动交叉签名。";
|
||||
"key_verification_verify_qr_code_title" = "通过扫描进行验证";
|
||||
"key_verification_verify_qr_code_information" = "扫描代码以安全地相互验证。";
|
||||
"key_verification_verify_qr_code_information_other_device" = "扫描以下代码以验证:";
|
||||
"key_verification_verify_qr_code_emoji_information" = "通过比较唯一的表情符号进行验证。";
|
||||
"key_verification_verify_qr_code_scan_code_action" = "扫描他们的代码";
|
||||
"key_verification_verify_qr_code_cannot_scan_action" = "不能扫描吗?";
|
||||
"key_verification_verify_qr_code_start_emoji_action" = "通过表情符号验证";
|
||||
"key_verification_verify_qr_code_other_scan_my_code_title" = "其他用户是否成功扫描了二维码?";
|
||||
"key_verification_verify_qr_code_scan_other_code_success_title" = "代码已验证!";
|
||||
"key_verification_verify_qr_code_scan_other_code_success_message" = "二维码已成功验证。";
|
||||
// Scanning
|
||||
"key_verification_scan_confirmation_scanning_title" = "快到了!\n正在等待确认…";
|
||||
"key_verification_scan_confirmation_scanning_user_waiting_other" = "等待中%@…";
|
||||
"key_verification_scan_confirmation_scanning_device_waiting_other" = "正在等待其他设备…";
|
||||
// Scanned
|
||||
"key_verification_scan_confirmation_scanned_title" = "快到了!";
|
||||
"key_verification_scan_confirmation_scanned_user_information" = "是否%@显示相同的盾牌?";
|
||||
"key_verification_scan_confirmation_scanned_device_information" = "另一台设备是否显示相同的盾牌?";
|
||||
"user_verification_session_details_verify_action_current_user_manually" = "通过文本手动验证";
|
||||
"secrets_recovery_with_passphrase_title" = "恢复密码";
|
||||
"secrets_recovery_with_passphrase_information_default" = "通过输入恢复密码,访问您的安全信息历史记录和交叉签名身份,以验证其他会话。";
|
||||
"secrets_recovery_with_passphrase_information_verify_device" = "使用您的恢复密码验证此设备。";
|
||||
"secrets_recovery_with_passphrase_passphrase_title" = "输入";
|
||||
"secrets_recovery_with_passphrase_passphrase_placeholder" = "输入恢复密码";
|
||||
"secrets_recovery_with_passphrase_recover_action" = "使用密码短语";
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part1" = "忘记了您的恢复密码?您可以 ";
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part2" = "使用您的恢复密钥";
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part3" = ".";
|
||||
"secrets_recovery_with_passphrase_invalid_passphrase_title" = "无法访问机密存储";
|
||||
"secrets_recovery_with_passphrase_invalid_passphrase_message" = "请验证您输入的恢复密码是否正确。";
|
||||
"secrets_recovery_with_key_title" = "恢复密钥";
|
||||
"secrets_recovery_with_key_information_default" = "通过输入恢复密钥访问安全信息历史记录和交叉签名身份,以验证其他会话。";
|
||||
"secrets_recovery_with_key_information_verify_device" = "使用您的恢复密码验证此设备。";
|
||||
"secrets_recovery_with_key_recovery_key_title" = "输入";
|
||||
"secrets_recovery_with_key_recovery_key_placeholder" = "输入恢复密钥";
|
||||
"secrets_recovery_with_key_recover_action" = "使用密钥";
|
||||
"secrets_recovery_with_key_invalid_recovery_key_title" = "无法访问机密存储";
|
||||
"secrets_recovery_with_key_invalid_recovery_key_message" = "请验证您输入的恢复密钥是否正确。";
|
||||
|
|
|
@ -25,4 +25,22 @@
|
|||
*/
|
||||
- (NSUInteger)riot_missedDiscussionsCount;
|
||||
|
||||
/**
|
||||
Check if E2E by default is welcomed on the user's HS.
|
||||
The default value is YES.
|
||||
|
||||
HS admins can disable it in /.well-known/matrix/client by returning:
|
||||
"im.vector.riot.e2ee": {
|
||||
"default": false
|
||||
}
|
||||
*/
|
||||
- (BOOL)riot_isE2EByDefaultEnabledByHSAdmin;
|
||||
|
||||
/**
|
||||
Riot version of [MXSession canEnableE2EByDefaultInNewRoomWithUsers:]
|
||||
*/
|
||||
- (MXHTTPOperation*)riot_canEnableE2EByDefaultInNewRoomWithUsers:(NSArray<NSString*>*)userIds
|
||||
success:(void (^)(BOOL canEnableE2E))success
|
||||
failure:(void (^)(NSError *error))failure;
|
||||
|
||||
@end
|
||||
|
|
|
@ -49,4 +49,33 @@
|
|||
return missedDiscussionsCount;
|
||||
}
|
||||
|
||||
- (BOOL)riot_isE2EByDefaultEnabledByHSAdmin
|
||||
{
|
||||
BOOL isE2EByDefaultEnabledByHSAdmin = YES;
|
||||
|
||||
MXWellKnown *wellKnown = self.homeserverWellknown;
|
||||
|
||||
if (wellKnown.JSONDictionary[@"im.vector.riot.e2ee"][@"default"])
|
||||
{
|
||||
MXJSONModelSetBoolean(isE2EByDefaultEnabledByHSAdmin, wellKnown.JSONDictionary[@"im.vector.riot.e2ee"][@"default"]);
|
||||
}
|
||||
|
||||
return isE2EByDefaultEnabledByHSAdmin;
|
||||
}
|
||||
|
||||
- (MXHTTPOperation*)riot_canEnableE2EByDefaultInNewRoomWithUsers:(NSArray<NSString*>*)userIds
|
||||
success:(void (^)(BOOL canEnableE2E))success
|
||||
failure:(void (^)(NSError *error))failure;
|
||||
{
|
||||
if (self.riot_isE2EByDefaultEnabledByHSAdmin)
|
||||
{
|
||||
return [self canEnableE2EByDefaultInNewRoomWithUsers:userIds success:success failure:failure];
|
||||
}
|
||||
else
|
||||
{
|
||||
success(NO);
|
||||
return [MXHTTPOperation new];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -47,5 +47,13 @@ extension UIImage {
|
|||
let tintedImage: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
|
||||
UIGraphicsEndImageContext()
|
||||
return tintedImage
|
||||
}
|
||||
}
|
||||
|
||||
func vc_withAlpha(_ alpha: CGFloat) -> UIImage? {
|
||||
UIGraphicsBeginImageContextWithOptions(size, false, scale)
|
||||
draw(at: .zero, blendMode: .normal, alpha: alpha)
|
||||
let newImage = UIGraphicsGetImageFromCurrentImageContext()
|
||||
UIGraphicsEndImageContext()
|
||||
return newImage
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,6 +106,8 @@ internal enum Asset {
|
|||
internal static let searchIcon = ImageAsset(name: "search_icon")
|
||||
internal static let secretsRecoveryKey = ImageAsset(name: "secrets_recovery_key")
|
||||
internal static let secretsRecoveryPassphrase = ImageAsset(name: "secrets_recovery_passphrase")
|
||||
internal static let secretsSetupKey = ImageAsset(name: "secrets_setup_key")
|
||||
internal static let secretsSetupPassphrase = ImageAsset(name: "secrets_setup_passphrase")
|
||||
internal static let removeIconPink = ImageAsset(name: "remove_icon_pink")
|
||||
internal static let settingsIcon = ImageAsset(name: "settings_icon")
|
||||
internal static let tabFavourites = ImageAsset(name: "tab_favourites")
|
||||
|
|
|
@ -137,6 +137,21 @@ internal enum StoryboardScene {
|
|||
|
||||
internal static let initialScene = InitialSceneType<Riot.SecretsRecoveryWithPassphraseViewController>(storyboard: SecretsRecoveryWithPassphraseViewController.self)
|
||||
}
|
||||
internal enum SecretsSetupRecoveryKeyViewController: StoryboardType {
|
||||
internal static let storyboardName = "SecretsSetupRecoveryKeyViewController"
|
||||
|
||||
internal static let initialScene = InitialSceneType<Riot.SecretsSetupRecoveryKeyViewController>(storyboard: SecretsSetupRecoveryKeyViewController.self)
|
||||
}
|
||||
internal enum SecretsSetupRecoveryPassphraseViewController: StoryboardType {
|
||||
internal static let storyboardName = "SecretsSetupRecoveryPassphraseViewController"
|
||||
|
||||
internal static let initialScene = InitialSceneType<Riot.SecretsSetupRecoveryPassphraseViewController>(storyboard: SecretsSetupRecoveryPassphraseViewController.self)
|
||||
}
|
||||
internal enum SecureKeyBackupSetupIntroViewController: StoryboardType {
|
||||
internal static let storyboardName = "SecureKeyBackupSetupIntroViewController"
|
||||
|
||||
internal static let initialScene = InitialSceneType<Riot.SecureKeyBackupSetupIntroViewController>(storyboard: SecureKeyBackupSetupIntroViewController.self)
|
||||
}
|
||||
internal enum ServiceTermsModalScreenViewController: StoryboardType {
|
||||
internal static let storyboardName = "ServiceTermsModalScreenViewController"
|
||||
|
||||
|
|
|
@ -1394,7 +1394,7 @@ internal enum VectorL10n {
|
|||
internal static var keyBackupRecoverTitle: String {
|
||||
return VectorL10n.tr("Vector", "key_backup_recover_title")
|
||||
}
|
||||
/// Start using Key Backup
|
||||
/// Safeguard against losing access to encrypted messages & data
|
||||
internal static var keyBackupSetupBannerSubtitle: String {
|
||||
return VectorL10n.tr("Vector", "key_backup_setup_banner_subtitle")
|
||||
}
|
||||
|
@ -3002,6 +3002,94 @@ internal enum VectorL10n {
|
|||
internal static var secretsRecoveryWithPassphraseTitle: String {
|
||||
return VectorL10n.tr("Vector", "secrets_recovery_with_passphrase_title")
|
||||
}
|
||||
/// Done
|
||||
internal static var secretsSetupRecoveryKeyDoneAction: String {
|
||||
return VectorL10n.tr("Vector", "secrets_setup_recovery_key_done_action")
|
||||
}
|
||||
/// Save
|
||||
internal static var secretsSetupRecoveryKeyExportAction: String {
|
||||
return VectorL10n.tr("Vector", "secrets_setup_recovery_key_export_action")
|
||||
}
|
||||
/// Store your Recovery Key somewhere safe. It can be used to unlock your encrypted messages & data.
|
||||
internal static var secretsSetupRecoveryKeyInformation: String {
|
||||
return VectorL10n.tr("Vector", "secrets_setup_recovery_key_information")
|
||||
}
|
||||
/// Loading…
|
||||
internal static var secretsSetupRecoveryKeyLoading: String {
|
||||
return VectorL10n.tr("Vector", "secrets_setup_recovery_key_loading")
|
||||
}
|
||||
/// ✓ Print it and store it somewhere safe\n✓ Save it on a USB key or backup drive\n✓ Copy it to your personal cloud storage
|
||||
internal static var secretsSetupRecoveryKeyStorageAlertMessage: String {
|
||||
return VectorL10n.tr("Vector", "secrets_setup_recovery_key_storage_alert_message")
|
||||
}
|
||||
/// Keep it safe
|
||||
internal static var secretsSetupRecoveryKeyStorageAlertTitle: String {
|
||||
return VectorL10n.tr("Vector", "secrets_setup_recovery_key_storage_alert_title")
|
||||
}
|
||||
/// Save your Security Key
|
||||
internal static var secretsSetupRecoveryKeyTitle: String {
|
||||
return VectorL10n.tr("Vector", "secrets_setup_recovery_key_title")
|
||||
}
|
||||
/// Don't use your account password.
|
||||
internal static var secretsSetupRecoveryPassphraseAdditionalInformation: String {
|
||||
return VectorL10n.tr("Vector", "secrets_setup_recovery_passphrase_additional_information")
|
||||
}
|
||||
/// Enter your Security Phrase again to confirm it.
|
||||
internal static var secretsSetupRecoveryPassphraseConfirmInformation: String {
|
||||
return VectorL10n.tr("Vector", "secrets_setup_recovery_passphrase_confirm_information")
|
||||
}
|
||||
/// Confirm passphrase
|
||||
internal static var secretsSetupRecoveryPassphraseConfirmPassphrasePlaceholder: String {
|
||||
return VectorL10n.tr("Vector", "secrets_setup_recovery_passphrase_confirm_passphrase_placeholder")
|
||||
}
|
||||
/// Confirm
|
||||
internal static var secretsSetupRecoveryPassphraseConfirmPassphraseTitle: String {
|
||||
return VectorL10n.tr("Vector", "secrets_setup_recovery_passphrase_confirm_passphrase_title")
|
||||
}
|
||||
/// Enter a security phrase only you know, used to secure secrets on your server.
|
||||
internal static var secretsSetupRecoveryPassphraseInformation: String {
|
||||
return VectorL10n.tr("Vector", "secrets_setup_recovery_passphrase_information")
|
||||
}
|
||||
/// Set a Security Phrase
|
||||
internal static var secretsSetupRecoveryPassphraseTitle: String {
|
||||
return VectorL10n.tr("Vector", "secrets_setup_recovery_passphrase_title")
|
||||
}
|
||||
/// Done
|
||||
internal static var secretsSetupRecoveryPassphraseValidateAction: String {
|
||||
return VectorL10n.tr("Vector", "secrets_setup_recovery_passphrase_validate_action")
|
||||
}
|
||||
/// If you cancel now, you may lose encrypted messages & data if you lose access to your logins.\n\nYou can also set up Secure Backup & manage your keys in Settings.
|
||||
internal static var secureKeyBackupSetupCancelAlertMessage: String {
|
||||
return VectorL10n.tr("Vector", "secure_key_backup_setup_cancel_alert_message")
|
||||
}
|
||||
/// Are your sure?
|
||||
internal static var secureKeyBackupSetupCancelAlertTitle: String {
|
||||
return VectorL10n.tr("Vector", "secure_key_backup_setup_cancel_alert_title")
|
||||
}
|
||||
/// Safe guard against losing access to encrypted messages & data by backing up encryption keys on your server.
|
||||
internal static var secureKeyBackupSetupIntroInfo: String {
|
||||
return VectorL10n.tr("Vector", "secure_key_backup_setup_intro_info")
|
||||
}
|
||||
/// Secure Backup
|
||||
internal static var secureKeyBackupSetupIntroTitle: String {
|
||||
return VectorL10n.tr("Vector", "secure_key_backup_setup_intro_title")
|
||||
}
|
||||
/// Generate a security key to store somewhere safe like a password manager or a safe.
|
||||
internal static var secureKeyBackupSetupIntroUseSecurityKeyInfo: String {
|
||||
return VectorL10n.tr("Vector", "secure_key_backup_setup_intro_use_security_key_info")
|
||||
}
|
||||
/// Use a Security Key
|
||||
internal static var secureKeyBackupSetupIntroUseSecurityKeyTitle: String {
|
||||
return VectorL10n.tr("Vector", "secure_key_backup_setup_intro_use_security_key_title")
|
||||
}
|
||||
/// Enter a secret phrase only you know, and generate a key for backup.
|
||||
internal static var secureKeyBackupSetupIntroUseSecurityPassphraseInfo: String {
|
||||
return VectorL10n.tr("Vector", "secure_key_backup_setup_intro_use_security_passphrase_info")
|
||||
}
|
||||
/// Use a Security Passphrase
|
||||
internal static var secureKeyBackupSetupIntroUseSecurityPassphraseTitle: String {
|
||||
return VectorL10n.tr("Vector", "secure_key_backup_setup_intro_use_security_passphrase_title")
|
||||
}
|
||||
/// ADVANCED
|
||||
internal static var securitySettingsAdvanced: String {
|
||||
return VectorL10n.tr("Vector", "security_settings_advanced")
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#import "AppDelegate.h"
|
||||
#import "Riot-Swift.h"
|
||||
#import "MXSession+Riot.h"
|
||||
|
||||
#import "AuthInputsView.h"
|
||||
#import "ForgotPasswordInputsView.h"
|
||||
|
@ -1154,32 +1155,42 @@
|
|||
case MXCrossSigningStateNotBootstrapped:
|
||||
{
|
||||
#ifdef NEW_CROSS_SIGNING_FLOW
|
||||
// Bootstrap cross-signing on user's account
|
||||
// We do it for both registration and new login as long as cross-signing does not exist yet
|
||||
if (self.authInputsView.password.length)
|
||||
// TODO: This is still not sure we want to disable the automatic cross-signing bootstrap
|
||||
// if the admin disabled e2e by default.
|
||||
// Do like riot-web for the moment
|
||||
if (session.riot_isE2EByDefaultEnabledByHSAdmin)
|
||||
#else
|
||||
if (0)
|
||||
#endif
|
||||
{
|
||||
NSLog(@"[AuthenticationVC] sessionStateDidChange: Bootstrap with password");
|
||||
|
||||
[session.crypto.crossSigning bootstrapWithPassword:self.authInputsView.password success:^{
|
||||
NSLog(@"[AuthenticationVC] sessionStateDidChange: Bootstrap succeeded");
|
||||
[self dismiss];
|
||||
} failure:^(NSError * _Nonnull error) {
|
||||
NSLog(@"[AuthenticationVC] sessionStateDidChange: Bootstrap failed. Error: %@", error);
|
||||
// Bootstrap cross-signing on user's account
|
||||
// We do it for both registration and new login as long as cross-signing does not exist yet
|
||||
if (self.authInputsView.password.length)
|
||||
{
|
||||
NSLog(@"[AuthenticationVC] sessionStateDidChange: Bootstrap with password");
|
||||
|
||||
[session.crypto.crossSigning bootstrapWithPassword:self.authInputsView.password success:^{
|
||||
NSLog(@"[AuthenticationVC] sessionStateDidChange: Bootstrap succeeded");
|
||||
[self dismiss];
|
||||
} failure:^(NSError * _Nonnull error) {
|
||||
NSLog(@"[AuthenticationVC] sessionStateDidChange: Bootstrap failed. Error: %@", error);
|
||||
[session.crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil];
|
||||
[self dismiss];
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"[AuthenticationVC] sessionStateDidChange: Do not know how to bootstrap cross-signing. Skip it.");
|
||||
|
||||
[session.crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil];
|
||||
[self dismiss];
|
||||
}];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"[AuthenticationVC] sessionStateDidChange: Do not know how to bootstrap cross-signing. Skip it.");
|
||||
|
||||
[session.crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil];
|
||||
[self dismiss];
|
||||
}
|
||||
#else
|
||||
[session.crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil];
|
||||
[self dismiss];
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case MXCrossSigningStateCrossSigningExists:
|
||||
|
|
|
@ -1058,7 +1058,7 @@
|
|||
|
||||
|
||||
// Create a new room
|
||||
[self.mainSession canEnableE2EByDefaultInNewRoomWithUsers:inviteArray success:^(BOOL canEnableE2E) {
|
||||
[self.mainSession riot_canEnableE2EByDefaultInNewRoomWithUsers:inviteArray success:^(BOOL canEnableE2E) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
MXRoomCreationParameters *roomCreationParameters = [MXRoomCreationParameters new];
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
Copyright 2020 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 UIKit
|
||||
import Reusable
|
||||
|
||||
final class SecureKeyBackupSetupIntroCell: UIView, NibOwnerLoadable, Themable {
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
private enum ImageAlpha {
|
||||
static let highlighted: CGFloat = 0.3
|
||||
}
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Outlets
|
||||
|
||||
@IBOutlet private weak var backgroundView: UIView!
|
||||
@IBOutlet private weak var imageView: UIImageView!
|
||||
@IBOutlet private weak var titleLabel: UILabel!
|
||||
@IBOutlet private weak var informationLabel: UILabel!
|
||||
@IBOutlet private weak var accessoryImageView: UIImageView!
|
||||
@IBOutlet private weak var separatorView: UIView!
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private var theme: Theme?
|
||||
|
||||
private var isHighlighted: Bool = false {
|
||||
didSet {
|
||||
self.updateView()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Public
|
||||
|
||||
var action: (() -> Void)?
|
||||
|
||||
// MARK: Setup
|
||||
|
||||
private func commonInit() {
|
||||
self.setupGestureRecognizer()
|
||||
|
||||
let accessoryTemplateImage = Asset.Images.disclosureIcon.image.withRenderingMode(.alwaysTemplate)
|
||||
self.accessoryImageView.image = accessoryTemplateImage
|
||||
self.accessoryImageView.highlightedImage = accessoryTemplateImage.vc_withAlpha(ImageAlpha.highlighted)
|
||||
}
|
||||
|
||||
convenience init() {
|
||||
self.init(frame: CGRect.zero)
|
||||
self.commonInit()
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
self.loadNibContent()
|
||||
self.commonInit()
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
self.loadNibContent()
|
||||
self.commonInit()
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func update(theme: Theme) {
|
||||
self.theme = theme
|
||||
|
||||
self.backgroundView.backgroundColor = theme.backgroundColor
|
||||
self.imageView.tintColor = theme.textPrimaryColor
|
||||
self.titleLabel.textColor = theme.tintColor
|
||||
self.informationLabel.textColor = theme.textSecondaryColor
|
||||
self.accessoryImageView.tintColor = theme.textSecondaryColor
|
||||
self.separatorView.backgroundColor = theme.lineBreakColor
|
||||
|
||||
self.updateView()
|
||||
}
|
||||
|
||||
func fill(title: String, information: String, image: UIImage) {
|
||||
let templateImage = image.withRenderingMode(.alwaysTemplate)
|
||||
|
||||
self.imageView.image = templateImage
|
||||
self.imageView.highlightedImage = templateImage.vc_withAlpha(ImageAlpha.highlighted)
|
||||
|
||||
self.titleLabel.text = title
|
||||
self.informationLabel.text = information
|
||||
|
||||
self.setupAccessibility(title: title, isEnabled: true)
|
||||
self.updateView()
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func setupAccessibility(title: String, isEnabled: Bool) {
|
||||
self.isAccessibilityElement = true
|
||||
self.accessibilityLabel = title
|
||||
self.accessibilityTraits = .button
|
||||
if !isEnabled {
|
||||
self.accessibilityTraits.insert(.notEnabled)
|
||||
}
|
||||
}
|
||||
|
||||
private func setupGestureRecognizer() {
|
||||
let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(buttonAction(_:)))
|
||||
gestureRecognizer.minimumPressDuration = 0
|
||||
self.addGestureRecognizer(gestureRecognizer)
|
||||
}
|
||||
|
||||
private func updateView() {
|
||||
|
||||
if let theme = self.theme {
|
||||
self.backgroundView.backgroundColor = self.isHighlighted ? theme.overlayBackgroundColor : theme.backgroundColor
|
||||
}
|
||||
|
||||
self.imageView.isHighlighted = self.isHighlighted
|
||||
self.accessoryImageView.isHighlighted = self.isHighlighted
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@objc private func buttonAction(_ sender: UILongPressGestureRecognizer) {
|
||||
|
||||
let isBackgroundViewTouched = sender.vc_isTouchingInside()
|
||||
|
||||
switch sender.state {
|
||||
case .began, .changed:
|
||||
self.isHighlighted = isBackgroundViewTouched
|
||||
case .ended:
|
||||
self.isHighlighted = false
|
||||
|
||||
if isBackgroundViewTouched {
|
||||
self.action?()
|
||||
}
|
||||
case .cancelled:
|
||||
self.isHighlighted = false
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina6_1" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="SecureKeyBackupSetupIntroCell" customModule="Riot" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="accessoryImageView" destination="N76-Fa-onz" id="nYX-r6-t7R"/>
|
||||
<outlet property="backgroundView" destination="WrK-Wq-nzz" id="kgB-Zb-g9N"/>
|
||||
<outlet property="imageView" destination="PfY-xb-Psn" id="qgq-7B-nSS"/>
|
||||
<outlet property="informationLabel" destination="q9X-wE-MwV" id="a4J-ZK-teU"/>
|
||||
<outlet property="separatorView" destination="eKS-Ze-zhB" id="TF5-27-XFD"/>
|
||||
<outlet property="titleLabel" destination="eGd-jn-myj" id="MyG-x1-33i"/>
|
||||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="iN0-l3-epB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="426" height="122"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="WrK-Wq-nzz">
|
||||
<rect key="frame" x="0.0" y="0.0" width="426" height="122"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="secrets_setup_key" translatesAutoresizingMaskIntoConstraints="NO" id="PfY-xb-Psn">
|
||||
<rect key="frame" x="19" y="18" width="24" height="24"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="PfY-xb-Psn" secondAttribute="height" multiplier="1:1" id="71S-sH-VTt"/>
|
||||
<constraint firstAttribute="width" constant="24" id="Shz-Df-UoM"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="252" text="Use a Security Key" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="eGd-jn-myj">
|
||||
<rect key="frame" x="63" y="20" width="317" height="19.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<color key="textColor" red="0.01176470588" green="0.70196078429999997" blue="0.50588235290000005" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Generate a security key to store somewhere safe like a password manager or a safe." lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="q9X-wE-MwV">
|
||||
<rect key="frame" x="63" y="49.5" width="317" height="52.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="12"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="disclosure_icon" translatesAutoresizingMaskIntoConstraints="NO" id="N76-Fa-onz">
|
||||
<rect key="frame" x="400" y="55" width="6" height="12"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="6" id="23d-HN-WiD"/>
|
||||
<constraint firstAttribute="height" constant="12" id="4Yt-I6-2YL"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="eKS-Ze-zhB" userLabel="separatorView">
|
||||
<rect key="frame" x="0.0" y="121" width="426" height="1"/>
|
||||
<color key="backgroundColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="1" id="5hw-tO-Dw9"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="PfY-xb-Psn" firstAttribute="centerY" secondItem="eGd-jn-myj" secondAttribute="centerY" id="3Ha-I2-24v"/>
|
||||
<constraint firstAttribute="trailing" secondItem="N76-Fa-onz" secondAttribute="trailing" constant="20" id="9C0-mv-gaL"/>
|
||||
<constraint firstAttribute="trailing" secondItem="eKS-Ze-zhB" secondAttribute="trailing" id="BlW-zS-HoC"/>
|
||||
<constraint firstItem="N76-Fa-onz" firstAttribute="leading" secondItem="eGd-jn-myj" secondAttribute="trailing" constant="20" id="CKw-l3-vdY"/>
|
||||
<constraint firstItem="PfY-xb-Psn" firstAttribute="leading" secondItem="WrK-Wq-nzz" secondAttribute="leading" constant="19" id="NXM-42-myZ"/>
|
||||
<constraint firstItem="q9X-wE-MwV" firstAttribute="leading" secondItem="eGd-jn-myj" secondAttribute="leading" id="Ovd-Xd-S7O"/>
|
||||
<constraint firstAttribute="bottom" secondItem="q9X-wE-MwV" secondAttribute="bottom" constant="20" id="S9M-i1-KQ6"/>
|
||||
<constraint firstItem="q9X-wE-MwV" firstAttribute="trailing" secondItem="eGd-jn-myj" secondAttribute="trailing" id="YU0-XX-vAU"/>
|
||||
<constraint firstItem="eGd-jn-myj" firstAttribute="top" secondItem="WrK-Wq-nzz" secondAttribute="top" constant="20" id="cAQ-R0-bco"/>
|
||||
<constraint firstAttribute="bottom" secondItem="eKS-Ze-zhB" secondAttribute="bottom" id="cnI-2n-T2c"/>
|
||||
<constraint firstItem="q9X-wE-MwV" firstAttribute="top" secondItem="eGd-jn-myj" secondAttribute="bottom" constant="10" id="kYI-mK-UC1"/>
|
||||
<constraint firstItem="N76-Fa-onz" firstAttribute="centerY" secondItem="WrK-Wq-nzz" secondAttribute="centerY" id="rG1-iI-v3T"/>
|
||||
<constraint firstItem="eKS-Ze-zhB" firstAttribute="leading" secondItem="WrK-Wq-nzz" secondAttribute="leading" id="raL-7N-TKN"/>
|
||||
<constraint firstItem="eGd-jn-myj" firstAttribute="leading" secondItem="PfY-xb-Psn" secondAttribute="trailing" constant="20" id="zi9-PT-A2O"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="WrK-Wq-nzz" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="dAF-lS-uGD"/>
|
||||
<constraint firstItem="WrK-Wq-nzz" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="fAW-fz-tYP"/>
|
||||
<constraint firstAttribute="bottom" secondItem="WrK-Wq-nzz" secondAttribute="bottom" id="lU3-Jc-aUe"/>
|
||||
<constraint firstAttribute="trailing" secondItem="WrK-Wq-nzz" secondAttribute="trailing" id="lUt-K8-wV9"/>
|
||||
</constraints>
|
||||
<nil key="simulatedTopBarMetrics"/>
|
||||
<nil key="simulatedBottomBarMetrics"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
|
||||
<point key="canvasLocation" x="146.37681159420291" y="-122.54464285714285"/>
|
||||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="disclosure_icon" width="6" height="12"/>
|
||||
<image name="secrets_setup_key" width="48" height="48"/>
|
||||
</resources>
|
||||
</document>
|
|
@ -0,0 +1,132 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="LSX-Vb-DIu">
|
||||
<device id="retina6_1" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Secure Key Backup Setup Intro View Controller-->
|
||||
<scene sceneID="srP-wo-sRp">
|
||||
<objects>
|
||||
<viewController extendedLayoutIncludesOpaqueBars="YES" automaticallyAdjustsScrollViewInsets="NO" id="LSX-Vb-DIu" customClass="SecureKeyBackupSetupIntroViewController" customModule="Riot" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="pmD-eJ-G3m">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="mvC-lc-ylT">
|
||||
<rect key="frame" x="0.0" y="44" width="414" height="852"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Fub-g4-o4o">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="391"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="79w-lw-B8z">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="391"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Safe guard against losing access to encrypted messages & data by backing up encryption keys on your server." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DZf-di-JcI">
|
||||
<rect key="frame" x="20" y="30" width="374" height="54"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="tul-b1-7gY">
|
||||
<rect key="frame" x="0.0" y="114" width="414" height="257"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="Jc9-fc-Vwh">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="257"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="d77-sQ-Uio">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="1"/>
|
||||
<color key="backgroundColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="1" id="Gwq-JQ-4Zj"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="RQF-pm-g37" customClass="SecureKeyBackupSetupIntroCell" customModule="Riot" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="1" width="414" height="128"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="128" placeholder="YES" id="dOF-Du-P3S"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Yps-bc-ruH" customClass="SecureKeyBackupSetupIntroCell" customModule="Riot" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="129" width="414" height="128"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="128" placeholder="YES" id="Gpk-nd-3G2"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="d77-sQ-Uio" firstAttribute="width" secondItem="Jc9-fc-Vwh" secondAttribute="width" id="S3Q-F0-nwW"/>
|
||||
<constraint firstItem="RQF-pm-g37" firstAttribute="width" secondItem="Jc9-fc-Vwh" secondAttribute="width" id="fZs-9s-jUW"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="Jc9-fc-Vwh" firstAttribute="top" secondItem="tul-b1-7gY" secondAttribute="top" id="1Vr-Y3-t2r"/>
|
||||
<constraint firstItem="Jc9-fc-Vwh" firstAttribute="leading" secondItem="tul-b1-7gY" secondAttribute="leading" id="4op-QY-3vL"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Jc9-fc-Vwh" secondAttribute="bottom" id="FqW-Rc-K1T"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Jc9-fc-Vwh" secondAttribute="trailing" id="QcB-wY-lCT"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="tul-b1-7gY" secondAttribute="trailing" id="TFD-iw-7y4"/>
|
||||
<constraint firstItem="tul-b1-7gY" firstAttribute="top" secondItem="DZf-di-JcI" secondAttribute="bottom" constant="30" id="Ury-rf-0xS"/>
|
||||
<constraint firstAttribute="trailing" secondItem="DZf-di-JcI" secondAttribute="trailing" constant="20" id="bS3-Gc-DyD"/>
|
||||
<constraint firstAttribute="width" priority="750" constant="500" id="fuc-5G-HCd"/>
|
||||
<constraint firstItem="tul-b1-7gY" firstAttribute="leading" secondItem="79w-lw-B8z" secondAttribute="leading" id="gYj-LZ-esB"/>
|
||||
<constraint firstItem="DZf-di-JcI" firstAttribute="leading" secondItem="79w-lw-B8z" secondAttribute="leading" constant="20" id="nPo-3g-WcD"/>
|
||||
<constraint firstAttribute="bottom" secondItem="tul-b1-7gY" secondAttribute="bottom" constant="20" id="qYa-0L-wrp"/>
|
||||
<constraint firstItem="DZf-di-JcI" firstAttribute="top" secondItem="79w-lw-B8z" secondAttribute="top" constant="30" id="t80-aS-JzH"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="79w-lw-B8z" firstAttribute="centerX" secondItem="Fub-g4-o4o" secondAttribute="centerX" id="5Az-52-cbQ"/>
|
||||
<constraint firstItem="79w-lw-B8z" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Fub-g4-o4o" secondAttribute="leading" id="Aei-Nr-Wzb"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="79w-lw-B8z" secondAttribute="trailing" id="CBG-M0-Uqd"/>
|
||||
<constraint firstAttribute="bottom" secondItem="79w-lw-B8z" secondAttribute="bottom" id="JbI-yr-iot"/>
|
||||
<constraint firstItem="79w-lw-B8z" firstAttribute="top" secondItem="Fub-g4-o4o" secondAttribute="top" id="s6B-HO-iVd"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="Fub-g4-o4o" secondAttribute="trailing" id="N9B-1U-3j7"/>
|
||||
<constraint firstItem="Fub-g4-o4o" firstAttribute="width" secondItem="mvC-lc-ylT" secondAttribute="width" id="NzH-5s-nuz"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Fub-g4-o4o" secondAttribute="bottom" id="gYj-V0-rlA"/>
|
||||
<constraint firstItem="Fub-g4-o4o" firstAttribute="leading" secondItem="mvC-lc-ylT" secondAttribute="leading" id="jHU-W6-8Ny"/>
|
||||
<constraint firstItem="Fub-g4-o4o" firstAttribute="top" secondItem="mvC-lc-ylT" secondAttribute="top" id="nFB-Af-IUw"/>
|
||||
</constraints>
|
||||
</scrollView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="JkH-9M-Qql" firstAttribute="top" secondItem="mvC-lc-ylT" secondAttribute="top" id="5Vc-aR-jAF"/>
|
||||
<constraint firstItem="mvC-lc-ylT" firstAttribute="leading" secondItem="JkH-9M-Qql" secondAttribute="leading" id="HBB-YL-5P5"/>
|
||||
<constraint firstAttribute="bottom" secondItem="mvC-lc-ylT" secondAttribute="bottom" id="dn5-CG-87P"/>
|
||||
<constraint firstItem="JkH-9M-Qql" firstAttribute="trailing" secondItem="mvC-lc-ylT" secondAttribute="trailing" id="xj4-xF-VEA"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="JkH-9M-Qql"/>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="informationLabel" destination="DZf-di-JcI" id="czR-MT-Ipb"/>
|
||||
<outlet property="secureKeyCell" destination="RQF-pm-g37" id="5dK-h1-N6t"/>
|
||||
<outlet property="securePassphraseCell" destination="Yps-bc-ruH" id="56B-9H-MOh"/>
|
||||
<outlet property="topSeparatorView" destination="d77-sQ-Uio" id="TPp-kq-cFq"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="WpU-UP-qtu" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-3772.4637681159425" y="-774.10714285714278"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
Copyright 2020 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 UIKit
|
||||
|
||||
protocol SecureKeyBackupSetupIntroViewControllerDelegate: class {
|
||||
func secureKeyBackupSetupIntroViewControllerDidTapUseKey(_ secureKeyBackupSetupIntroViewController: SecureKeyBackupSetupIntroViewController)
|
||||
func secureKeyBackupSetupIntroViewControllerDidTapUsePassphrase(_ secureKeyBackupSetupIntroViewController: SecureKeyBackupSetupIntroViewController)
|
||||
func secureKeyBackupSetupIntroViewControllerDidCancel(_ secureKeyBackupSetupIntroViewController: SecureKeyBackupSetupIntroViewController)
|
||||
}
|
||||
|
||||
@objcMembers
|
||||
final class SecureKeyBackupSetupIntroViewController: UIViewController {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Outlets
|
||||
|
||||
@IBOutlet private weak var informationLabel: UILabel!
|
||||
|
||||
@IBOutlet private weak var topSeparatorView: UIView!
|
||||
@IBOutlet private weak var secureKeyCell: SecureKeyBackupSetupIntroCell!
|
||||
@IBOutlet private weak var securePassphraseCell: SecureKeyBackupSetupIntroCell!
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private var theme: Theme!
|
||||
|
||||
// MARK: Public
|
||||
|
||||
weak var delegate: SecureKeyBackupSetupIntroViewControllerDelegate?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
class func instantiate() -> SecureKeyBackupSetupIntroViewController {
|
||||
let viewController = StoryboardScene.SecureKeyBackupSetupIntroViewController.initialScene.instantiate()
|
||||
viewController.theme = ThemeService.shared().theme
|
||||
return viewController
|
||||
}
|
||||
|
||||
// MARK: - Life cycle
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
|
||||
self.vc_removeBackTitle()
|
||||
|
||||
self.setupViews()
|
||||
self.registerThemeServiceDidChangeThemeNotification()
|
||||
self.update(theme: self.theme)
|
||||
}
|
||||
|
||||
override var preferredStatusBarStyle: UIStatusBarStyle {
|
||||
return self.theme.statusBarStyle
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func setupViews() {
|
||||
let cancelBarButtonItem = MXKBarButtonItem(title: VectorL10n.cancel, style: .plain) { [weak self] in
|
||||
guard let self = self else {
|
||||
return
|
||||
}
|
||||
self.delegate?.secureKeyBackupSetupIntroViewControllerDidCancel(self)
|
||||
}
|
||||
self.navigationItem.rightBarButtonItem = cancelBarButtonItem
|
||||
|
||||
self.title = VectorL10n.secureKeyBackupSetupIntroTitle
|
||||
|
||||
self.informationLabel.text = VectorL10n.secureKeyBackupSetupIntroInfo
|
||||
|
||||
self.secureKeyCell.fill(title: VectorL10n.secureKeyBackupSetupIntroUseSecurityKeyTitle,
|
||||
information: VectorL10n.secureKeyBackupSetupIntroUseSecurityKeyInfo,
|
||||
image: Asset.Images.secretsSetupKey.image)
|
||||
|
||||
self.secureKeyCell.action = { [weak self] in
|
||||
guard let self = self else {
|
||||
return
|
||||
}
|
||||
self.delegate?.secureKeyBackupSetupIntroViewControllerDidTapUseKey(self)
|
||||
}
|
||||
|
||||
self.securePassphraseCell.fill(title: VectorL10n.secureKeyBackupSetupIntroUseSecurityPassphraseTitle,
|
||||
information: VectorL10n.secureKeyBackupSetupIntroUseSecurityPassphraseInfo,
|
||||
image: Asset.Images.secretsSetupPassphrase.image)
|
||||
|
||||
self.securePassphraseCell.action = { [weak self] in
|
||||
guard let self = self else {
|
||||
return
|
||||
}
|
||||
self.delegate?.secureKeyBackupSetupIntroViewControllerDidTapUsePassphrase(self)
|
||||
}
|
||||
}
|
||||
|
||||
private func update(theme: Theme) {
|
||||
self.theme = theme
|
||||
|
||||
self.view.backgroundColor = theme.headerBackgroundColor
|
||||
|
||||
if let navigationBar = self.navigationController?.navigationBar {
|
||||
theme.applyStyle(onNavigationBar: navigationBar)
|
||||
}
|
||||
|
||||
self.informationLabel.textColor = theme.textPrimaryColor
|
||||
|
||||
self.topSeparatorView.backgroundColor = theme.lineBreakColor
|
||||
self.secureKeyCell.update(theme: theme)
|
||||
self.securePassphraseCell.update(theme: theme)
|
||||
}
|
||||
|
||||
private func registerThemeServiceDidChangeThemeNotification() {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil)
|
||||
}
|
||||
|
||||
@objc private func themeDidChange() {
|
||||
self.update(theme: ThemeService.shared().theme)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
// File created from FlowTemplate
|
||||
// $ createRootCoordinator.sh KeyBackupSetup/SecureSetup SecureKeyBackupSetup
|
||||
/*
|
||||
Copyright 2020 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 UIKit
|
||||
|
||||
@objcMembers
|
||||
final class SecureKeyBackupSetupCoordinator: SecureKeyBackupSetupCoordinatorType {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let navigationRouter: NavigationRouterType
|
||||
private let recoveryService: MXRecoveryService
|
||||
|
||||
// MARK: Public
|
||||
|
||||
// Must be used only internally
|
||||
var childCoordinators: [Coordinator] = []
|
||||
|
||||
weak var delegate: SecureKeyBackupSetupCoordinatorDelegate?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(session: MXSession) {
|
||||
self.navigationRouter = NavigationRouter(navigationController: RiotNavigationController())
|
||||
self.recoveryService = session.crypto.recoveryService
|
||||
}
|
||||
|
||||
// MARK: - Public methods
|
||||
|
||||
func start() {
|
||||
let rootViewController = self.createIntro()
|
||||
self.navigationRouter.setRootModule(rootViewController)
|
||||
}
|
||||
|
||||
func toPresentable() -> UIViewController {
|
||||
return self.navigationRouter.toPresentable()
|
||||
}
|
||||
|
||||
// MARK: - Private methods
|
||||
|
||||
private func createIntro() -> SecureKeyBackupSetupIntroViewController {
|
||||
let introViewController = SecureKeyBackupSetupIntroViewController.instantiate()
|
||||
introViewController.delegate = self
|
||||
return introViewController
|
||||
}
|
||||
|
||||
private func showSetupKey(passphrase: String? = nil) {
|
||||
let coordinator = SecretsSetupRecoveryKeyCoordinator(recoveryService: self.recoveryService, passphrase: passphrase)
|
||||
coordinator.delegate = self
|
||||
coordinator.start()
|
||||
|
||||
self.add(childCoordinator: coordinator)
|
||||
self.navigationRouter.push(coordinator, animated: true) { [weak self] in
|
||||
self?.remove(childCoordinator: coordinator)
|
||||
}
|
||||
}
|
||||
|
||||
private func showSetupPassphrase() {
|
||||
let coordinator = SecretsSetupRecoveryPassphraseCoordinator(passphraseInput: .new)
|
||||
coordinator.delegate = self
|
||||
coordinator.start()
|
||||
|
||||
self.add(childCoordinator: coordinator)
|
||||
self.navigationRouter.push(coordinator, animated: true) { [weak self] in
|
||||
self?.remove(childCoordinator: coordinator)
|
||||
}
|
||||
}
|
||||
|
||||
private func showSetupPassphraseConfirmation(with passphrase: String) {
|
||||
let coordinator = SecretsSetupRecoveryPassphraseCoordinator(passphraseInput: .confirm(passphrase))
|
||||
coordinator.delegate = self
|
||||
coordinator.start()
|
||||
|
||||
self.add(childCoordinator: coordinator)
|
||||
self.navigationRouter.push(coordinator, animated: true) { [weak self] in
|
||||
self?.remove(childCoordinator: coordinator)
|
||||
}
|
||||
}
|
||||
|
||||
private func showCancelAlert() {
|
||||
let alertController = UIAlertController(title: VectorL10n.secureKeyBackupSetupCancelAlertTitle,
|
||||
message: VectorL10n.secureKeyBackupSetupCancelAlertMessage,
|
||||
preferredStyle: .alert)
|
||||
|
||||
alertController.addAction(UIAlertAction(title: VectorL10n.continue, style: .cancel, handler: { action in
|
||||
}))
|
||||
|
||||
alertController.addAction(UIAlertAction(title: VectorL10n.keyBackupSetupSkipAlertSkipAction, style: .default, handler: { action in
|
||||
self.delegate?.secureKeyBackupSetupCoordinatorDidCancel(self)
|
||||
}))
|
||||
|
||||
self.navigationRouter.present(alertController, animated: true)
|
||||
}
|
||||
|
||||
private func didCancel(showSkipAlert: Bool = true) {
|
||||
if showSkipAlert {
|
||||
self.showCancelAlert()
|
||||
} else {
|
||||
self.delegate?.secureKeyBackupSetupCoordinatorDidCancel(self)
|
||||
}
|
||||
}
|
||||
|
||||
private func didComplete() {
|
||||
self.delegate?.secureKeyBackupSetupCoordinatorDidComplete(self)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - SecureKeyBackupSetupIntroViewControllerDelegate
|
||||
extension SecureKeyBackupSetupCoordinator: SecureKeyBackupSetupIntroViewControllerDelegate {
|
||||
|
||||
func secureKeyBackupSetupIntroViewControllerDidTapUseKey(_ secureKeyBackupSetupIntroViewController: SecureKeyBackupSetupIntroViewController) {
|
||||
self.showSetupKey()
|
||||
}
|
||||
|
||||
func secureKeyBackupSetupIntroViewControllerDidTapUsePassphrase(_ secureKeyBackupSetupIntroViewController: SecureKeyBackupSetupIntroViewController) {
|
||||
self.showSetupPassphrase()
|
||||
}
|
||||
|
||||
func secureKeyBackupSetupIntroViewControllerDidCancel(_ secureKeyBackupSetupIntroViewController: SecureKeyBackupSetupIntroViewController) {
|
||||
self.didCancel()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - SecretsSetupRecoveryKeyCoordinatorDelegate
|
||||
extension SecureKeyBackupSetupCoordinator: SecretsSetupRecoveryKeyCoordinatorDelegate {
|
||||
|
||||
func secretsSetupRecoveryKeyCoordinatorDidComplete(_ coordinator: SecretsSetupRecoveryKeyCoordinatorType) {
|
||||
self.didComplete()
|
||||
}
|
||||
|
||||
func secretsSetupRecoveryKeyCoordinatorDidFailed(_ coordinator: SecretsSetupRecoveryKeyCoordinatorType) {
|
||||
self.didCancel(showSkipAlert: false)
|
||||
}
|
||||
|
||||
func secretsSetupRecoveryKeyCoordinatorDidCancel(_ coordinator: SecretsSetupRecoveryKeyCoordinatorType) {
|
||||
self.didCancel()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - SecretsSetupRecoveryPassphraseCoordinatorDelegate
|
||||
extension SecureKeyBackupSetupCoordinator: SecretsSetupRecoveryPassphraseCoordinatorDelegate {
|
||||
|
||||
func secretsSetupRecoveryPassphraseCoordinator(_ coordinator: SecretsSetupRecoveryPassphraseCoordinatorType, didEnterNewPassphrase passphrase: String) {
|
||||
self.showSetupPassphraseConfirmation(with: passphrase)
|
||||
}
|
||||
|
||||
func secretsSetupRecoveryPassphraseCoordinator(_ coordinator: SecretsSetupRecoveryPassphraseCoordinatorType, didConfirmPassphrase passphrase: String) {
|
||||
self.showSetupKey(passphrase: passphrase)
|
||||
}
|
||||
|
||||
func secretsSetupRecoveryPassphraseCoordinatorDidCancel(_ coordinator: SecretsSetupRecoveryPassphraseCoordinatorType) {
|
||||
self.didCancel()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
// File created from FlowTemplate
|
||||
// $ createRootCoordinator.sh KeyBackupSetup/SecureSetup SecureKeyBackupSetup
|
||||
/*
|
||||
Copyright 2020 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
|
||||
|
||||
@objc protocol SecureKeyBackupSetupCoordinatorBridgePresenterDelegate {
|
||||
func secureKeyBackupSetupCoordinatorBridgePresenterDelegateDidComplete(_ coordinatorBridgePresenter: SecureKeyBackupSetupCoordinatorBridgePresenter)
|
||||
func secureKeyBackupSetupCoordinatorBridgePresenterDelegateDidCancel(_ coordinatorBridgePresenter: SecureKeyBackupSetupCoordinatorBridgePresenter)
|
||||
}
|
||||
|
||||
/// SecureKeyBackupSetupCoordinatorBridgePresenter enables to start SecureKeyBackupSetupCoordinator from a view controller.
|
||||
/// This bridge is used while waiting for global usage of coordinator pattern.
|
||||
@objcMembers
|
||||
final class SecureKeyBackupSetupCoordinatorBridgePresenter: NSObject {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let session: MXSession
|
||||
private var coordinator: SecureKeyBackupSetupCoordinator?
|
||||
|
||||
// MARK: Public
|
||||
|
||||
weak var delegate: SecureKeyBackupSetupCoordinatorBridgePresenterDelegate?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(session: MXSession) {
|
||||
self.session = session
|
||||
super.init()
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
// NOTE: Default value feature is not compatible with Objective-C.
|
||||
// func present(from viewController: UIViewController, animated: Bool) {
|
||||
// self.present(from: viewController, animated: animated)
|
||||
// }
|
||||
|
||||
func present(from viewController: UIViewController, animated: Bool) {
|
||||
let secureKeyBackupSetupCoordinator = SecureKeyBackupSetupCoordinator(session: self.session)
|
||||
secureKeyBackupSetupCoordinator.delegate = self
|
||||
viewController.present(secureKeyBackupSetupCoordinator.toPresentable(), animated: animated, completion: nil)
|
||||
secureKeyBackupSetupCoordinator.start()
|
||||
|
||||
self.coordinator = secureKeyBackupSetupCoordinator
|
||||
}
|
||||
|
||||
func dismiss(animated: Bool, completion: (() -> Void)?) {
|
||||
guard let coordinator = self.coordinator else {
|
||||
return
|
||||
}
|
||||
coordinator.toPresentable().dismiss(animated: animated) {
|
||||
self.coordinator = nil
|
||||
|
||||
if let completion = completion {
|
||||
completion()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - SecureKeyBackupSetupCoordinatorDelegate
|
||||
extension SecureKeyBackupSetupCoordinatorBridgePresenter: SecureKeyBackupSetupCoordinatorDelegate {
|
||||
func secureKeyBackupSetupCoordinatorDidComplete(_ coordinator: SecureKeyBackupSetupCoordinatorType) {
|
||||
self.delegate?.secureKeyBackupSetupCoordinatorBridgePresenterDelegateDidComplete(self)
|
||||
}
|
||||
|
||||
func secureKeyBackupSetupCoordinatorDidCancel(_ coordinator: SecureKeyBackupSetupCoordinatorType) {
|
||||
self.delegate?.secureKeyBackupSetupCoordinatorBridgePresenterDelegateDidCancel(self)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// File created from FlowTemplate
|
||||
// $ createRootCoordinator.sh KeyBackupSetup/SecureSetup SecureKeyBackupSetup
|
||||
/*
|
||||
Copyright 2020 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 SecureKeyBackupSetupCoordinatorDelegate: class {
|
||||
func secureKeyBackupSetupCoordinatorDidComplete(_ coordinator: SecureKeyBackupSetupCoordinatorType)
|
||||
func secureKeyBackupSetupCoordinatorDidCancel(_ coordinator: SecureKeyBackupSetupCoordinatorType)
|
||||
}
|
||||
|
||||
/// `SecureKeyBackupSetupCoordinatorType` is a protocol describing a Coordinator that handle keybackup setup navigation flow.
|
||||
protocol SecureKeyBackupSetupCoordinatorType: Coordinator, Presentable {
|
||||
var delegate: SecureKeyBackupSetupCoordinatorDelegate? { get }
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh SecretsSetupRecoveryKey SecretsSetupRecoveryKey
|
||||
/*
|
||||
Copyright 2020 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
final class SecretsSetupRecoveryKeyCoordinator: SecretsSetupRecoveryKeyCoordinatorType {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private var secretsSetupRecoveryKeyViewModel: SecretsSetupRecoveryKeyViewModelType
|
||||
private let secretsSetupRecoveryKeyViewController: SecretsSetupRecoveryKeyViewController
|
||||
|
||||
// MARK: Public
|
||||
|
||||
// Must be used only internally
|
||||
var childCoordinators: [Coordinator] = []
|
||||
|
||||
weak var delegate: SecretsSetupRecoveryKeyCoordinatorDelegate?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(recoveryService: MXRecoveryService, passphrase: String?) {
|
||||
let secretsSetupRecoveryKeyViewModel = SecretsSetupRecoveryKeyViewModel(recoveryService: recoveryService, passphrase: passphrase)
|
||||
let secretsSetupRecoveryKeyViewController = SecretsSetupRecoveryKeyViewController.instantiate(with: secretsSetupRecoveryKeyViewModel)
|
||||
self.secretsSetupRecoveryKeyViewModel = secretsSetupRecoveryKeyViewModel
|
||||
self.secretsSetupRecoveryKeyViewController = secretsSetupRecoveryKeyViewController
|
||||
}
|
||||
|
||||
// MARK: - Public methods
|
||||
|
||||
func start() {
|
||||
self.secretsSetupRecoveryKeyViewModel.coordinatorDelegate = self
|
||||
}
|
||||
|
||||
func toPresentable() -> UIViewController {
|
||||
return self.secretsSetupRecoveryKeyViewController
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - SecretsSetupRecoveryKeyViewModelCoordinatorDelegate
|
||||
extension SecretsSetupRecoveryKeyCoordinator: SecretsSetupRecoveryKeyViewModelCoordinatorDelegate {
|
||||
|
||||
func secretsSetupRecoveryKeyViewModelDidComplete(_ viewModel: SecretsSetupRecoveryKeyViewModelType) {
|
||||
self.delegate?.secretsSetupRecoveryKeyCoordinatorDidComplete(self)
|
||||
}
|
||||
|
||||
func secretsSetupRecoveryKeyViewModelDidFailed(_ viewModel: SecretsSetupRecoveryKeyViewModelType) {
|
||||
self.delegate?.secretsSetupRecoveryKeyCoordinatorDidFailed(self)
|
||||
}
|
||||
|
||||
func secretsSetupRecoveryKeyViewModelDidCancel(_ viewModel: SecretsSetupRecoveryKeyViewModelType) {
|
||||
self.delegate?.secretsSetupRecoveryKeyCoordinatorDidCancel(self)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh SecretsSetupRecoveryKey SecretsSetupRecoveryKey
|
||||
/*
|
||||
Copyright 2020 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 SecretsSetupRecoveryKeyCoordinatorDelegate: class {
|
||||
func secretsSetupRecoveryKeyCoordinatorDidComplete(_ coordinator: SecretsSetupRecoveryKeyCoordinatorType)
|
||||
func secretsSetupRecoveryKeyCoordinatorDidFailed(_ coordinator: SecretsSetupRecoveryKeyCoordinatorType)
|
||||
func secretsSetupRecoveryKeyCoordinatorDidCancel(_ coordinator: SecretsSetupRecoveryKeyCoordinatorType)
|
||||
}
|
||||
|
||||
/// `SecretsSetupRecoveryKeyCoordinatorType` is a protocol describing a Coordinator that handle key backup setup passphrase navigation flow.
|
||||
protocol SecretsSetupRecoveryKeyCoordinatorType: Coordinator, Presentable {
|
||||
var delegate: SecretsSetupRecoveryKeyCoordinatorDelegate? { get }
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh SecretsSetupRecoveryKey SecretsSetupRecoveryKey
|
||||
/*
|
||||
Copyright 2020 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
|
||||
|
||||
/// SecretsSetupRecoveryKeyViewController view actions exposed to view model
|
||||
enum SecretsSetupRecoveryKeyViewAction {
|
||||
case loadData
|
||||
case done
|
||||
case errorAlertOk
|
||||
case cancel
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="EoE-Pl-I63">
|
||||
<device id="retina6_1" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Secrets Setup Recovery Key View Controller-->
|
||||
<scene sceneID="x3I-nC-qtU">
|
||||
<objects>
|
||||
<viewController extendedLayoutIncludesOpaqueBars="YES" automaticallyAdjustsScrollViewInsets="NO" id="EoE-Pl-I63" customClass="SecretsSetupRecoveryKeyViewController" customModule="Riot" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="EZ7-Nb-xmk">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Ahz-9d-sce">
|
||||
<rect key="frame" x="0.0" y="44" width="414" height="852"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Rs5-uo-2W5">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="382"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="K9F-ti-0rB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="382"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="secrets_setup_key" translatesAutoresizingMaskIntoConstraints="NO" id="JwH-yj-Gj8">
|
||||
<rect key="frame" x="183" y="35" width="48" height="48"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="JwH-yj-Gj8" secondAttribute="height" multiplier="1:1" id="DTn-tC-iTc"/>
|
||||
<constraint firstAttribute="width" constant="48" id="uXl-gX-etQ"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Store your Recovery Key somewhere safe. It can be used to unlock your encrypted messages & data." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="csL-ru-oas">
|
||||
<rect key="frame" x="20" y="113" width="374" height="36"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Loading…" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aDh-9M-4UN">
|
||||
<rect key="frame" x="20" y="184" width="374" height="18"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<color key="textColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="zgt-AN-9EH">
|
||||
<rect key="frame" x="0.0" y="242" width="414" height="120"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="cju-9A-6Ns" customClass="RoundedButton" customModule="Riot" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="0.0" width="374" height="50"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="ywR-tU-0tp"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<inset key="contentEdgeInsets" minX="20" minY="0.0" maxX="20" maxY="0.0"/>
|
||||
<state key="normal" title="Export">
|
||||
<color key="titleColor" red="0.47843137250000001" green="0.78823529410000004" blue="0.63137254899999995" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</state>
|
||||
<state key="disabled">
|
||||
<color key="titleColor" red="0.47843137250000001" green="0.78823529410000004" blue="0.63137254899999995" alpha="0.5" colorSpace="calibratedRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="exportButtonAction:" destination="EoE-Pl-I63" eventType="touchUpInside" id="8Sv-N4-mhU"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="v3h-dA-xvr" userLabel="Continue" customClass="RoundedButton" customModule="Riot" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="70" width="374" height="50"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="efg-jS-vMe"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<inset key="contentEdgeInsets" minX="20" minY="0.0" maxX="20" maxY="0.0"/>
|
||||
<state key="normal" title="Continue">
|
||||
<color key="titleColor" red="0.47843137250000001" green="0.78823529410000004" blue="0.63137254899999995" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</state>
|
||||
<state key="disabled">
|
||||
<color key="titleColor" red="0.47843137250000001" green="0.78823529410000004" blue="0.63137254899999995" alpha="0.5" colorSpace="calibratedRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="doneButtonAction:" destination="EoE-Pl-I63" eventType="touchUpInside" id="NO6-2J-vWo"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="v3h-dA-xvr" firstAttribute="top" secondItem="cju-9A-6Ns" secondAttribute="bottom" constant="20" id="CVl-bR-ZyK"/>
|
||||
<constraint firstAttribute="bottom" secondItem="v3h-dA-xvr" secondAttribute="bottom" id="PPw-gM-JID"/>
|
||||
<constraint firstItem="v3h-dA-xvr" firstAttribute="leading" secondItem="cju-9A-6Ns" secondAttribute="leading" id="THe-E7-SvT"/>
|
||||
<constraint firstItem="v3h-dA-xvr" firstAttribute="trailing" secondItem="cju-9A-6Ns" secondAttribute="trailing" id="W5O-7M-cF3"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="cju-9A-6Ns" secondAttribute="trailing" constant="20" id="X0c-Z0-KGn"/>
|
||||
<constraint firstItem="cju-9A-6Ns" firstAttribute="top" secondItem="zgt-AN-9EH" secondAttribute="top" id="dPj-uh-WWa"/>
|
||||
<constraint firstItem="cju-9A-6Ns" firstAttribute="centerX" secondItem="zgt-AN-9EH" secondAttribute="centerX" id="iuh-Zf-BZM"/>
|
||||
<constraint firstItem="cju-9A-6Ns" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="zgt-AN-9EH" secondAttribute="leading" constant="20" id="iyq-Bv-kvf"/>
|
||||
<constraint firstItem="cju-9A-6Ns" firstAttribute="width" secondItem="zgt-AN-9EH" secondAttribute="width" priority="750" id="t3e-c6-wSf"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="csL-ru-oas" secondAttribute="trailing" constant="20" id="4ZO-ii-ENI"/>
|
||||
<constraint firstAttribute="width" priority="750" constant="500" id="G40-eF-Vmb"/>
|
||||
<constraint firstItem="csL-ru-oas" firstAttribute="leading" secondItem="K9F-ti-0rB" secondAttribute="leading" constant="20" id="GaH-AP-bZ1"/>
|
||||
<constraint firstItem="aDh-9M-4UN" firstAttribute="leading" secondItem="csL-ru-oas" secondAttribute="leading" id="J0Y-Fl-1Lm"/>
|
||||
<constraint firstAttribute="bottom" secondItem="zgt-AN-9EH" secondAttribute="bottom" constant="20" id="NNI-yY-2gw"/>
|
||||
<constraint firstItem="aDh-9M-4UN" firstAttribute="trailing" secondItem="csL-ru-oas" secondAttribute="trailing" id="QAS-cx-4zF"/>
|
||||
<constraint firstItem="zgt-AN-9EH" firstAttribute="top" secondItem="aDh-9M-4UN" secondAttribute="bottom" constant="40" id="WQw-uJ-5v6"/>
|
||||
<constraint firstItem="zgt-AN-9EH" firstAttribute="leading" secondItem="K9F-ti-0rB" secondAttribute="leading" id="dKH-aq-rWl"/>
|
||||
<constraint firstAttribute="trailing" secondItem="zgt-AN-9EH" secondAttribute="trailing" id="dRS-cB-t6V"/>
|
||||
<constraint firstItem="aDh-9M-4UN" firstAttribute="top" secondItem="csL-ru-oas" secondAttribute="bottom" constant="35" id="fB9-8Q-Fee"/>
|
||||
<constraint firstItem="csL-ru-oas" firstAttribute="top" secondItem="JwH-yj-Gj8" secondAttribute="bottom" constant="30" id="pKd-Oy-PNV"/>
|
||||
<constraint firstItem="JwH-yj-Gj8" firstAttribute="centerX" secondItem="K9F-ti-0rB" secondAttribute="centerX" id="qYR-oP-1zH"/>
|
||||
<constraint firstItem="JwH-yj-Gj8" firstAttribute="top" secondItem="K9F-ti-0rB" secondAttribute="top" constant="35" id="sae-bb-nrs"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="K9F-ti-0rB" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Rs5-uo-2W5" secondAttribute="leading" id="4rN-tv-wkb"/>
|
||||
<constraint firstItem="K9F-ti-0rB" firstAttribute="centerX" secondItem="Rs5-uo-2W5" secondAttribute="centerX" id="PIo-oO-BbD"/>
|
||||
<constraint firstItem="K9F-ti-0rB" firstAttribute="top" secondItem="Rs5-uo-2W5" secondAttribute="top" id="nB3-uX-q4J"/>
|
||||
<constraint firstAttribute="bottom" secondItem="K9F-ti-0rB" secondAttribute="bottom" id="t4Y-vr-8c6"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="K9F-ti-0rB" secondAttribute="trailing" id="txe-zb-TiV"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="Rs5-uo-2W5" secondAttribute="bottom" id="Fai-XD-wYZ"/>
|
||||
<constraint firstItem="Rs5-uo-2W5" firstAttribute="leading" secondItem="Ahz-9d-sce" secondAttribute="leading" id="Fv4-4B-T6y"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Rs5-uo-2W5" secondAttribute="trailing" id="lUM-5U-R9B"/>
|
||||
<constraint firstItem="Rs5-uo-2W5" firstAttribute="top" secondItem="Ahz-9d-sce" secondAttribute="top" id="s95-pV-QYC"/>
|
||||
<constraint firstItem="Rs5-uo-2W5" firstAttribute="width" secondItem="Ahz-9d-sce" secondAttribute="width" id="whx-pE-t67"/>
|
||||
</constraints>
|
||||
</scrollView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.94509803920000002" green="0.96078431369999995" blue="0.97254901959999995" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="R4q-cd-DVX" firstAttribute="top" secondItem="Ahz-9d-sce" secondAttribute="top" id="233-gk-CKV"/>
|
||||
<constraint firstItem="R4q-cd-DVX" firstAttribute="trailing" secondItem="Ahz-9d-sce" secondAttribute="trailing" id="Rc0-Sf-qtU"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Ahz-9d-sce" secondAttribute="bottom" id="V3e-5C-fSc"/>
|
||||
<constraint firstItem="Ahz-9d-sce" firstAttribute="leading" secondItem="R4q-cd-DVX" secondAttribute="leading" id="kow-MO-5hW"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="R4q-cd-DVX"/>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="doneButton" destination="v3h-dA-xvr" id="YEi-d4-sUs"/>
|
||||
<outlet property="exportButton" destination="cju-9A-6Ns" id="TU9-kQ-MbV"/>
|
||||
<outlet property="informationLabel" destination="csL-ru-oas" id="tkl-2J-VDB"/>
|
||||
<outlet property="recoveryKeyLabel" destination="aDh-9M-4UN" id="yai-aZ-7uj"/>
|
||||
<outlet property="secureKeyImageView" destination="JwH-yj-Gj8" id="H1W-pB-CN1"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="ekR-Lh-PNe" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-3772" y="-774"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="secrets_setup_key" width="48" height="48"/>
|
||||
</resources>
|
||||
</document>
|
|
@ -0,0 +1,225 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh SecretsSetupRecoveryKey SecretsSetupRecoveryKey
|
||||
/*
|
||||
Copyright 2020 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 UIKit
|
||||
|
||||
final class SecretsSetupRecoveryKeyViewController: UIViewController {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Outlets
|
||||
|
||||
@IBOutlet private weak var secureKeyImageView: UIImageView!
|
||||
@IBOutlet private weak var informationLabel: UILabel!
|
||||
@IBOutlet private weak var recoveryKeyLabel: UILabel!
|
||||
@IBOutlet private weak var exportButton: RoundedButton!
|
||||
@IBOutlet private weak var doneButton: RoundedButton!
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private var viewModel: SecretsSetupRecoveryKeyViewModelType!
|
||||
private var theme: Theme!
|
||||
private var errorPresenter: MXKErrorPresentation!
|
||||
private var activityPresenter: ActivityIndicatorPresenter!
|
||||
|
||||
private var recoveryKey: String?
|
||||
private var hasSavedRecoveryKey: Bool = false
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
class func instantiate(with viewModel: SecretsSetupRecoveryKeyViewModelType) -> SecretsSetupRecoveryKeyViewController {
|
||||
let viewController = StoryboardScene.SecretsSetupRecoveryKeyViewController.initialScene.instantiate()
|
||||
viewController.viewModel = viewModel
|
||||
viewController.theme = ThemeService.shared().theme
|
||||
return viewController
|
||||
}
|
||||
|
||||
// MARK: - Life cycle
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
|
||||
self.setupViews()
|
||||
self.activityPresenter = ActivityIndicatorPresenter()
|
||||
self.errorPresenter = MXKErrorAlertPresentation()
|
||||
|
||||
self.registerThemeServiceDidChangeThemeNotification()
|
||||
self.update(theme: self.theme)
|
||||
|
||||
self.viewModel.viewDelegate = self
|
||||
|
||||
self.viewModel.process(viewAction: .loadData)
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
// Hide back button
|
||||
self.navigationItem.setHidesBackButton(true, animated: animated)
|
||||
}
|
||||
|
||||
override var preferredStatusBarStyle: UIStatusBarStyle {
|
||||
return self.theme.statusBarStyle
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func update(theme: Theme) {
|
||||
self.theme = theme
|
||||
|
||||
self.view.backgroundColor = theme.headerBackgroundColor
|
||||
|
||||
if let navigationBar = self.navigationController?.navigationBar {
|
||||
theme.applyStyle(onNavigationBar: navigationBar)
|
||||
}
|
||||
|
||||
self.secureKeyImageView.tintColor = theme.textPrimaryColor
|
||||
self.informationLabel.textColor = theme.textPrimaryColor
|
||||
self.recoveryKeyLabel.textColor = theme.textSecondaryColor
|
||||
|
||||
self.exportButton.update(theme: theme)
|
||||
self.doneButton.update(theme: theme)
|
||||
}
|
||||
|
||||
private func registerThemeServiceDidChangeThemeNotification() {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil)
|
||||
}
|
||||
|
||||
@objc private func themeDidChange() {
|
||||
self.update(theme: ThemeService.shared().theme)
|
||||
}
|
||||
|
||||
private func setupViews() {
|
||||
let cancelBarButtonItem = MXKBarButtonItem(title: VectorL10n.cancel, style: .plain) { [weak self] in
|
||||
self?.cancelButtonAction()
|
||||
}
|
||||
|
||||
self.navigationItem.rightBarButtonItem = cancelBarButtonItem
|
||||
|
||||
self.vc_removeBackTitle()
|
||||
|
||||
self.title = VectorL10n.secretsSetupRecoveryKeyTitle
|
||||
|
||||
self.secureKeyImageView.image = Asset.Images.secretsSetupKey.image.withRenderingMode(.alwaysTemplate)
|
||||
self.informationLabel.text = VectorL10n.secretsSetupRecoveryKeyInformation
|
||||
self.recoveryKeyLabel.text = VectorL10n.secretsSetupRecoveryKeyLoading
|
||||
|
||||
self.exportButton.setTitle(VectorL10n.secretsSetupRecoveryKeyExportAction, for: .normal)
|
||||
self.exportButton.isEnabled = false
|
||||
self.doneButton.setTitle(VectorL10n.continue, for: .normal)
|
||||
|
||||
self.updateDoneButton()
|
||||
}
|
||||
|
||||
private func render(viewState: SecretsSetupRecoveryKeyViewState) {
|
||||
switch viewState {
|
||||
case .loading:
|
||||
self.renderLoading()
|
||||
case .loaded(let recoveryKey):
|
||||
self.renderLoaded(recoveryKey: recoveryKey)
|
||||
case .error(let error):
|
||||
self.render(error: error)
|
||||
}
|
||||
}
|
||||
|
||||
private func renderLoading() {
|
||||
self.activityPresenter.presentActivityIndicator(on: self.view, animated: true)
|
||||
}
|
||||
|
||||
private func renderLoaded(recoveryKey: String) {
|
||||
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
|
||||
self.exportButton.isEnabled = true
|
||||
self.recoveryKey = recoveryKey
|
||||
self.recoveryKeyLabel.text = recoveryKey
|
||||
}
|
||||
|
||||
private func render(error: Error) {
|
||||
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
|
||||
self.errorPresenter.presentError(from: self, forError: error, animated: true) {
|
||||
self.viewModel.process(viewAction: .errorAlertOk)
|
||||
}
|
||||
}
|
||||
|
||||
private func updateDoneButton() {
|
||||
self.doneButton.isEnabled = self.hasSavedRecoveryKey
|
||||
}
|
||||
|
||||
private func presentKeepSafeAlert() {
|
||||
let alertController = UIAlertController(title: VectorL10n.secretsSetupRecoveryKeyStorageAlertTitle,
|
||||
message: VectorL10n.secretsSetupRecoveryKeyStorageAlertMessage,
|
||||
preferredStyle: .alert)
|
||||
|
||||
alertController.addAction(UIAlertAction(title: VectorL10n.continue, style: .cancel, handler: { action in
|
||||
self.viewModel.process(viewAction: .done)
|
||||
}))
|
||||
|
||||
self.present(alertController, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
private func shareRecoveryKey() {
|
||||
guard let recoveryKey = self.recoveryKey else {
|
||||
return
|
||||
}
|
||||
|
||||
// Set up activity view controller
|
||||
let activityItems: [Any] = [ recoveryKey ]
|
||||
let activityViewController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
|
||||
|
||||
activityViewController.completionWithItemsHandler = { (activityType, completed, returnedItems, error) in
|
||||
|
||||
// Enable made copy button only if user has selected an activity item and has setup recovery key without passphrase
|
||||
if completed {
|
||||
self.hasSavedRecoveryKey = true
|
||||
self.updateDoneButton()
|
||||
}
|
||||
}
|
||||
|
||||
// Configure source view when activity view controller is presented with a popover
|
||||
if let popoverPresentationController = activityViewController.popoverPresentationController {
|
||||
popoverPresentationController.sourceView = self.exportButton
|
||||
popoverPresentationController.sourceRect = self.exportButton.bounds
|
||||
popoverPresentationController.permittedArrowDirections = [.down, .up]
|
||||
}
|
||||
|
||||
self.present(activityViewController, animated: true)
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@IBAction private func exportButtonAction(_ sender: Any) {
|
||||
self.shareRecoveryKey()
|
||||
}
|
||||
|
||||
@IBAction private func doneButtonAction(_ sender: Any) {
|
||||
self.presentKeepSafeAlert()
|
||||
}
|
||||
|
||||
private func cancelButtonAction() {
|
||||
self.viewModel.process(viewAction: .cancel)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - SecretsSetupRecoveryKeyViewModelViewDelegate
|
||||
extension SecretsSetupRecoveryKeyViewController: SecretsSetupRecoveryKeyViewModelViewDelegate {
|
||||
|
||||
func secretsSetupRecoveryKeyViewModel(_ viewModel: SecretsSetupRecoveryKeyViewModelType, didUpdateViewState viewSate: SecretsSetupRecoveryKeyViewState) {
|
||||
self.render(viewState: viewSate)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh SecretsSetupRecoveryKey SecretsSetupRecoveryKey
|
||||
/*
|
||||
Copyright 2020 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
|
||||
|
||||
final class SecretsSetupRecoveryKeyViewModel: SecretsSetupRecoveryKeyViewModelType {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let recoveryService: MXRecoveryService
|
||||
private let passphrase: String?
|
||||
|
||||
// MARK: Public
|
||||
|
||||
weak var viewDelegate: SecretsSetupRecoveryKeyViewModelViewDelegate?
|
||||
weak var coordinatorDelegate: SecretsSetupRecoveryKeyViewModelCoordinatorDelegate?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(recoveryService: MXRecoveryService, passphrase: String?) {
|
||||
self.recoveryService = recoveryService
|
||||
self.passphrase = passphrase
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func process(viewAction: SecretsSetupRecoveryKeyViewAction) {
|
||||
switch viewAction {
|
||||
case .loadData:
|
||||
self.createSecureKey()
|
||||
case .done:
|
||||
self.coordinatorDelegate?.secretsSetupRecoveryKeyViewModelDidComplete(self)
|
||||
case .errorAlertOk:
|
||||
self.coordinatorDelegate?.secretsSetupRecoveryKeyViewModelDidFailed(self)
|
||||
case .cancel:
|
||||
self.coordinatorDelegate?.secretsSetupRecoveryKeyViewModelDidCancel(self)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func createSecureKey() {
|
||||
self.update(viewState: .loading)
|
||||
|
||||
self.recoveryService.createRecovery(forSecrets: nil, withPassphrase: self.passphrase, success: { secretStorageKeyCreationInfo in
|
||||
self.update(viewState: .loaded(secretStorageKeyCreationInfo.recoveryKey))
|
||||
}, failure: { error in
|
||||
self.update(viewState: .error(error))
|
||||
})
|
||||
}
|
||||
|
||||
private func update(viewState: SecretsSetupRecoveryKeyViewState) {
|
||||
self.viewDelegate?.secretsSetupRecoveryKeyViewModel(self, didUpdateViewState: viewState)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh SecretsSetupRecoveryKey SecretsSetupRecoveryKey
|
||||
/*
|
||||
Copyright 2020 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 SecretsSetupRecoveryKeyViewModelViewDelegate: class {
|
||||
func secretsSetupRecoveryKeyViewModel(_ viewModel: SecretsSetupRecoveryKeyViewModelType, didUpdateViewState viewSate: SecretsSetupRecoveryKeyViewState)
|
||||
}
|
||||
|
||||
protocol SecretsSetupRecoveryKeyViewModelCoordinatorDelegate: class {
|
||||
func secretsSetupRecoveryKeyViewModelDidComplete(_ viewModel: SecretsSetupRecoveryKeyViewModelType)
|
||||
func secretsSetupRecoveryKeyViewModelDidFailed(_ viewModel: SecretsSetupRecoveryKeyViewModelType)
|
||||
func secretsSetupRecoveryKeyViewModelDidCancel(_ viewModel: SecretsSetupRecoveryKeyViewModelType)
|
||||
}
|
||||
|
||||
/// Protocol describing the view model used by `SecretsSetupRecoveryKeyViewController`
|
||||
protocol SecretsSetupRecoveryKeyViewModelType {
|
||||
|
||||
var viewDelegate: SecretsSetupRecoveryKeyViewModelViewDelegate? { get set }
|
||||
var coordinatorDelegate: SecretsSetupRecoveryKeyViewModelCoordinatorDelegate? { get set }
|
||||
|
||||
func process(viewAction: SecretsSetupRecoveryKeyViewAction)
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh SecretsSetupRecoveryKey SecretsSetupRecoveryKey
|
||||
/*
|
||||
Copyright 2020 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
|
||||
|
||||
/// SecretsSetupRecoveryKeyViewController view state
|
||||
enum SecretsSetupRecoveryKeyViewState {
|
||||
case loading
|
||||
case loaded(_ recoveryKey: String)
|
||||
case error(Error)
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Test SecretsSetupRecoveryPassphrase
|
||||
/*
|
||||
Copyright 2020 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
final class SecretsSetupRecoveryPassphraseCoordinator: SecretsSetupRecoveryPassphraseCoordinatorType {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private var secretsSetupRecoveryPassphraseViewModel: SecretsSetupRecoveryPassphraseViewModelType
|
||||
private let secretsSetupRecoveryPassphraseViewController: SecretsSetupRecoveryPassphraseViewController
|
||||
|
||||
// MARK: Public
|
||||
|
||||
// Must be used only internally
|
||||
var childCoordinators: [Coordinator] = []
|
||||
|
||||
weak var delegate: SecretsSetupRecoveryPassphraseCoordinatorDelegate?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(passphraseInput: SecretsSetupRecoveryPassphraseInput) {
|
||||
|
||||
let secretsSetupRecoveryPassphraseViewModel = SecretsSetupRecoveryPassphraseViewModel(passphraseInput: passphraseInput)
|
||||
let secretsSetupRecoveryPassphraseViewController = SecretsSetupRecoveryPassphraseViewController.instantiate(with: secretsSetupRecoveryPassphraseViewModel)
|
||||
self.secretsSetupRecoveryPassphraseViewModel = secretsSetupRecoveryPassphraseViewModel
|
||||
self.secretsSetupRecoveryPassphraseViewController = secretsSetupRecoveryPassphraseViewController
|
||||
}
|
||||
|
||||
// MARK: - Public methods
|
||||
|
||||
func start() {
|
||||
self.secretsSetupRecoveryPassphraseViewModel.coordinatorDelegate = self
|
||||
}
|
||||
|
||||
func toPresentable() -> UIViewController {
|
||||
return self.secretsSetupRecoveryPassphraseViewController
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - SecretsSetupRecoveryPassphraseViewModelCoordinatorDelegate
|
||||
extension SecretsSetupRecoveryPassphraseCoordinator: SecretsSetupRecoveryPassphraseViewModelCoordinatorDelegate {
|
||||
|
||||
func secretsSetupRecoveryPassphraseViewModel(_ viewModel: SecretsSetupRecoveryPassphraseViewModelType, didEnterNewPassphrase passphrase: String) {
|
||||
self.delegate?.secretsSetupRecoveryPassphraseCoordinator(self, didEnterNewPassphrase: passphrase)
|
||||
}
|
||||
|
||||
func secretsSetupRecoveryPassphraseViewModel(_ viewModel: SecretsSetupRecoveryPassphraseViewModelType, didConfirmPassphrase passphrase: String) {
|
||||
self.delegate?.secretsSetupRecoveryPassphraseCoordinator(self, didConfirmPassphrase: passphrase)
|
||||
}
|
||||
|
||||
func secretsSetupRecoveryPassphraseViewModelDidCancel(_ viewModel: SecretsSetupRecoveryPassphraseViewModelType) {
|
||||
self.delegate?.secretsSetupRecoveryPassphraseCoordinatorDidCancel(self)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Test SecretsSetupRecoveryPassphrase
|
||||
/*
|
||||
Copyright 2020 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 SecretsSetupRecoveryPassphraseCoordinatorDelegate: class {
|
||||
func secretsSetupRecoveryPassphraseCoordinator(_ coordinator: SecretsSetupRecoveryPassphraseCoordinatorType, didEnterNewPassphrase passphrase: String)
|
||||
func secretsSetupRecoveryPassphraseCoordinator(_ coordinator: SecretsSetupRecoveryPassphraseCoordinatorType, didConfirmPassphrase passphrase: String)
|
||||
func secretsSetupRecoveryPassphraseCoordinatorDidCancel(_ coordinator: SecretsSetupRecoveryPassphraseCoordinatorType)
|
||||
}
|
||||
|
||||
/// `SecretsSetupRecoveryPassphraseCoordinatorType` is a protocol describing a Coordinator that handle key backup setup passphrase navigation flow.
|
||||
protocol SecretsSetupRecoveryPassphraseCoordinatorType: Coordinator, Presentable {
|
||||
var delegate: SecretsSetupRecoveryPassphraseCoordinatorDelegate? { get }
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Test SecretsSetupRecoveryPassphrase
|
||||
/*
|
||||
Copyright 2020 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
|
||||
|
||||
enum SecretsSetupRecoveryPassphraseInput {
|
||||
case new
|
||||
case confirm(_ passphrase: String)
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Test SecretsSetupRecoveryPassphrase
|
||||
/*
|
||||
Copyright 2020 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
|
||||
|
||||
/// SecretsSetupRecoveryPassphraseViewController view actions exposed to view model
|
||||
enum SecretsSetupRecoveryPassphraseViewAction {
|
||||
case loadData
|
||||
case updatePassphrase(_ passphrase: String?)
|
||||
case validate
|
||||
case cancel
|
||||
}
|
|
@ -0,0 +1,285 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="bIB-0i-ukm">
|
||||
<device id="retina6_1" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Secrets Setup Recovery Passphrase View Controller-->
|
||||
<scene sceneID="etY-7t-lyY">
|
||||
<objects>
|
||||
<viewController extendedLayoutIncludesOpaqueBars="YES" automaticallyAdjustsScrollViewInsets="NO" id="bIB-0i-ukm" customClass="SecretsSetupRecoveryPassphraseViewController" customModule="Riot" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="D8T-l5-mMj">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="o4q-2F-ezk">
|
||||
<rect key="frame" x="0.0" y="44" width="414" height="852"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="dME-t7-qZD">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="598"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NHb-J1-L5X">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="598"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="secrets_setup_passphrase" translatesAutoresizingMaskIntoConstraints="NO" id="ZX3-oS-5DJ">
|
||||
<rect key="frame" x="185" y="35" width="44" height="48"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="48" id="380-Pr-HJO"/>
|
||||
<constraint firstAttribute="width" constant="44" id="Ypb-bz-jVe"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ecv-l3-ryP">
|
||||
<rect key="frame" x="20" y="113" width="374" height="54"/>
|
||||
<string key="text">Access your secure message history and your cross-signing identity for verifying other sessions by entering your recovery passphrase.</string>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5eP-6U-QZi">
|
||||
<rect key="frame" x="0.0" y="207" width="414" height="251.5"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="bottom" translatesAutoresizingMaskIntoConstraints="NO" id="mPf-Xv-wqH">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="251.5"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="4z6-DU-d2T">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="78.5"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" text="enter" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="iM1-le-WDv">
|
||||
<rect key="frame" x="20" y="10" width="39.5" height="58.5"/>
|
||||
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Enter passphrase" textAlignment="natural" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="wuc-Sr-qja">
|
||||
<rect key="frame" x="79.5" y="14.5" width="280.5" height="50"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="oeq-kq-s6b"/>
|
||||
</constraints>
|
||||
<nil key="textColor"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" returnKeyType="next" secureTextEntry="YES"/>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="bIB-0i-ukm" id="ZTp-o9-59m"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="H1x-SK-Bsn">
|
||||
<rect key="frame" x="360" y="17.5" width="44" height="44"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="44" id="qC3-Mk-XiH"/>
|
||||
<constraint firstAttribute="height" constant="44" id="uwx-Uv-7kY"/>
|
||||
</constraints>
|
||||
<state key="normal" image="reveal_password_button"/>
|
||||
<connections>
|
||||
<action selector="passphraseVisibilityButtonAction:" destination="bIB-0i-ukm" eventType="touchUpInside" id="cic-gC-Lfl"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="iM1-le-WDv" firstAttribute="leading" secondItem="4z6-DU-d2T" secondAttribute="leading" constant="20" id="5Qr-ay-AD3"/>
|
||||
<constraint firstAttribute="trailing" secondItem="H1x-SK-Bsn" secondAttribute="trailing" constant="10" id="9bF-iX-wf7"/>
|
||||
<constraint firstItem="iM1-le-WDv" firstAttribute="centerY" secondItem="4z6-DU-d2T" secondAttribute="centerY" id="E3g-fR-guv"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="wuc-Sr-qja" secondAttribute="bottom" constant="5" id="EF3-tn-aHa"/>
|
||||
<constraint firstItem="H1x-SK-Bsn" firstAttribute="centerY" secondItem="wuc-Sr-qja" secondAttribute="centerY" id="QWg-IV-bRt"/>
|
||||
<constraint firstAttribute="bottom" secondItem="iM1-le-WDv" secondAttribute="bottom" constant="10" id="VIu-zS-irW"/>
|
||||
<constraint firstItem="wuc-Sr-qja" firstAttribute="top" relation="greaterThanOrEqual" secondItem="4z6-DU-d2T" secondAttribute="top" constant="5" id="WEZ-WG-H3c"/>
|
||||
<constraint firstItem="wuc-Sr-qja" firstAttribute="leading" secondItem="iM1-le-WDv" secondAttribute="trailing" priority="750" constant="10" id="XG2-GF-pwv"/>
|
||||
<constraint firstItem="H1x-SK-Bsn" firstAttribute="leading" secondItem="wuc-Sr-qja" secondAttribute="trailing" id="g2t-e4-oKl"/>
|
||||
<constraint firstItem="iM1-le-WDv" firstAttribute="top" secondItem="4z6-DU-d2T" secondAttribute="top" constant="10" id="iKt-i6-jnP"/>
|
||||
<constraint firstItem="iM1-le-WDv" firstAttribute="centerY" secondItem="wuc-Sr-qja" secondAttribute="centerY" id="tkC-ad-yyK"/>
|
||||
<constraint firstItem="wuc-Sr-qja" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="iM1-le-WDv" secondAttribute="trailing" constant="20" id="uOM-mT-X0Z"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="pQ6-Ke-kTc">
|
||||
<rect key="frame" x="0.0" y="78.5" width="414" height="173"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="15" translatesAutoresizingMaskIntoConstraints="NO" id="XEQ-L8-Tbl">
|
||||
<rect key="frame" x="0.0" y="5" width="414" height="153"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="O4X-SY-HCD">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="5"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="7Ur-Gj-5yT" customClass="PasswordStrengthView" customModule="Riot" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="0.0" width="374" height="5"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="5" id="LGA-bA-pUr"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="7Ur-Gj-5yT" firstAttribute="top" secondItem="O4X-SY-HCD" secondAttribute="top" id="hAi-DD-d7R"/>
|
||||
<constraint firstItem="7Ur-Gj-5yT" firstAttribute="leading" secondItem="O4X-SY-HCD" secondAttribute="leading" constant="20" id="qLK-02-VvY"/>
|
||||
<constraint firstAttribute="bottom" secondItem="7Ur-Gj-5yT" secondAttribute="bottom" id="sye-7J-VNw"/>
|
||||
<constraint firstAttribute="trailing" secondItem="7Ur-Gj-5yT" secondAttribute="trailing" constant="20" id="uYv-z7-RLE"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Yd2-sG-uwh">
|
||||
<rect key="frame" x="0.0" y="20" width="414" height="133"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Try adding a word" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="A2u-5W-L5q">
|
||||
<rect key="frame" x="20" y="0.0" width="374" height="133"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<color key="textColor" red="1" green="0.14913141730000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" priority="250" id="I6i-Jg-mZ3"/>
|
||||
<constraint firstItem="A2u-5W-L5q" firstAttribute="top" secondItem="Yd2-sG-uwh" secondAttribute="top" id="Qib-J0-MO4"/>
|
||||
<constraint firstAttribute="bottom" secondItem="A2u-5W-L5q" secondAttribute="bottom" id="UZc-rg-rAc"/>
|
||||
<constraint firstAttribute="trailing" secondItem="A2u-5W-L5q" secondAttribute="trailing" constant="20" id="YYn-et-fHT"/>
|
||||
<constraint firstItem="A2u-5W-L5q" firstAttribute="leading" secondItem="Yd2-sG-uwh" secondAttribute="leading" constant="20" id="bLx-1L-c23"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="O4X-SY-HCD" firstAttribute="width" secondItem="XEQ-L8-Tbl" secondAttribute="width" id="NRY-zi-9gP"/>
|
||||
<constraint firstItem="Yd2-sG-uwh" firstAttribute="width" secondItem="XEQ-L8-Tbl" secondAttribute="width" id="Wxj-rm-tK6"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="XEQ-L8-Tbl" firstAttribute="leading" secondItem="pQ6-Ke-kTc" secondAttribute="leading" id="aVG-9g-4t9"/>
|
||||
<constraint firstItem="XEQ-L8-Tbl" firstAttribute="top" secondItem="pQ6-Ke-kTc" secondAttribute="top" constant="5" id="qz3-J5-Jc0"/>
|
||||
<constraint firstAttribute="bottom" secondItem="XEQ-L8-Tbl" secondAttribute="bottom" constant="15" id="tG9-Jd-R6N"/>
|
||||
<constraint firstAttribute="trailing" secondItem="XEQ-L8-Tbl" secondAttribute="trailing" id="vAD-HS-KZy"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="pQ6-Ke-kTc" firstAttribute="width" secondItem="mPf-Xv-wqH" secondAttribute="width" id="FJz-yd-QPP"/>
|
||||
<constraint firstItem="4z6-DU-d2T" firstAttribute="width" secondItem="mPf-Xv-wqH" secondAttribute="width" id="Tjm-Zw-JKh"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="mPf-Xv-wqH" firstAttribute="top" secondItem="5eP-6U-QZi" secondAttribute="top" id="1fu-vG-gQo"/>
|
||||
<constraint firstAttribute="trailing" secondItem="mPf-Xv-wqH" secondAttribute="trailing" id="3aT-0u-Dqp"/>
|
||||
<constraint firstAttribute="bottom" secondItem="mPf-Xv-wqH" secondAttribute="bottom" id="QyV-Wc-l5Z"/>
|
||||
<constraint firstItem="mPf-Xv-wqH" firstAttribute="leading" secondItem="5eP-6U-QZi" secondAttribute="leading" id="czh-ku-UT4"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Don't use your account password." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2LW-AX-yzs">
|
||||
<rect key="frame" x="20" y="473.5" width="374" height="14.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="12"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="2kp-HO-dRr">
|
||||
<rect key="frame" x="0.0" y="528" width="414" height="50"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="5Ow-Ba-bLe" customClass="RoundedButton" customModule="Riot" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="0.0" width="374" height="50"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="aYo-rF-vZL"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<inset key="contentEdgeInsets" minX="20" minY="0.0" maxX="20" maxY="0.0"/>
|
||||
<state key="normal" title="Validate">
|
||||
<color key="titleColor" red="0.47843137250000001" green="0.78823529410000004" blue="0.63137254899999995" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</state>
|
||||
<state key="disabled">
|
||||
<color key="titleColor" red="0.47843137250000001" green="0.78823529410000004" blue="0.63137254899999995" alpha="0.5" colorSpace="calibratedRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="validateButtonAction:" destination="bIB-0i-ukm" eventType="touchUpInside" id="CRT-SQ-iBx"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="5Ow-Ba-bLe" secondAttribute="bottom" id="Ey4-nH-44x"/>
|
||||
<constraint firstItem="5Ow-Ba-bLe" firstAttribute="width" secondItem="2kp-HO-dRr" secondAttribute="width" priority="750" id="d9G-hg-c38"/>
|
||||
<constraint firstItem="5Ow-Ba-bLe" firstAttribute="top" secondItem="2kp-HO-dRr" secondAttribute="top" id="p83-Ml-a6D"/>
|
||||
<constraint firstItem="5Ow-Ba-bLe" firstAttribute="centerX" secondItem="2kp-HO-dRr" secondAttribute="centerX" id="taR-rx-sJn"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="5eP-6U-QZi" secondAttribute="trailing" id="0ve-ds-mJr"/>
|
||||
<constraint firstItem="ecv-l3-ryP" firstAttribute="leading" secondItem="NHb-J1-L5X" secondAttribute="leading" constant="20" id="1Wo-9r-ycH"/>
|
||||
<constraint firstItem="2LW-AX-yzs" firstAttribute="leading" secondItem="NHb-J1-L5X" secondAttribute="leading" constant="20" id="6je-oq-7RI"/>
|
||||
<constraint firstItem="2LW-AX-yzs" firstAttribute="top" secondItem="5eP-6U-QZi" secondAttribute="bottom" constant="15" id="7ul-hJ-K6H"/>
|
||||
<constraint firstAttribute="trailing" secondItem="ecv-l3-ryP" secondAttribute="trailing" constant="20" id="9jK-Nm-ExO"/>
|
||||
<constraint firstAttribute="width" priority="750" constant="500" id="Gg8-aF-YB1"/>
|
||||
<constraint firstAttribute="trailing" secondItem="2LW-AX-yzs" secondAttribute="trailing" constant="20" id="HxK-zm-30M"/>
|
||||
<constraint firstItem="ecv-l3-ryP" firstAttribute="top" secondItem="ZX3-oS-5DJ" secondAttribute="bottom" constant="30" id="Sgu-ux-Ec9"/>
|
||||
<constraint firstAttribute="trailing" secondItem="2kp-HO-dRr" secondAttribute="trailing" id="TQA-Lg-F8a"/>
|
||||
<constraint firstItem="2kp-HO-dRr" firstAttribute="leading" secondItem="NHb-J1-L5X" secondAttribute="leading" id="Yqh-Ug-xoQ"/>
|
||||
<constraint firstItem="ZX3-oS-5DJ" firstAttribute="centerX" secondItem="NHb-J1-L5X" secondAttribute="centerX" id="dhm-uO-9qa"/>
|
||||
<constraint firstItem="5eP-6U-QZi" firstAttribute="leading" secondItem="NHb-J1-L5X" secondAttribute="leading" id="em6-Xe-8LR"/>
|
||||
<constraint firstItem="ZX3-oS-5DJ" firstAttribute="top" secondItem="NHb-J1-L5X" secondAttribute="top" constant="35" id="gxm-Dc-zzj"/>
|
||||
<constraint firstItem="2kp-HO-dRr" firstAttribute="top" secondItem="2LW-AX-yzs" secondAttribute="bottom" constant="40" id="hMN-TD-hYF"/>
|
||||
<constraint firstAttribute="bottom" secondItem="2kp-HO-dRr" secondAttribute="bottom" constant="20" id="svg-Pb-ME3"/>
|
||||
<constraint firstItem="5eP-6U-QZi" firstAttribute="top" secondItem="ecv-l3-ryP" secondAttribute="bottom" constant="40" id="vDP-O1-IhH"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="NHb-J1-L5X" secondAttribute="bottom" id="53C-6L-LrF"/>
|
||||
<constraint firstItem="NHb-J1-L5X" firstAttribute="top" secondItem="dME-t7-qZD" secondAttribute="top" id="ZlU-kl-Rzq"/>
|
||||
<constraint firstItem="5Ow-Ba-bLe" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="dME-t7-qZD" secondAttribute="leading" constant="20" id="ZmL-F4-HZY"/>
|
||||
<constraint firstItem="NHb-J1-L5X" firstAttribute="centerX" secondItem="dME-t7-qZD" secondAttribute="centerX" id="cUL-iD-JJv"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="NHb-J1-L5X" secondAttribute="trailing" id="eLO-V9-4WS"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="5Ow-Ba-bLe" secondAttribute="trailing" constant="20" id="lAb-bG-jNQ"/>
|
||||
<constraint firstItem="NHb-J1-L5X" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="dME-t7-qZD" secondAttribute="leading" id="qix-Tx-bKx"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="dME-t7-qZD" firstAttribute="leading" secondItem="o4q-2F-ezk" secondAttribute="leading" id="Eqv-Ts-WXt"/>
|
||||
<constraint firstItem="dME-t7-qZD" firstAttribute="width" secondItem="o4q-2F-ezk" secondAttribute="width" id="PLv-tO-F3G"/>
|
||||
<constraint firstAttribute="trailing" secondItem="dME-t7-qZD" secondAttribute="trailing" id="WWJ-PK-ihX"/>
|
||||
<constraint firstItem="dME-t7-qZD" firstAttribute="top" secondItem="o4q-2F-ezk" secondAttribute="top" id="Wqq-0l-F66"/>
|
||||
<constraint firstAttribute="bottom" secondItem="dME-t7-qZD" secondAttribute="bottom" id="itF-04-4ea"/>
|
||||
</constraints>
|
||||
</scrollView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.94509803920000002" green="0.96078431369999995" blue="0.97254901959999995" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="o4q-2F-ezk" firstAttribute="leading" secondItem="dKy-p2-wAx" secondAttribute="leading" id="Jje-qL-QFy"/>
|
||||
<constraint firstItem="dKy-p2-wAx" firstAttribute="trailing" secondItem="o4q-2F-ezk" secondAttribute="trailing" id="Jow-ri-Vds"/>
|
||||
<constraint firstAttribute="bottom" secondItem="o4q-2F-ezk" secondAttribute="bottom" id="flc-Xx-pJR"/>
|
||||
<constraint firstItem="dKy-p2-wAx" firstAttribute="top" secondItem="o4q-2F-ezk" secondAttribute="top" id="rly-LW-com"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="dKy-p2-wAx"/>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="additionalInformationLabel" destination="2LW-AX-yzs" id="sSr-zi-cYk"/>
|
||||
<outlet property="formBackgroundView" destination="5eP-6U-QZi" id="DSp-VW-aQt"/>
|
||||
<outlet property="informationLabel" destination="ecv-l3-ryP" id="cJ6-CH-05z"/>
|
||||
<outlet property="passphraseAdditionalInfoView" destination="pQ6-Ke-kTc" id="0tj-vn-lWG"/>
|
||||
<outlet property="passphraseAdditionalLabel" destination="A2u-5W-L5q" id="OI1-F7-Rsm"/>
|
||||
<outlet property="passphraseStrengthContainerView" destination="O4X-SY-HCD" id="Ibs-aY-NAO"/>
|
||||
<outlet property="passphraseStrengthView" destination="7Ur-Gj-5yT" id="4um-Bj-28E"/>
|
||||
<outlet property="passphraseTextField" destination="wuc-Sr-qja" id="FPu-mI-s69"/>
|
||||
<outlet property="passphraseTitleLabel" destination="iM1-le-WDv" id="MXH-F1-72q"/>
|
||||
<outlet property="passphraseVisibilityButton" destination="H1x-SK-Bsn" id="hJB-hW-7Jk"/>
|
||||
<outlet property="scrollView" destination="o4q-2F-ezk" id="yWy-nx-irL"/>
|
||||
<outlet property="securePassphraseImageView" destination="ZX3-oS-5DJ" id="wi7-vp-rvG"/>
|
||||
<outlet property="validateButton" destination="5Ow-Ba-bLe" id="Ugv-xk-l5i"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Lob-0d-tfH" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-3772.4637681159425" y="-774.10714285714278"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="reveal_password_button" width="24" height="18"/>
|
||||
<image name="secrets_setup_passphrase" width="48" height="48"/>
|
||||
</resources>
|
||||
</document>
|
|
@ -0,0 +1,323 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Test SecretsSetupRecoveryPassphrase
|
||||
/*
|
||||
Copyright 2020 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 UIKit
|
||||
|
||||
final class SecretsSetupRecoveryPassphraseViewController: UIViewController {
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
private enum Constants {
|
||||
static let animationDuration: TimeInterval = 0.3
|
||||
}
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Outlets
|
||||
|
||||
@IBOutlet private weak var scrollView: UIScrollView!
|
||||
|
||||
@IBOutlet private weak var securePassphraseImageView: UIImageView!
|
||||
@IBOutlet private weak var informationLabel: UILabel!
|
||||
|
||||
@IBOutlet private weak var formBackgroundView: UIView!
|
||||
|
||||
@IBOutlet private weak var passphraseTitleLabel: UILabel!
|
||||
@IBOutlet private weak var passphraseTextField: UITextField!
|
||||
@IBOutlet private weak var passphraseVisibilityButton: UIButton!
|
||||
|
||||
@IBOutlet private weak var passphraseAdditionalInfoView: UIView!
|
||||
@IBOutlet private weak var passphraseStrengthContainerView: UIView!
|
||||
@IBOutlet private weak var passphraseStrengthView: PasswordStrengthView!
|
||||
@IBOutlet private weak var passphraseAdditionalLabel: UILabel!
|
||||
|
||||
@IBOutlet private weak var additionalInformationLabel: UILabel!
|
||||
|
||||
@IBOutlet private weak var validateButton: RoundedButton!
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private var viewModel: SecretsSetupRecoveryPassphraseViewModelType!
|
||||
private var theme: Theme!
|
||||
private var keyboardAvoider: KeyboardAvoider?
|
||||
private var errorPresenter: MXKErrorPresentation!
|
||||
private var activityPresenter: ActivityIndicatorPresenter!
|
||||
private var isFirstViewAppearing: Bool = true
|
||||
private var isPassphraseTextFieldEditedOnce: Bool = false
|
||||
|
||||
private var currentViewData: SecretsSetupRecoveryPassphraseViewData?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
class func instantiate(with viewModel: SecretsSetupRecoveryPassphraseViewModelType) -> SecretsSetupRecoveryPassphraseViewController {
|
||||
let viewController = StoryboardScene.SecretsSetupRecoveryPassphraseViewController.initialScene.instantiate()
|
||||
viewController.viewModel = viewModel
|
||||
viewController.theme = ThemeService.shared().theme
|
||||
return viewController
|
||||
}
|
||||
|
||||
// MARK: - Life cycle
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
|
||||
self.setupViews()
|
||||
self.keyboardAvoider = KeyboardAvoider(scrollViewContainerView: self.view, scrollView: self.scrollView)
|
||||
self.activityPresenter = ActivityIndicatorPresenter()
|
||||
self.errorPresenter = MXKErrorAlertPresentation()
|
||||
|
||||
self.registerThemeServiceDidChangeThemeNotification()
|
||||
self.update(theme: self.theme)
|
||||
|
||||
self.viewModel.viewDelegate = self
|
||||
|
||||
self.viewModel.process(viewAction: .loadData)
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
self.keyboardAvoider?.startAvoiding()
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
if self.isFirstViewAppearing {
|
||||
self.isFirstViewAppearing = false
|
||||
}
|
||||
}
|
||||
|
||||
override func viewDidDisappear(_ animated: Bool) {
|
||||
super.viewDidDisappear(animated)
|
||||
|
||||
self.view.endEditing(true)
|
||||
self.keyboardAvoider?.stopAvoiding()
|
||||
}
|
||||
|
||||
override var preferredStatusBarStyle: UIStatusBarStyle {
|
||||
return self.theme.statusBarStyle
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func setupViews() {
|
||||
let cancelBarButtonItem = MXKBarButtonItem(title: VectorL10n.cancel, style: .plain) { [weak self] in
|
||||
self?.cancelButtonAction()
|
||||
}
|
||||
|
||||
self.navigationItem.rightBarButtonItem = cancelBarButtonItem
|
||||
|
||||
self.vc_removeBackTitle()
|
||||
|
||||
self.title = VectorL10n.secretsSetupRecoveryPassphraseTitle
|
||||
|
||||
self.scrollView.keyboardDismissMode = .interactive
|
||||
|
||||
self.securePassphraseImageView.image = Asset.Images.secretsSetupPassphrase.image.withRenderingMode(.alwaysTemplate)
|
||||
|
||||
self.passphraseTextField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)
|
||||
self.passphraseAdditionalInfoView.isHidden = true
|
||||
|
||||
let visibilityImage = Asset.Images.revealPasswordButton.image.withRenderingMode(.alwaysTemplate)
|
||||
self.passphraseVisibilityButton.setImage(visibilityImage, for: .normal)
|
||||
|
||||
self.additionalInformationLabel.text = VectorL10n.secretsSetupRecoveryPassphraseAdditionalInformation
|
||||
|
||||
self.validateButton.setTitle(VectorL10n.continue, for: .normal)
|
||||
}
|
||||
|
||||
private func update(theme: Theme) {
|
||||
self.theme = theme
|
||||
|
||||
self.view.backgroundColor = theme.headerBackgroundColor
|
||||
|
||||
if let navigationBar = self.navigationController?.navigationBar {
|
||||
theme.applyStyle(onNavigationBar: navigationBar)
|
||||
}
|
||||
|
||||
self.securePassphraseImageView.tintColor = theme.textPrimaryColor
|
||||
|
||||
self.informationLabel.textColor = theme.textPrimaryColor
|
||||
|
||||
self.formBackgroundView.backgroundColor = theme.backgroundColor
|
||||
self.passphraseTitleLabel.textColor = theme.textPrimaryColor
|
||||
theme.applyStyle(onTextField: self.passphraseTextField)
|
||||
|
||||
let passphraseTitle: String
|
||||
|
||||
if let viewData = self.currentViewData, case .confimPassphrase = viewData.mode {
|
||||
passphraseTitle = VectorL10n.secretsSetupRecoveryPassphraseConfirmPassphrasePlaceholder
|
||||
} else {
|
||||
passphraseTitle = VectorL10n.keyBackupSetupPassphrasePassphrasePlaceholder
|
||||
}
|
||||
|
||||
self.passphraseTextField.attributedPlaceholder = NSAttributedString(string: passphraseTitle,
|
||||
attributes: [.foregroundColor: theme.placeholderTextColor])
|
||||
self.passphraseVisibilityButton.tintColor = theme.tintColor
|
||||
|
||||
self.additionalInformationLabel.textColor = theme.textSecondaryColor
|
||||
|
||||
self.validateButton.update(theme: theme)
|
||||
}
|
||||
|
||||
private func registerThemeServiceDidChangeThemeNotification() {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil)
|
||||
}
|
||||
|
||||
@objc private func themeDidChange() {
|
||||
self.update(theme: ThemeService.shared().theme)
|
||||
}
|
||||
|
||||
private func render(viewState: SecretsSetupRecoveryPassphraseViewState) {
|
||||
switch viewState {
|
||||
case .loaded(let viewData):
|
||||
self.renderLoaded(viewData: viewData)
|
||||
case .formUpdated(let viewData):
|
||||
self.renderFormUpdated(viewData: viewData)
|
||||
case .error(let error):
|
||||
self.render(error: error)
|
||||
}
|
||||
}
|
||||
|
||||
private func renderLoaded(viewData: SecretsSetupRecoveryPassphraseViewData) {
|
||||
|
||||
self.currentViewData = viewData
|
||||
|
||||
let informationText: String
|
||||
let passphraseTitle: String
|
||||
let showPasswordStrength: Bool
|
||||
|
||||
switch viewData.mode {
|
||||
case .newPassphrase(strength: let strength):
|
||||
informationText = VectorL10n.secretsSetupRecoveryPassphraseInformation
|
||||
passphraseTitle = VectorL10n.keyBackupSetupPassphrasePassphraseTitle
|
||||
showPasswordStrength = true
|
||||
self.passphraseStrengthView.strength = strength
|
||||
case .confimPassphrase:
|
||||
informationText = VectorL10n.secretsSetupRecoveryPassphraseConfirmInformation
|
||||
passphraseTitle = VectorL10n.secretsSetupRecoveryPassphraseConfirmPassphraseTitle
|
||||
showPasswordStrength = false
|
||||
}
|
||||
|
||||
self.informationLabel.text = informationText
|
||||
self.passphraseTitleLabel.text = passphraseTitle
|
||||
|
||||
self.passphraseStrengthContainerView.isHidden = !showPasswordStrength
|
||||
|
||||
self.update(theme: self.theme)
|
||||
}
|
||||
|
||||
private func renderFormUpdated(viewData: SecretsSetupRecoveryPassphraseViewData) {
|
||||
self.currentViewData = viewData
|
||||
|
||||
if case .newPassphrase(strength: let strength) = viewData.mode {
|
||||
self.passphraseStrengthView.strength = strength
|
||||
}
|
||||
|
||||
self.validateButton.isEnabled = viewData.isFormValid
|
||||
self.updatePassphraseAdditionalLabel(viewData: viewData)
|
||||
|
||||
// Show passphrase additional info at first character entered
|
||||
if self.isPassphraseTextFieldEditedOnce == false, self.passphraseTextField.text?.isEmpty == false {
|
||||
self.isPassphraseTextFieldEditedOnce = true
|
||||
self.showPassphraseAdditionalInfo(animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
private func render(error: Error) {
|
||||
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
|
||||
self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: nil)
|
||||
}
|
||||
|
||||
private func showPassphraseAdditionalInfo(animated: Bool) {
|
||||
guard self.passphraseAdditionalInfoView.isHidden else {
|
||||
return
|
||||
}
|
||||
|
||||
// Workaround to layout passphraseStrengthView corner radius
|
||||
self.passphraseStrengthView.setNeedsLayout()
|
||||
|
||||
UIView.animate(withDuration: Constants.animationDuration) {
|
||||
self.passphraseAdditionalInfoView.isHidden = false
|
||||
}
|
||||
}
|
||||
|
||||
private func updatePassphraseAdditionalLabel(viewData: SecretsSetupRecoveryPassphraseViewData) {
|
||||
|
||||
let text: String
|
||||
let textColor: UIColor
|
||||
|
||||
if viewData.isFormValid {
|
||||
switch viewData.mode {
|
||||
case .newPassphrase:
|
||||
text = VectorL10n.keyBackupSetupPassphrasePassphraseValid
|
||||
case .confimPassphrase:
|
||||
text = VectorL10n.keyBackupSetupPassphraseConfirmPassphraseValid
|
||||
}
|
||||
|
||||
textColor = self.theme.tintColor
|
||||
} else {
|
||||
switch viewData.mode {
|
||||
case .newPassphrase:
|
||||
text = VectorL10n.keyBackupSetupPassphrasePassphraseInvalid
|
||||
case .confimPassphrase:
|
||||
text = VectorL10n.keyBackupSetupPassphraseConfirmPassphraseInvalid
|
||||
}
|
||||
|
||||
textColor = self.theme.noticeColor
|
||||
}
|
||||
|
||||
self.passphraseAdditionalLabel.text = text
|
||||
self.passphraseAdditionalLabel.textColor = textColor
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@IBAction private func passphraseVisibilityButtonAction(_ sender: Any) {
|
||||
guard self.isPassphraseTextFieldEditedOnce else {
|
||||
return
|
||||
}
|
||||
self.passphraseTextField.isSecureTextEntry.toggle()
|
||||
}
|
||||
|
||||
@objc private func textFieldDidChange(_ textField: UITextField) {
|
||||
guard textField == self.passphraseTextField else {
|
||||
return
|
||||
}
|
||||
self.viewModel.process(viewAction: .updatePassphrase(textField.text))
|
||||
}
|
||||
|
||||
@IBAction private func validateButtonAction(_ sender: Any) {
|
||||
self.viewModel.process(viewAction: .validate)
|
||||
}
|
||||
|
||||
private func cancelButtonAction() {
|
||||
self.viewModel.process(viewAction: .cancel)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - SecretsSetupRecoveryPassphraseViewModelViewDelegate
|
||||
extension SecretsSetupRecoveryPassphraseViewController: SecretsSetupRecoveryPassphraseViewModelViewDelegate {
|
||||
|
||||
func secretsSetupRecoveryPassphraseViewModel(_ viewModel: SecretsSetupRecoveryPassphraseViewModelType, didUpdateViewState viewSate: SecretsSetupRecoveryPassphraseViewState) {
|
||||
self.render(viewState: viewSate)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Test SecretsSetupRecoveryPassphrase
|
||||
/*
|
||||
Copyright 2020 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
|
||||
|
||||
final class SecretsSetupRecoveryPassphraseViewModel: SecretsSetupRecoveryPassphraseViewModelType {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let passphraseInput: SecretsSetupRecoveryPassphraseInput
|
||||
private let passwordStrengthManager: PasswordStrengthManager
|
||||
|
||||
private var currentViewData: SecretsSetupRecoveryPassphraseViewData?
|
||||
private var passphrase: String?
|
||||
|
||||
// MARK: Public
|
||||
|
||||
weak var viewDelegate: SecretsSetupRecoveryPassphraseViewModelViewDelegate?
|
||||
weak var coordinatorDelegate: SecretsSetupRecoveryPassphraseViewModelCoordinatorDelegate?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(passphraseInput: SecretsSetupRecoveryPassphraseInput) {
|
||||
self.passphraseInput = passphraseInput
|
||||
self.passwordStrengthManager = PasswordStrengthManager()
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func process(viewAction: SecretsSetupRecoveryPassphraseViewAction) {
|
||||
switch viewAction {
|
||||
case .loadData:
|
||||
self.loadData()
|
||||
case .updatePassphrase(let passphrase):
|
||||
self.updatePassphrase(passphrase)
|
||||
case .validate:
|
||||
self.validate()
|
||||
case .cancel:
|
||||
self.coordinatorDelegate?.secretsSetupRecoveryPassphraseViewModelDidCancel(self)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func loadData() {
|
||||
|
||||
let viewDataMode: SecretsSetupRecoveryPassphraseViewDataMode
|
||||
|
||||
switch self.passphraseInput {
|
||||
case .new:
|
||||
viewDataMode = .newPassphrase(strength: .tooGuessable)
|
||||
case .confirm:
|
||||
viewDataMode = .confimPassphrase
|
||||
}
|
||||
|
||||
let viewData = SecretsSetupRecoveryPassphraseViewData(mode: viewDataMode, isFormValid: false)
|
||||
|
||||
self.update(viewState: .loaded(viewData))
|
||||
}
|
||||
|
||||
private func update(viewState: SecretsSetupRecoveryPassphraseViewState) {
|
||||
self.viewDelegate?.secretsSetupRecoveryPassphraseViewModel(self, didUpdateViewState: viewState)
|
||||
}
|
||||
|
||||
private func updatePassphrase(_ passphrase: String?) {
|
||||
|
||||
let viewDataMode: SecretsSetupRecoveryPassphraseViewDataMode
|
||||
let isFormValid: Bool
|
||||
|
||||
switch self.passphraseInput {
|
||||
case .new:
|
||||
let passphraseStrength = self.passwordStrength(for: passphrase)
|
||||
viewDataMode = .newPassphrase(strength: passphraseStrength)
|
||||
isFormValid = passphraseStrength == .veryUnguessable
|
||||
case .confirm(let passphraseToConfirm):
|
||||
viewDataMode = .confimPassphrase
|
||||
isFormValid = passphrase == passphraseToConfirm
|
||||
}
|
||||
|
||||
let viewData = SecretsSetupRecoveryPassphraseViewData(mode: viewDataMode, isFormValid: isFormValid)
|
||||
|
||||
self.passphrase = passphrase
|
||||
self.currentViewData = viewData
|
||||
|
||||
self.update(viewState: .formUpdated(viewData))
|
||||
}
|
||||
|
||||
private func validate() {
|
||||
guard let viewData = self.currentViewData,
|
||||
viewData.isFormValid,
|
||||
let passphrase = self.passphrase else {
|
||||
return
|
||||
}
|
||||
|
||||
switch self.passphraseInput {
|
||||
case .new:
|
||||
self.coordinatorDelegate?.secretsSetupRecoveryPassphraseViewModel(self, didEnterNewPassphrase: passphrase)
|
||||
case .confirm:
|
||||
self.coordinatorDelegate?.secretsSetupRecoveryPassphraseViewModel(self, didConfirmPassphrase: passphrase)
|
||||
}
|
||||
}
|
||||
|
||||
private func passwordStrength(for password: String?) -> PasswordStrength {
|
||||
guard let password = password else {
|
||||
return .tooGuessable
|
||||
}
|
||||
return self.passwordStrengthManager.passwordStrength(for: password)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Test SecretsSetupRecoveryPassphrase
|
||||
/*
|
||||
Copyright 2020 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 SecretsSetupRecoveryPassphraseViewModelViewDelegate: class {
|
||||
func secretsSetupRecoveryPassphraseViewModel(_ viewModel: SecretsSetupRecoveryPassphraseViewModelType, didUpdateViewState viewSate: SecretsSetupRecoveryPassphraseViewState)
|
||||
}
|
||||
|
||||
protocol SecretsSetupRecoveryPassphraseViewModelCoordinatorDelegate: class {
|
||||
func secretsSetupRecoveryPassphraseViewModel(_ viewModel: SecretsSetupRecoveryPassphraseViewModelType, didEnterNewPassphrase passphrase: String)
|
||||
func secretsSetupRecoveryPassphraseViewModel(_ viewModel: SecretsSetupRecoveryPassphraseViewModelType, didConfirmPassphrase passphrase: String)
|
||||
func secretsSetupRecoveryPassphraseViewModelDidCancel(_ viewModel: SecretsSetupRecoveryPassphraseViewModelType)
|
||||
}
|
||||
|
||||
/// Protocol describing the view model used by `SecretsSetupRecoveryPassphraseViewController`
|
||||
protocol SecretsSetupRecoveryPassphraseViewModelType {
|
||||
|
||||
var viewDelegate: SecretsSetupRecoveryPassphraseViewModelViewDelegate? { get set }
|
||||
var coordinatorDelegate: SecretsSetupRecoveryPassphraseViewModelCoordinatorDelegate? { get set }
|
||||
|
||||
func process(viewAction: SecretsSetupRecoveryPassphraseViewAction)
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Test SecretsSetupRecoveryPassphrase
|
||||
/*
|
||||
Copyright 2020 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
|
||||
|
||||
enum SecretsSetupRecoveryPassphraseViewDataMode {
|
||||
case newPassphrase(strength: PasswordStrength)
|
||||
case confimPassphrase
|
||||
}
|
||||
|
||||
struct SecretsSetupRecoveryPassphraseViewData {
|
||||
let mode: SecretsSetupRecoveryPassphraseViewDataMode
|
||||
let isFormValid: Bool
|
||||
}
|
||||
|
||||
/// SecretsSetupRecoveryPassphraseViewController view state
|
||||
enum SecretsSetupRecoveryPassphraseViewState {
|
||||
case loaded(_ viewData: SecretsSetupRecoveryPassphraseViewData)
|
||||
case formUpdated(_ viewData: SecretsSetupRecoveryPassphraseViewData)
|
||||
case error(Error)
|
||||
}
|
|
@ -564,7 +564,7 @@
|
|||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
};
|
||||
|
||||
[self.mainSession canEnableE2EByDefaultInNewRoomWithUsers:inviteArray success:^(BOOL canEnableE2E) {
|
||||
[self.mainSession riot_canEnableE2EByDefaultInNewRoomWithUsers:inviteArray success:^(BOOL canEnableE2E) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
// Create new room
|
||||
|
|
25
Tools/Rageshakes/getlogs.sh
Normal file
|
@ -0,0 +1,25 @@
|
|||
#!/bin/sh
|
||||
|
||||
# ./getlogs.sh https://riot.im/bugreports/listing/2020-06-07/104229/
|
||||
|
||||
if [ ! $# -eq 1 ]; then
|
||||
echo "Usage: ./getLogs.sh [http link]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
LOGS_URL=$1
|
||||
|
||||
ID=$( basename $LOGS_URL )
|
||||
|
||||
echo $ID
|
||||
mkdir $ID
|
||||
cd $ID
|
||||
|
||||
wget -r -nd --user=matrix --password=a^njerkoo=les $LOGS_URL
|
||||
|
||||
for f in *.log.gz; do
|
||||
mv -- "$f" "${f%.log.gz}.log"
|
||||
done
|
||||
|
||||
rm *.html
|
||||
|