mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-19 16:13:42 +02:00
Implement manually verify device screen.
This commit is contained in:
+71
@@ -0,0 +1,71 @@
|
||||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh KeyVerification/Device/ManuallyVerify KeyVerificationManuallyVerify
|
||||
/*
|
||||
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 KeyVerificationManuallyVerifyCoordinator: KeyVerificationManuallyVerifyCoordinatorType {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let session: MXSession
|
||||
private var keyVerificationManuallyVerifyViewModel: KeyVerificationManuallyVerifyViewModelType
|
||||
private let keyVerificationManuallyVerifyViewController: KeyVerificationManuallyVerifyViewController
|
||||
|
||||
// MARK: Public
|
||||
|
||||
// Must be used only internally
|
||||
var childCoordinators: [Coordinator] = []
|
||||
|
||||
weak var delegate: KeyVerificationManuallyVerifyCoordinatorDelegate?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(session: MXSession, deviceId: String, userId: String) {
|
||||
self.session = session
|
||||
|
||||
let keyVerificationManuallyVerifyViewModel = KeyVerificationManuallyVerifyViewModel(session: self.session, deviceId: deviceId, userId: userId)
|
||||
let keyVerificationManuallyVerifyViewController = KeyVerificationManuallyVerifyViewController.instantiate(with: keyVerificationManuallyVerifyViewModel)
|
||||
self.keyVerificationManuallyVerifyViewModel = keyVerificationManuallyVerifyViewModel
|
||||
self.keyVerificationManuallyVerifyViewController = keyVerificationManuallyVerifyViewController
|
||||
}
|
||||
|
||||
// MARK: - Public methods
|
||||
|
||||
func start() {
|
||||
self.keyVerificationManuallyVerifyViewModel.coordinatorDelegate = self
|
||||
}
|
||||
|
||||
func toPresentable() -> UIViewController {
|
||||
return self.keyVerificationManuallyVerifyViewController
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - KeyVerificationManuallyVerifyViewModelCoordinatorDelegate
|
||||
extension KeyVerificationManuallyVerifyCoordinator: KeyVerificationManuallyVerifyViewModelCoordinatorDelegate {
|
||||
|
||||
func keyVerificationManuallyVerifyViewModel(_ viewModel: KeyVerificationManuallyVerifyViewModelType, didVerifiedDeviceWithId deviceId: String, of userId: String) {
|
||||
self.delegate?.keyVerificationManuallyVerifyCoordinator(self, didVerifiedDeviceWithId: deviceId, of: userId)
|
||||
}
|
||||
|
||||
func keyVerificationManuallyVerifyViewModelDidCancel(_ viewModel: KeyVerificationManuallyVerifyViewModelType) {
|
||||
self.delegate?.keyVerificationManuallyVerifyCoordinatorDidCancel(self)
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh KeyVerification/Device/ManuallyVerify KeyVerificationManuallyVerify
|
||||
/*
|
||||
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 KeyVerificationManuallyVerifyCoordinatorDelegate: class {
|
||||
func keyVerificationManuallyVerifyCoordinator(_ coordinator: KeyVerificationManuallyVerifyCoordinatorType, didVerifiedDeviceWithId deviceId: String, of userId: String)
|
||||
func keyVerificationManuallyVerifyCoordinatorDidCancel(_ coordinator: KeyVerificationManuallyVerifyCoordinatorType)
|
||||
}
|
||||
|
||||
/// `KeyVerificationManuallyVerifyCoordinatorType` is a protocol describing a Coordinator that handle key backup setup passphrase navigation flow.
|
||||
protocol KeyVerificationManuallyVerifyCoordinatorType: Coordinator, Presentable {
|
||||
var delegate: KeyVerificationManuallyVerifyCoordinatorDelegate? { get }
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh KeyVerification/Device/ManuallyVerify KeyVerificationManuallyVerify
|
||||
/*
|
||||
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
|
||||
|
||||
/// KeyVerificationManuallyVerifyViewController view actions exposed to view model
|
||||
enum KeyVerificationManuallyVerifyViewAction {
|
||||
case loadData
|
||||
case verify
|
||||
case cancel
|
||||
}
|
||||
+232
@@ -0,0 +1,232 @@
|
||||
<?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="V8j-Lb-PgC">
|
||||
<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>
|
||||
<!--Key Verification Manually Verify View Controller-->
|
||||
<scene sceneID="mt5-wz-YKA">
|
||||
<objects>
|
||||
<viewController extendedLayoutIncludesOpaqueBars="YES" automaticallyAdjustsScrollViewInsets="NO" id="V8j-Lb-PgC" customClass="KeyVerificationManuallyVerifyViewController" customModule="Riot" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="EL9-GA-lwo">
|
||||
<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="9U2-KL-ZVA">
|
||||
<rect key="frame" x="0.0" y="44" width="414" height="852"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="e7g-um-WO4">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="502"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="voD-3Q-ryt">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="502"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" text="Confirm by comparing the following with the User Settings in your other session:" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="RIj-L9-tZn">
|
||||
<rect key="frame" x="20" y="20" width="374" height="33.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="12" translatesAutoresizingMaskIntoConstraints="NO" id="qfH-9X-kBZ">
|
||||
<rect key="frame" x="20" y="73.5" width="374" height="201"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="YcY-tZ-Ga6">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="59"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Session name" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="tp3-dZ-JyO">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="17"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="14"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="https://riot.im" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9SQ-lH-Hur">
|
||||
<rect key="frame" x="0.0" y="22" width="374" height="37"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="tp3-dZ-JyO" firstAttribute="top" secondItem="YcY-tZ-Ga6" secondAttribute="top" id="Eai-tB-VyY"/>
|
||||
<constraint firstAttribute="bottom" secondItem="9SQ-lH-Hur" secondAttribute="bottom" id="MOQ-bv-PAZ"/>
|
||||
<constraint firstItem="9SQ-lH-Hur" firstAttribute="top" secondItem="tp3-dZ-JyO" secondAttribute="bottom" constant="5" id="RuS-7X-CNf"/>
|
||||
<constraint firstAttribute="height" priority="250" id="Y0c-6A-FOP"/>
|
||||
<constraint firstItem="9SQ-lH-Hur" firstAttribute="leading" secondItem="tp3-dZ-JyO" secondAttribute="leading" id="Y9I-6j-wkw"/>
|
||||
<constraint firstAttribute="trailing" secondItem="tp3-dZ-JyO" secondAttribute="trailing" id="cVj-3V-bmi"/>
|
||||
<constraint firstItem="tp3-dZ-JyO" firstAttribute="leading" secondItem="YcY-tZ-Ga6" secondAttribute="leading" id="dDq-eF-TRE"/>
|
||||
<constraint firstItem="9SQ-lH-Hur" firstAttribute="trailing" secondItem="tp3-dZ-JyO" secondAttribute="trailing" id="rzJ-k3-tSZ"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jWK-JI-wHI">
|
||||
<rect key="frame" x="0.0" y="71" width="374" height="59"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Session ID" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uVC-qK-ET7">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="17"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="14"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="https://riot.im" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="WHf-qc-H4w">
|
||||
<rect key="frame" x="0.0" y="22" width="374" height="37"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="uVC-qK-ET7" secondAttribute="trailing" id="Cq3-wf-eMz"/>
|
||||
<constraint firstAttribute="height" priority="250" id="IhG-aQ-Ez2"/>
|
||||
<constraint firstItem="WHf-qc-H4w" firstAttribute="top" secondItem="uVC-qK-ET7" secondAttribute="bottom" constant="5" id="Ivk-6g-bPa"/>
|
||||
<constraint firstItem="WHf-qc-H4w" firstAttribute="trailing" secondItem="uVC-qK-ET7" secondAttribute="trailing" id="MFO-Gp-1oy"/>
|
||||
<constraint firstItem="uVC-qK-ET7" firstAttribute="top" secondItem="jWK-JI-wHI" secondAttribute="top" id="POZ-uv-KVR"/>
|
||||
<constraint firstItem="WHf-qc-H4w" firstAttribute="leading" secondItem="uVC-qK-ET7" secondAttribute="leading" id="o6y-OG-KcW"/>
|
||||
<constraint firstAttribute="bottom" secondItem="WHf-qc-H4w" secondAttribute="bottom" id="pX1-4I-5fr"/>
|
||||
<constraint firstItem="uVC-qK-ET7" firstAttribute="leading" secondItem="jWK-JI-wHI" secondAttribute="leading" id="qky-qV-dcB"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="EKr-6X-weJ">
|
||||
<rect key="frame" x="0.0" y="142" width="374" height="59"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Session key" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="tBF-i0-Q4C">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="17"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="14"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="https://riot.im" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5fG-Wi-cVH">
|
||||
<rect key="frame" x="0.0" y="22" width="374" height="37"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="5fG-Wi-cVH" firstAttribute="leading" secondItem="tBF-i0-Q4C" secondAttribute="leading" id="Kyc-YY-gzQ"/>
|
||||
<constraint firstAttribute="bottom" secondItem="5fG-Wi-cVH" secondAttribute="bottom" id="ZCc-3Y-ECo"/>
|
||||
<constraint firstItem="5fG-Wi-cVH" firstAttribute="trailing" secondItem="tBF-i0-Q4C" secondAttribute="trailing" id="Zga-sP-Zc6"/>
|
||||
<constraint firstItem="5fG-Wi-cVH" firstAttribute="top" secondItem="tBF-i0-Q4C" secondAttribute="bottom" constant="5" id="cr4-9q-O5W"/>
|
||||
<constraint firstItem="tBF-i0-Q4C" firstAttribute="top" secondItem="EKr-6X-weJ" secondAttribute="top" id="jVr-qa-EU3"/>
|
||||
<constraint firstAttribute="trailing" secondItem="tBF-i0-Q4C" secondAttribute="trailing" id="mPM-qs-32S"/>
|
||||
<constraint firstAttribute="height" priority="250" id="sHG-MG-dz7"/>
|
||||
<constraint firstItem="tBF-i0-Q4C" firstAttribute="leading" secondItem="EKr-6X-weJ" secondAttribute="leading" id="taB-4o-BQf"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="YcY-tZ-Ga6" firstAttribute="width" secondItem="qfH-9X-kBZ" secondAttribute="width" id="5XJ-Oq-N4o"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" text="If they don't match, the security of your communication may be compromised." lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="wT1-a7-XOh">
|
||||
<rect key="frame" x="20" y="294.5" width="374" height="33.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" alignment="center" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="mVH-0o-ZrL">
|
||||
<rect key="frame" x="20" y="358" width="374" height="44"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="6wi-YQ-QmI" customClass="RoundedButton" customModule="Riot" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="177" height="44"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<inset key="contentEdgeInsets" minX="10" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="Cancel">
|
||||
<color key="titleColor" red="1" green="0.29411764709999999" blue="0.33333333329999998" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="cancelButtonAction:" destination="V8j-Lb-PgC" eventType="touchUpInside" id="ytK-85-toE"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="3pY-eX-Qfn" customClass="RoundedButton" customModule="Riot" customModuleProvider="target">
|
||||
<rect key="frame" x="197" y="0.0" width="177" height="44"/>
|
||||
<inset key="contentEdgeInsets" minX="10" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="Verify">
|
||||
<color key="titleColor" red="0.01176470588" green="0.70196078429999997" blue="0.50588235290000005" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="verifyButtonAction:" destination="V8j-Lb-PgC" eventType="touchUpInside" id="cfQ-bJ-jrr"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" priority="750" constant="44" id="BCf-fL-ZMJ"/>
|
||||
<constraint firstItem="3pY-eX-Qfn" firstAttribute="height" secondItem="mVH-0o-ZrL" secondAttribute="height" priority="999" id="WUy-05-S5d"/>
|
||||
<constraint firstItem="6wi-YQ-QmI" firstAttribute="height" secondItem="mVH-0o-ZrL" secondAttribute="height" priority="999" id="mZw-S9-WUz"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="mVH-0o-ZrL" firstAttribute="leading" secondItem="voD-3Q-ryt" secondAttribute="leading" constant="20" id="1x2-p1-gBl"/>
|
||||
<constraint firstAttribute="bottom" secondItem="mVH-0o-ZrL" secondAttribute="bottom" constant="100" id="3Ks-I4-3Pa"/>
|
||||
<constraint firstItem="qfH-9X-kBZ" firstAttribute="top" secondItem="RIj-L9-tZn" secondAttribute="bottom" constant="20" id="7wU-kb-txG"/>
|
||||
<constraint firstItem="wT1-a7-XOh" firstAttribute="trailing" secondItem="qfH-9X-kBZ" secondAttribute="trailing" id="9ws-hQ-6ag"/>
|
||||
<constraint firstItem="RIj-L9-tZn" firstAttribute="leading" secondItem="voD-3Q-ryt" secondAttribute="leading" constant="20" id="B24-EF-h5n"/>
|
||||
<constraint firstItem="RIj-L9-tZn" firstAttribute="top" secondItem="voD-3Q-ryt" secondAttribute="top" constant="20" id="BMO-Kj-hUI"/>
|
||||
<constraint firstItem="qfH-9X-kBZ" firstAttribute="trailing" secondItem="RIj-L9-tZn" secondAttribute="trailing" id="f5i-AM-Rae"/>
|
||||
<constraint firstAttribute="width" priority="750" constant="500" id="glD-Sz-73O"/>
|
||||
<constraint firstAttribute="trailing" secondItem="mVH-0o-ZrL" secondAttribute="trailing" constant="20" id="oL7-Le-sqy"/>
|
||||
<constraint firstItem="mVH-0o-ZrL" firstAttribute="top" secondItem="wT1-a7-XOh" secondAttribute="bottom" constant="30" id="rxl-Le-eol"/>
|
||||
<constraint firstItem="qfH-9X-kBZ" firstAttribute="leading" secondItem="RIj-L9-tZn" secondAttribute="leading" id="sNm-19-5lu"/>
|
||||
<constraint firstAttribute="trailing" secondItem="RIj-L9-tZn" secondAttribute="trailing" constant="20" id="ucH-Ci-kvn"/>
|
||||
<constraint firstItem="wT1-a7-XOh" firstAttribute="leading" secondItem="qfH-9X-kBZ" secondAttribute="leading" id="w6D-nQ-QPq"/>
|
||||
<constraint firstItem="wT1-a7-XOh" firstAttribute="top" secondItem="qfH-9X-kBZ" secondAttribute="bottom" constant="20" id="zv7-lG-ks8"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="voD-3Q-ryt" secondAttribute="bottom" id="63a-5e-ptU"/>
|
||||
<constraint firstItem="voD-3Q-ryt" firstAttribute="centerX" secondItem="e7g-um-WO4" secondAttribute="centerX" id="P2G-mq-gQW"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="voD-3Q-ryt" secondAttribute="trailing" id="QgV-SO-5yf"/>
|
||||
<constraint firstItem="voD-3Q-ryt" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="e7g-um-WO4" secondAttribute="leading" id="YPo-u1-PtT"/>
|
||||
<constraint firstItem="voD-3Q-ryt" firstAttribute="top" secondItem="e7g-um-WO4" secondAttribute="top" id="rhQ-96-szL"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="e7g-um-WO4" secondAttribute="trailing" id="GyG-Fh-PME"/>
|
||||
<constraint firstItem="e7g-um-WO4" firstAttribute="width" secondItem="9U2-KL-ZVA" secondAttribute="width" id="Ok2-WQ-Zgc"/>
|
||||
<constraint firstAttribute="bottom" secondItem="e7g-um-WO4" secondAttribute="bottom" id="Y46-NP-zAc"/>
|
||||
<constraint firstItem="e7g-um-WO4" firstAttribute="leading" secondItem="9U2-KL-ZVA" secondAttribute="leading" id="aoV-Yh-AcD"/>
|
||||
<constraint firstItem="e7g-um-WO4" firstAttribute="top" secondItem="9U2-KL-ZVA" secondAttribute="top" id="pFN-bA-SHw"/>
|
||||
</constraints>
|
||||
</scrollView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.94509803921568625" green="0.96078431372549022" blue="0.97254901960784312" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="9U2-KL-ZVA" secondAttribute="bottom" id="7Cb-nY-CsO"/>
|
||||
<constraint firstItem="9U2-KL-ZVA" firstAttribute="leading" secondItem="bFg-jh-JZB" secondAttribute="leading" id="GdQ-hK-muG"/>
|
||||
<constraint firstItem="bFg-jh-JZB" firstAttribute="trailing" secondItem="9U2-KL-ZVA" secondAttribute="trailing" id="sbD-ek-vGJ"/>
|
||||
<constraint firstItem="bFg-jh-JZB" firstAttribute="top" secondItem="9U2-KL-ZVA" secondAttribute="top" id="wTB-V6-IHV"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="bFg-jh-JZB"/>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="additionalInformationLabel" destination="wT1-a7-XOh" id="5a3-Q0-gKF"/>
|
||||
<outlet property="cancelButton" destination="6wi-YQ-QmI" id="0t1-M8-B6e"/>
|
||||
<outlet property="deviceIdLabel" destination="WHf-qc-H4w" id="jmP-9Y-cXH"/>
|
||||
<outlet property="deviceIdTitleLabel" destination="uVC-qK-ET7" id="ObX-Ys-hcO"/>
|
||||
<outlet property="deviceKeyLabel" destination="5fG-Wi-cVH" id="a71-J8-TuA"/>
|
||||
<outlet property="deviceKeyTitleLabel" destination="tBF-i0-Q4C" id="hBk-B1-Htu"/>
|
||||
<outlet property="deviceNameLabel" destination="9SQ-lH-Hur" id="jqo-Y2-JzC"/>
|
||||
<outlet property="deviceNameTitleLabel" destination="tp3-dZ-JyO" id="4Mt-qK-wfm"/>
|
||||
<outlet property="informationLabel" destination="RIj-L9-tZn" id="TlB-EU-XGq"/>
|
||||
<outlet property="scrollView" destination="9U2-KL-ZVA" id="ojG-2y-X7b"/>
|
||||
<outlet property="verifyButton" destination="3pY-eX-Qfn" id="qhX-1D-gp9"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="zK0-v6-7Wt" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-3198.5507246376815" y="-647.54464285714278"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
+224
@@ -0,0 +1,224 @@
|
||||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh KeyVerification/Device/ManuallyVerify KeyVerificationManuallyVerify
|
||||
/*
|
||||
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 KeyVerificationManuallyVerifyViewController: UIViewController {
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Outlets
|
||||
|
||||
@IBOutlet private weak var scrollView: UIScrollView!
|
||||
|
||||
@IBOutlet private weak var informationLabel: UILabel!
|
||||
|
||||
@IBOutlet private weak var deviceNameTitleLabel: UILabel!
|
||||
@IBOutlet private weak var deviceNameLabel: UILabel!
|
||||
|
||||
@IBOutlet private weak var deviceIdTitleLabel: UILabel!
|
||||
@IBOutlet private weak var deviceIdLabel: UILabel!
|
||||
|
||||
@IBOutlet private weak var deviceKeyTitleLabel: UILabel!
|
||||
@IBOutlet private weak var deviceKeyLabel: UILabel!
|
||||
|
||||
@IBOutlet private weak var additionalInformationLabel: UILabel!
|
||||
|
||||
@IBOutlet private weak var verifyButton: RoundedButton!
|
||||
@IBOutlet private weak var cancelButton: RoundedButton!
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private var viewModel: KeyVerificationManuallyVerifyViewModelType!
|
||||
private var theme: Theme!
|
||||
private var errorPresenter: MXKErrorPresentation!
|
||||
private var activityPresenter: ActivityIndicatorPresenter!
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
class func instantiate(with viewModel: KeyVerificationManuallyVerifyViewModelType) -> KeyVerificationManuallyVerifyViewController {
|
||||
let viewController = StoryboardScene.KeyVerificationManuallyVerifyViewController.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)
|
||||
|
||||
if let navigationController = self.navigationController {
|
||||
if navigationController.navigationBar.isHidden == true {
|
||||
self.navigationItem.hidesBackButton = true
|
||||
// Show navigation bar if needed
|
||||
navigationController.setNavigationBarHidden(false, animated: animated)
|
||||
} else {
|
||||
// Hide back button
|
||||
self.navigationItem.setHidesBackButton(true, animated: animated)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func viewDidLayoutSubviews() {
|
||||
super.viewDidLayoutSubviews()
|
||||
|
||||
// Fix label height after orientation change. See here https://www.objc.io/issues/3-views/advanced-auto-layout-toolbox/#intrinsic-content-size-of-multi-line-text for more information.
|
||||
self.informationLabel.vc_fixMultilineHeight()
|
||||
self.deviceNameTitleLabel.vc_fixMultilineHeight()
|
||||
self.deviceNameLabel.vc_fixMultilineHeight()
|
||||
self.deviceIdLabel.vc_fixMultilineHeight()
|
||||
self.deviceIdTitleLabel.vc_fixMultilineHeight()
|
||||
self.deviceKeyTitleLabel.vc_fixMultilineHeight()
|
||||
self.deviceKeyLabel.vc_fixMultilineHeight()
|
||||
self.additionalInformationLabel.vc_fixMultilineHeight()
|
||||
|
||||
self.view.layoutIfNeeded()
|
||||
}
|
||||
|
||||
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.informationLabel.textColor = theme.textPrimaryColor
|
||||
|
||||
self.deviceNameTitleLabel.textColor = theme.textPrimaryColor
|
||||
self.deviceNameLabel.textColor = theme.textPrimaryColor
|
||||
|
||||
self.deviceIdTitleLabel.textColor = theme.textPrimaryColor
|
||||
self.deviceIdLabel.textColor = theme.textPrimaryColor
|
||||
|
||||
self.deviceKeyTitleLabel.textColor = theme.textPrimaryColor
|
||||
self.deviceKeyLabel.textColor = theme.textPrimaryColor
|
||||
|
||||
self.additionalInformationLabel.textColor = theme.textPrimaryColor
|
||||
|
||||
self.cancelButton.update(theme: theme)
|
||||
self.verifyButton.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?.cancelAction()
|
||||
}
|
||||
|
||||
self.navigationItem.rightBarButtonItem = cancelBarButtonItem
|
||||
|
||||
self.title = VectorL10n.keyVerificationManuallyVerifyDeviceTitle
|
||||
self.informationLabel.text = VectorL10n.keyVerificationManuallyVerifyDeviceInstruction
|
||||
self.deviceNameTitleLabel.text = VectorL10n.keyVerificationManuallyVerifyDeviceNameTitle
|
||||
self.deviceIdTitleLabel.text = VectorL10n.keyVerificationManuallyVerifyDeviceIdTitle
|
||||
self.deviceKeyTitleLabel.text = VectorL10n.keyVerificationManuallyVerifyDeviceKeyTitle
|
||||
self.additionalInformationLabel.text = VectorL10n.keyVerificationManuallyVerifyDeviceAdditionalInformation
|
||||
|
||||
self.deviceNameLabel.text = nil
|
||||
self.deviceIdLabel.text = nil
|
||||
self.deviceKeyLabel.text = nil
|
||||
|
||||
self.cancelButton.actionStyle = .cancel
|
||||
}
|
||||
|
||||
private func render(viewState: KeyVerificationManuallyVerifyViewState) {
|
||||
switch viewState {
|
||||
case .loading:
|
||||
self.renderLoading()
|
||||
case .loaded(let viewData):
|
||||
self.renderLoaded(viewData: viewData)
|
||||
case .error(let error):
|
||||
self.render(error: error)
|
||||
}
|
||||
}
|
||||
|
||||
private func renderLoading() {
|
||||
self.activityPresenter.presentActivityIndicator(on: self.view, animated: true)
|
||||
}
|
||||
|
||||
private func renderLoaded(viewData: KeyVerificationManuallyVerifyViewData) {
|
||||
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
|
||||
|
||||
self.deviceNameLabel.text = viewData.deviceName
|
||||
self.deviceIdLabel.text = viewData.deviceId
|
||||
self.deviceKeyLabel.text = viewData.deviceKey
|
||||
}
|
||||
|
||||
private func render(error: Error) {
|
||||
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
|
||||
self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: nil)
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@IBAction private func verifyButtonAction(_ sender: Any) {
|
||||
self.viewModel.process(viewAction: .verify)
|
||||
}
|
||||
|
||||
@IBAction private func cancelButtonAction(_ sender: Any) {
|
||||
self.cancelAction()
|
||||
}
|
||||
|
||||
private func cancelAction() {
|
||||
self.viewModel.process(viewAction: .cancel)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - KeyVerificationManuallyVerifyViewModelViewDelegate
|
||||
extension KeyVerificationManuallyVerifyViewController: KeyVerificationManuallyVerifyViewModelViewDelegate {
|
||||
|
||||
func keyVerificationManuallyVerifyViewModel(_ viewModel: KeyVerificationManuallyVerifyViewModelType, didUpdateViewState viewSate: KeyVerificationManuallyVerifyViewState) {
|
||||
self.render(viewState: viewSate)
|
||||
}
|
||||
}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh KeyVerification/Device/ManuallyVerify KeyVerificationManuallyVerify
|
||||
/*
|
||||
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 KeyVerificationManuallyVerifyViewModelError: Error {
|
||||
case unknown
|
||||
case deviceNotFound
|
||||
}
|
||||
|
||||
final class KeyVerificationManuallyVerifyViewModel: KeyVerificationManuallyVerifyViewModelType {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let session: MXSession
|
||||
private let deviceId: String
|
||||
private let userId: String
|
||||
|
||||
private var currentOperation: MXHTTPOperation?
|
||||
|
||||
// MARK: Public
|
||||
|
||||
weak var viewDelegate: KeyVerificationManuallyVerifyViewModelViewDelegate?
|
||||
weak var coordinatorDelegate: KeyVerificationManuallyVerifyViewModelCoordinatorDelegate?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(session: MXSession, deviceId: String, userId: String) {
|
||||
self.session = session
|
||||
self.deviceId = deviceId
|
||||
self.userId = userId
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.cancelOperations()
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func process(viewAction: KeyVerificationManuallyVerifyViewAction) {
|
||||
switch viewAction {
|
||||
case .loadData:
|
||||
self.loadData()
|
||||
case .verify:
|
||||
self.verifyDevice()
|
||||
case .cancel:
|
||||
self.cancelOperations()
|
||||
self.coordinatorDelegate?.keyVerificationManuallyVerifyViewModelDidCancel(self)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func loadData() {
|
||||
|
||||
guard let deviceInfo = self.session.crypto.device(withDeviceId: self.deviceId, ofUser: self.userId) else {
|
||||
self.update(viewState: .error(KeyVerificationManuallyVerifyViewModelError.deviceNotFound))
|
||||
return
|
||||
}
|
||||
|
||||
var deviceKey: String?
|
||||
|
||||
if let deviceFingerprint = deviceInfo.fingerprint {
|
||||
deviceKey = MXTools.addWhiteSpaces(to: deviceFingerprint, every: 4)
|
||||
}
|
||||
|
||||
let viewData = KeyVerificationManuallyVerifyViewData(deviceId: self.deviceId, deviceName: deviceInfo.displayName, deviceKey: deviceKey)
|
||||
self.update(viewState: .loaded(viewData))
|
||||
}
|
||||
|
||||
private func update(viewState: KeyVerificationManuallyVerifyViewState) {
|
||||
self.viewDelegate?.keyVerificationManuallyVerifyViewModel(self, didUpdateViewState: viewState)
|
||||
}
|
||||
|
||||
private func verifyDevice() {
|
||||
|
||||
self.update(viewState: .loading)
|
||||
|
||||
self.session.crypto.setDeviceVerification(.verified, forDevice: self.deviceId, ofUser: self.userId, success: { [weak self] in
|
||||
guard let self = self else {
|
||||
return
|
||||
}
|
||||
self.coordinatorDelegate?.keyVerificationManuallyVerifyViewModel(self, didVerifiedDeviceWithId: self.deviceId, of: self.userId)
|
||||
}, failure: { [weak self] (error) in
|
||||
guard let self = self else {
|
||||
return
|
||||
}
|
||||
let finalError = error ?? KeyVerificationManuallyVerifyViewModelError.unknown
|
||||
self.update(viewState: .error(finalError))
|
||||
})
|
||||
}
|
||||
|
||||
private func cancelOperations() {
|
||||
self.currentOperation?.cancel()
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh KeyVerification/Device/ManuallyVerify KeyVerificationManuallyVerify
|
||||
/*
|
||||
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 KeyVerificationManuallyVerifyViewModelViewDelegate: class {
|
||||
func keyVerificationManuallyVerifyViewModel(_ viewModel: KeyVerificationManuallyVerifyViewModelType, didUpdateViewState viewSate: KeyVerificationManuallyVerifyViewState)
|
||||
}
|
||||
|
||||
protocol KeyVerificationManuallyVerifyViewModelCoordinatorDelegate: class {
|
||||
func keyVerificationManuallyVerifyViewModel(_ viewModel: KeyVerificationManuallyVerifyViewModelType, didVerifiedDeviceWithId deviceId: String, of userId: String)
|
||||
func keyVerificationManuallyVerifyViewModelDidCancel(_ viewModel: KeyVerificationManuallyVerifyViewModelType)
|
||||
}
|
||||
|
||||
/// Protocol describing the view model used by `KeyVerificationManuallyVerifyViewController`
|
||||
protocol KeyVerificationManuallyVerifyViewModelType {
|
||||
|
||||
var viewDelegate: KeyVerificationManuallyVerifyViewModelViewDelegate? { get set }
|
||||
var coordinatorDelegate: KeyVerificationManuallyVerifyViewModelCoordinatorDelegate? { get set }
|
||||
|
||||
func process(viewAction: KeyVerificationManuallyVerifyViewAction)
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh KeyVerification/Device/ManuallyVerify KeyVerificationManuallyVerify
|
||||
/*
|
||||
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
|
||||
|
||||
struct KeyVerificationManuallyVerifyViewData {
|
||||
let deviceId: String
|
||||
let deviceName: String?
|
||||
let deviceKey: String?
|
||||
}
|
||||
|
||||
/// KeyVerificationManuallyVerifyViewController view state
|
||||
enum KeyVerificationManuallyVerifyViewState {
|
||||
case loading
|
||||
case loaded(_ viewData: KeyVerificationManuallyVerifyViewData)
|
||||
case error(Error)
|
||||
}
|
||||
Reference in New Issue
Block a user