Complete security: Add recover secrets action.

This commit is contained in:
SBiOSoftWhare
2020-06-09 17:36:55 +02:00
parent 4bf3391198
commit a5ffe9381d
8 changed files with 226 additions and 81 deletions
@@ -72,4 +72,8 @@ extension KeyVerificationSelfVerifyWaitCoordinator: KeyVerificationSelfVerifyWai
func keyVerificationSelfVerifyWaitViewModelDidCancel(_ viewModel: KeyVerificationSelfVerifyWaitViewModelType) {
self.delegate?.keyVerificationSelfVerifyWaitCoordinatorDidCancel(self)
}
func keyVerificationSelfVerifyWaitViewModel(_ coordinator: KeyVerificationSelfVerifyWaitViewModelType, wantsToRecoverSecretsWith secretsRecoveryMode: SecretsRecoveryMode) {
self.delegate?.keyVerificationSelfVerifyWaitCoordinator(self, wantsToRecoverSecretsWith: secretsRecoveryMode)
}
}
@@ -22,6 +22,7 @@ protocol KeyVerificationSelfVerifyWaitCoordinatorDelegate: class {
func keyVerificationSelfVerifyWaitCoordinator(_ coordinator: KeyVerificationSelfVerifyWaitCoordinatorType, didAcceptKeyVerificationRequest keyVerificationRequest: MXKeyVerificationRequest)
func keyVerificationSelfVerifyWaitCoordinator(_ coordinator: KeyVerificationSelfVerifyWaitCoordinatorType, didAcceptIncomingSASTransaction incomingSASTransaction: MXIncomingSASTransaction)
func keyVerificationSelfVerifyWaitCoordinatorDidCancel(_ coordinator: KeyVerificationSelfVerifyWaitCoordinatorType)
func keyVerificationSelfVerifyWaitCoordinator(_ coordinator: KeyVerificationSelfVerifyWaitCoordinatorType, wantsToRecoverSecretsWith secretsRecoveryMode: SecretsRecoveryMode)
}
/// `KeyVerificationSelfVerifyWaitCoordinatorType` is a protocol describing a Coordinator that handle key backup setup passphrase navigation flow.
@@ -22,4 +22,5 @@ import Foundation
enum KeyVerificationSelfVerifyWaitViewAction {
case loadData
case cancel
case recoverSecrets
}
@@ -18,95 +18,166 @@
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IlB-Ch-LEo">
<rect key="frame" x="0.0" y="201.5" width="375" height="284"/>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="asO-rj-82y">
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="d5Y-pj-XsI">
<rect key="frame" x="20" y="10" width="335" height="84"/>
<string key="text">Verify this session from one of your others sessions, granting it access to encrypted messages.
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="tIM-sl-gwE">
<rect key="frame" x="0.0" y="0.0" width="375" height="412.5"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IlB-Ch-LEo">
<rect key="frame" x="0.0" y="0.0" width="375" height="412.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="d5Y-pj-XsI">
<rect key="frame" x="20" y="20" width="335" height="84"/>
<string key="text">Verify this session from one of your others sessions, granting it access to encrypted messages.
Use the latest Riot on your other devices:</string>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" translatesAutoresizingMaskIntoConstraints="NO" id="ANK-XS-dY7">
<rect key="frame" x="27.5" y="134" width="320" height="95.5"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" spacing="14" translatesAutoresizingMaskIntoConstraints="NO" id="3at-ql-vhb">
<rect key="frame" x="0.0" y="0.0" width="160" height="95.5"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="monitor" translatesAutoresizingMaskIntoConstraints="NO" id="nrB-Kj-4zE">
<rect key="frame" x="56" y="0.0" width="48" height="48"/>
<constraints>
<constraint firstAttribute="height" constant="48" id="F2W-zC-UJo"/>
<constraint firstAttribute="width" secondItem="nrB-Kj-4zE" secondAttribute="height" multiplier="1:1" id="TOT-bj-1W4"/>
</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="iBP-FF-AYM">
<rect key="frame" x="38.5" y="62" width="83" height="33.5"/>
<string key="text">Riot Web
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" translatesAutoresizingMaskIntoConstraints="NO" id="ANK-XS-dY7">
<rect key="frame" x="27.5" y="144" width="320" height="95.5"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" spacing="14" translatesAutoresizingMaskIntoConstraints="NO" id="3at-ql-vhb">
<rect key="frame" x="0.0" y="0.0" width="160" height="95.5"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="monitor" translatesAutoresizingMaskIntoConstraints="NO" id="nrB-Kj-4zE">
<rect key="frame" x="56" y="0.0" width="48" height="48"/>
<constraints>
<constraint firstAttribute="height" constant="48" id="F2W-zC-UJo"/>
<constraint firstAttribute="width" secondItem="nrB-Kj-4zE" secondAttribute="height" multiplier="1:1" id="TOT-bj-1W4"/>
</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="iBP-FF-AYM">
<rect key="frame" x="38.5" y="62" width="83" height="33.5"/>
<string key="text">Riot Web
Riot Desktop</string>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" spacing="14" translatesAutoresizingMaskIntoConstraints="NO" id="coY-7W-lY7">
<rect key="frame" x="160" y="0.0" width="160" height="95.5"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="smartphone" translatesAutoresizingMaskIntoConstraints="NO" id="P0P-X4-uSQ">
<rect key="frame" x="56" y="0.0" width="48" height="48"/>
<constraints>
<constraint firstAttribute="height" constant="48" id="4NO-k7-6iK"/>
<constraint firstAttribute="width" secondItem="P0P-X4-uSQ" secondAttribute="height" multiplier="1:1" id="AZP-GN-y8E"/>
</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="gLH-sE-KCq">
<rect key="frame" x="22.5" y="62" width="115" height="33.5"/>
<string key="text">Riot iOS
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" spacing="14" translatesAutoresizingMaskIntoConstraints="NO" id="coY-7W-lY7">
<rect key="frame" x="160" y="0.0" width="160" height="95.5"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="smartphone" translatesAutoresizingMaskIntoConstraints="NO" id="P0P-X4-uSQ">
<rect key="frame" x="56" y="0.0" width="48" height="48"/>
<constraints>
<constraint firstAttribute="height" constant="48" id="4NO-k7-6iK"/>
<constraint firstAttribute="width" secondItem="P0P-X4-uSQ" secondAttribute="height" multiplier="1:1" id="AZP-GN-y8E"/>
</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="gLH-sE-KCq">
<rect key="frame" x="22.5" y="62" width="115" height="33.5"/>
<string key="text">Riot iOS
Riot X for Android</string>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<nil key="textColor"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
</subviews>
<constraints>
<constraint firstAttribute="width" constant="320" id="TyM-5Y-YSw"/>
</constraints>
</stackView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="or another cross-signing capable Matrix client" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rFM-AQ-wAB">
<rect key="frame" x="20" y="259.5" width="335" height="14.5"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="12"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="8oJ-o6-DLK">
<rect key="frame" x="20" y="294" width="335" height="118.5"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="nf8-Ye-b9r">
<rect key="frame" x="0.0" y="0.0" width="335" height="118.5"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="OEt-k0-vgM" customClass="RoundedButton" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="0.0" y="10" width="335" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="7ws-Nc-I7y"/>
</constraints>
<inset key="contentEdgeInsets" minX="10" minY="0.0" maxX="10" maxY="0.0"/>
<state key="normal" title="Use a recovery passphrase or key">
<color key="titleColor" red="0.01176470588" green="0.70196078429999997" blue="0.50588235290000005" alpha="1" colorSpace="calibratedRGB"/>
</state>
<connections>
<action selector="recoverSecretsButtonAction:" destination="79A-qb-tmk" eventType="touchUpInside" id="FY5-tR-dyT"/>
</connections>
</button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="If you can't accessing an existing session" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4Ou-cM-K9C">
<rect key="frame" x="20" y="64" width="295" height="24.5"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="12"/>
<color key="textColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="4Ou-cM-K9C" secondAttribute="trailing" constant="20" id="6a1-gA-Cev"/>
<constraint firstAttribute="bottom" secondItem="4Ou-cM-K9C" secondAttribute="bottom" constant="30" id="X1c-Yc-qLh"/>
<constraint firstItem="4Ou-cM-K9C" firstAttribute="top" secondItem="OEt-k0-vgM" secondAttribute="bottom" constant="10" id="Y5b-Bf-IYu"/>
<constraint firstItem="OEt-k0-vgM" firstAttribute="top" secondItem="nf8-Ye-b9r" secondAttribute="top" constant="10" id="fvJ-vZ-MMa"/>
<constraint firstItem="OEt-k0-vgM" firstAttribute="leading" secondItem="nf8-Ye-b9r" secondAttribute="leading" id="loc-cf-E6p"/>
<constraint firstItem="4Ou-cM-K9C" firstAttribute="leading" secondItem="nf8-Ye-b9r" secondAttribute="leading" constant="20" id="o3E-Q9-7h1"/>
<constraint firstAttribute="trailing" secondItem="OEt-k0-vgM" secondAttribute="trailing" id="yQK-YS-7Yr"/>
</constraints>
</view>
</subviews>
<constraints>
<constraint firstItem="nf8-Ye-b9r" firstAttribute="width" secondItem="8oJ-o6-DLK" secondAttribute="width" id="ZNi-0G-uDR"/>
</constraints>
</stackView>
</subviews>
</stackView>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="d5Y-pj-XsI" secondAttribute="trailing" constant="20" id="3Mi-wg-su3"/>
<constraint firstAttribute="height" priority="250" id="72E-My-WHK"/>
<constraint firstItem="ANK-XS-dY7" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="IlB-Ch-LEo" secondAttribute="leading" id="9BR-a1-3By"/>
<constraint firstAttribute="bottom" secondItem="8oJ-o6-DLK" secondAttribute="bottom" id="CB2-Nd-n2g"/>
<constraint firstItem="rFM-AQ-wAB" firstAttribute="top" secondItem="ANK-XS-dY7" secondAttribute="bottom" constant="20" id="Goe-Tt-Jbm"/>
<constraint firstItem="d5Y-pj-XsI" firstAttribute="leading" secondItem="IlB-Ch-LEo" secondAttribute="leading" constant="20" id="Okc-DX-xdE"/>
<constraint firstItem="d5Y-pj-XsI" firstAttribute="top" secondItem="IlB-Ch-LEo" secondAttribute="top" constant="20" id="Pkt-ox-zZs"/>
<constraint firstItem="rFM-AQ-wAB" firstAttribute="leading" secondItem="IlB-Ch-LEo" secondAttribute="leading" constant="20" id="PtP-G3-lC6"/>
<constraint firstAttribute="trailing" secondItem="rFM-AQ-wAB" secondAttribute="trailing" constant="20" id="Q78-Oe-Lh2"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="ANK-XS-dY7" secondAttribute="trailing" id="RQI-kF-Z1h"/>
<constraint firstItem="8oJ-o6-DLK" firstAttribute="leading" secondItem="IlB-Ch-LEo" secondAttribute="leading" constant="20" id="RtP-rm-bjH"/>
<constraint firstItem="8oJ-o6-DLK" firstAttribute="top" secondItem="rFM-AQ-wAB" secondAttribute="bottom" constant="20" id="dvv-3U-uH4"/>
<constraint firstItem="ANK-XS-dY7" firstAttribute="top" secondItem="d5Y-pj-XsI" secondAttribute="bottom" constant="40" id="gnp-AK-DYa"/>
<constraint firstItem="ANK-XS-dY7" firstAttribute="centerX" secondItem="IlB-Ch-LEo" secondAttribute="centerX" id="nEo-IT-GtP"/>
<constraint firstAttribute="trailing" secondItem="8oJ-o6-DLK" secondAttribute="trailing" constant="20" id="vev-7p-7ua"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="width" constant="320" id="TyM-5Y-YSw"/>
<constraint firstItem="IlB-Ch-LEo" firstAttribute="centerX" secondItem="tIM-sl-gwE" secondAttribute="centerX" id="428-8q-pvc"/>
<constraint firstAttribute="bottom" secondItem="IlB-Ch-LEo" secondAttribute="bottom" id="8t4-aW-4OV"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="IlB-Ch-LEo" secondAttribute="trailing" id="EBp-6W-LtY"/>
<constraint firstItem="IlB-Ch-LEo" firstAttribute="top" secondItem="tIM-sl-gwE" secondAttribute="top" id="HqF-24-jLe"/>
<constraint firstItem="IlB-Ch-LEo" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="tIM-sl-gwE" secondAttribute="leading" id="d4W-6f-aGG"/>
</constraints>
</stackView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="or another cross-signing capable Matrix client" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rFM-AQ-wAB">
<rect key="frame" x="20" y="249.5" width="335" height="14.5"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="12"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="d5Y-pj-XsI" secondAttribute="trailing" constant="20" id="3Mi-wg-su3"/>
<constraint firstAttribute="bottom" secondItem="rFM-AQ-wAB" secondAttribute="bottom" constant="20" id="4Gy-0v-H5m"/>
<constraint firstAttribute="height" priority="250" id="72E-My-WHK"/>
<constraint firstItem="ANK-XS-dY7" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="IlB-Ch-LEo" secondAttribute="leading" id="9BR-a1-3By"/>
<constraint firstItem="rFM-AQ-wAB" firstAttribute="top" secondItem="ANK-XS-dY7" secondAttribute="bottom" constant="20" id="Goe-Tt-Jbm"/>
<constraint firstItem="d5Y-pj-XsI" firstAttribute="leading" secondItem="IlB-Ch-LEo" secondAttribute="leading" constant="20" id="Okc-DX-xdE"/>
<constraint firstItem="d5Y-pj-XsI" firstAttribute="top" secondItem="IlB-Ch-LEo" secondAttribute="top" constant="10" id="Pkt-ox-zZs"/>
<constraint firstItem="rFM-AQ-wAB" firstAttribute="leading" secondItem="IlB-Ch-LEo" secondAttribute="leading" constant="20" id="PtP-G3-lC6"/>
<constraint firstAttribute="trailing" secondItem="rFM-AQ-wAB" secondAttribute="trailing" constant="20" id="Q78-Oe-Lh2"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="ANK-XS-dY7" secondAttribute="trailing" id="RQI-kF-Z1h"/>
<constraint firstItem="ANK-XS-dY7" firstAttribute="top" secondItem="d5Y-pj-XsI" secondAttribute="bottom" constant="40" id="gnp-AK-DYa"/>
<constraint firstItem="ANK-XS-dY7" firstAttribute="centerX" secondItem="IlB-Ch-LEo" secondAttribute="centerX" id="nEo-IT-GtP"/>
<constraint firstAttribute="bottom" secondItem="tIM-sl-gwE" secondAttribute="bottom" id="I5t-jH-6vU"/>
<constraint firstItem="tIM-sl-gwE" firstAttribute="width" secondItem="asO-rj-82y" secondAttribute="width" id="Ngd-NZ-QSP"/>
<constraint firstItem="tIM-sl-gwE" firstAttribute="leading" secondItem="asO-rj-82y" secondAttribute="leading" id="clc-OI-kPa"/>
<constraint firstItem="tIM-sl-gwE" firstAttribute="top" secondItem="asO-rj-82y" secondAttribute="top" id="hZy-Kz-O3K"/>
<constraint firstAttribute="trailing" secondItem="tIM-sl-gwE" secondAttribute="trailing" id="k4M-hm-HD7"/>
</constraints>
</view>
</scrollView>
</subviews>
<color key="backgroundColor" red="0.94509803920000002" green="0.96078431369999995" blue="0.97254901959999995" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstItem="IlB-Ch-LEo" firstAttribute="centerY" secondItem="GnW-bb-rsL" secondAttribute="centerY" id="Hh1-tV-pXA"/>
<constraint firstItem="IlB-Ch-LEo" firstAttribute="trailing" secondItem="GnW-bb-rsL" secondAttribute="trailing" id="Kbx-ln-UzT"/>
<constraint firstItem="IlB-Ch-LEo" firstAttribute="leading" secondItem="GnW-bb-rsL" secondAttribute="leading" id="f6d-Hi-qnR"/>
<constraint firstItem="asO-rj-82y" firstAttribute="trailing" secondItem="GnW-bb-rsL" secondAttribute="trailing" id="Isw-tg-7go"/>
<constraint firstItem="GnW-bb-rsL" firstAttribute="leading" secondItem="asO-rj-82y" secondAttribute="leading" id="YWL-Xu-ApZ"/>
<constraint firstItem="GnW-bb-rsL" firstAttribute="top" secondItem="asO-rj-82y" secondAttribute="top" id="b3e-2d-oiV"/>
<constraint firstAttribute="bottomMargin" secondItem="asO-rj-82y" secondAttribute="bottom" id="wMk-Oq-DwP"/>
</constraints>
<viewLayoutGuide key="safeArea" id="GnW-bb-rsL"/>
</view>
@@ -117,6 +188,9 @@ Riot X for Android</string>
<outlet property="informationLabel" destination="d5Y-pj-XsI" id="TMb-bc-58a"/>
<outlet property="mobileClientImageView" destination="P0P-X4-uSQ" id="WtT-ix-yq8"/>
<outlet property="mobileClientLabel" destination="gLH-sE-KCq" id="jQ0-7U-mr8"/>
<outlet property="recoverSecretsAdditionalInformationLabel" destination="4Ou-cM-K9C" id="80N-lF-x2L"/>
<outlet property="recoverSecretsButton" destination="OEt-k0-vgM" id="RHU-ps-4m7"/>
<outlet property="recoverSecretsContainerView" destination="nf8-Ye-b9r" id="4az-pe-0Uc"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="OMs-Ee-CjK" userLabel="First Responder" sceneMemberID="firstResponder"/>
@@ -125,7 +199,7 @@ Riot X for Android</string>
</scene>
</scenes>
<resources>
<image name="monitor" width="24" height="24"/>
<image name="smartphone" width="24" height="24"/>
<image name="monitor" width="48" height="48"/>
<image name="smartphone" width="48" height="48"/>
</resources>
</document>
@@ -40,6 +40,11 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController {
@IBOutlet private weak var additionalInformationLabel: UILabel!
@IBOutlet private weak var recoverSecretsContainerView: UIView!
@IBOutlet private weak var recoverSecretsButton: RoundedButton!
@IBOutlet private weak var recoverSecretsAdditionalInformationLabel: UILabel!
// MARK: Private
private var viewModel: KeyVerificationSelfVerifyWaitViewModelType!
@@ -112,6 +117,8 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController {
self?.cancelButtonAction()
}
self.vc_removeBackTitle()
self.navigationItem.rightBarButtonItem = cancelBarButtonItem
self.cancelBarButtonItem = cancelBarButtonItem
@@ -126,14 +133,16 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController {
self.mobileClientImageView.image = Asset.Images.smartphone.image.withRenderingMode(.alwaysTemplate)
self.additionalInformationLabel.text = VectorL10n.deviceVerificationSelfVerifyWaitAdditionalInformation
self.recoverSecretsAdditionalInformationLabel.text = VectorL10n.deviceVerificationSelfVerifyWaitRecoverSecretsAdditionalInformation
}
private func render(viewState: KeyVerificationSelfVerifyWaitViewState) {
switch viewState {
case .loading:
self.renderLoading()
case .loaded(let isNewSignIn):
self.renderLoaded(isNewSignIn: isNewSignIn)
case .loaded(let viewData):
self.renderLoaded(viewData: viewData)
case .cancelled(let reason):
self.renderCancelled(reason: reason)
case .cancelledByMe(let reason):
@@ -147,11 +156,32 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController {
self.activityPresenter.presentActivityIndicator(on: self.view, animated: true)
}
private func renderLoaded(isNewSignIn: Bool) {
private func renderLoaded(viewData: KeyVerificationSelfVerifyWaitViewData) {
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
self.title = isNewSignIn ? VectorL10n.deviceVerificationSelfVerifyWaitNewSignInTitle : VectorL10n.deviceVerificationSelfVerifyWaitTitle
self.cancelBarButtonItem?.title = isNewSignIn ? VectorL10n.skip : VectorL10n.cancel
self.title = viewData.isNewSignIn ? VectorL10n.deviceVerificationSelfVerifyWaitNewSignInTitle : VectorL10n.deviceVerificationSelfVerifyWaitTitle
self.cancelBarButtonItem?.title = viewData.isNewSignIn ? VectorL10n.skip : VectorL10n.cancel
let hideRecoverSecrets: Bool
let recoverSecretsButtonTitle: String?
switch viewData.secretsRecoveryAvailability {
case .notAvailable:
hideRecoverSecrets = true
recoverSecretsButtonTitle = nil
case .available(let secretsRecoveryMode):
hideRecoverSecrets = false
switch secretsRecoveryMode {
case .passphraseOrKey:
recoverSecretsButtonTitle = VectorL10n.deviceVerificationSelfVerifyWaitRecoverSecretsWithPassphrase
case .onlyKey:
recoverSecretsButtonTitle = VectorL10n.deviceVerificationSelfVerifyWaitRecoverSecretsWithoutPassphrase
}
}
self.recoverSecretsContainerView.isHidden = hideRecoverSecrets
self.recoverSecretsButton.setTitle(recoverSecretsButtonTitle, for: .normal)
}
private func renderCancelled(reason: MXTransactionCancelCode) {
@@ -184,6 +214,10 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController {
private func cancelButtonAction() {
self.viewModel.process(viewAction: .cancel)
}
@IBAction private func recoverSecretsButtonAction(_ sender: Any) {
self.viewModel.process(viewAction: .recoverSecrets)
}
}
@@ -28,6 +28,9 @@ final class KeyVerificationSelfVerifyWaitViewModel: KeyVerificationSelfVerifyWai
private let keyVerificationService: KeyVerificationService
private let verificationManager: MXKeyVerificationManager
private let isNewSignIn: Bool
private lazy var secretsRecoveryAvailability: SecretsRecoveryAvailability = {
return self.secretsRecoveryAvailability(from: self.session.crypto.recoveryService)
}()
private var keyVerificationRequest: MXKeyVerificationRequest?
@@ -57,6 +60,12 @@ final class KeyVerificationSelfVerifyWaitViewModel: KeyVerificationSelfVerifyWai
self.loadData()
case .cancel:
self.cancel()
case .recoverSecrets:
switch self.secretsRecoveryAvailability {
case .notAvailable:
fatalError("Should not happen: When recovery is not available button is hidden")
case .available(let secretsRecoveryMode): self.coordinatorDelegate?.keyVerificationSelfVerifyWaitViewModel(self, wantsToRecoverSecretsWith: secretsRecoveryMode)
}
}
}
@@ -80,11 +89,22 @@ final class KeyVerificationSelfVerifyWaitViewModel: KeyVerificationSelfVerifyWai
})
}
// let recoverySecretsStatus = self.recoveryStatus(from: self.session.crypto.recoveryService)
let viewData = KeyVerificationSelfVerifyWaitViewData(isNewSignIn: self.isNewSignIn, secretsRecoveryAvailability: self.secretsRecoveryAvailability)
self.registerKeyVerificationManagerNewRequestNotification(for: self.verificationManager)
self.update(viewState: .loaded(self.isNewSignIn))
self.update(viewState: .loaded(viewData))
self.registerTransactionDidStateChangeNotification()
}
private func secretsRecoveryAvailability(from recoveryService: MXRecoveryService) -> SecretsRecoveryAvailability {
guard recoveryService.hasRecovery() else {
return .notAvailable
}
let secretsRecoveryMode: SecretsRecoveryMode = recoveryService.usePassphrase() ? .passphraseOrKey : .onlyKey
return .available(secretsRecoveryMode)
}
private func cancel() {
self.unregisterKeyVerificationManagerNewRequestNotification()
self.cancelKeyVerificationRequest()
@@ -26,6 +26,7 @@ protocol KeyVerificationSelfVerifyWaitViewModelCoordinatorDelegate: class {
func keyVerificationSelfVerifyWaitViewModel(_ viewModel: KeyVerificationSelfVerifyWaitViewModelType, didAcceptKeyVerificationRequest keyVerificationRequest: MXKeyVerificationRequest)
func keyVerificationSelfVerifyWaitViewModel(_ viewModel: KeyVerificationSelfVerifyWaitViewModelType, didAcceptIncomingSASTransaction incomingSASTransaction: MXIncomingSASTransaction)
func keyVerificationSelfVerifyWaitViewModelDidCancel(_ viewModel: KeyVerificationSelfVerifyWaitViewModelType)
func keyVerificationSelfVerifyWaitViewModel(_ viewModel: KeyVerificationSelfVerifyWaitViewModelType, wantsToRecoverSecretsWith secretsRecoveryMode: SecretsRecoveryMode)
}
/// Protocol describing the view model used by `KeyVerificationSelfVerifyWaitViewController`
@@ -18,10 +18,20 @@
import Foundation
enum SecretsRecoveryAvailability {
case notAvailable
case available(_ mode: SecretsRecoveryMode)
}
struct KeyVerificationSelfVerifyWaitViewData {
let isNewSignIn: Bool
let secretsRecoveryAvailability: SecretsRecoveryAvailability
}
/// KeyVerificationSelfVerifyWaitViewController view state
enum KeyVerificationSelfVerifyWaitViewState {
case loading
case loaded(_ isNewSignIn: Bool)
case loaded(_ viewData: KeyVerificationSelfVerifyWaitViewData)
case cancelled(MXTransactionCancelCode)
case cancelledByMe(MXTransactionCancelCode)
case error(Error)