mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-23 18:12:44 +02:00
Settings identity server: WIP.
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
// File created from FlowTemplate
|
||||
// $ createRootCoordinator.sh Test SettingsIdentityServer
|
||||
/*
|
||||
Copyright 2019 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 SettingsIdentityServerCoordinator: SettingsIdentityServerCoordinatorType {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let session: MXSession
|
||||
private let settingsIdentityServerViewController: SettingsIdentityServerViewController
|
||||
|
||||
// MARK: Public
|
||||
|
||||
// Must be used only internally
|
||||
var childCoordinators: [Coordinator] = []
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(session: MXSession) {
|
||||
self.session = session
|
||||
|
||||
let settingsIdentityServerViewModel = SettingsIdentityServerViewModel(session: self.session)
|
||||
let settingsIdentityServerViewController = SettingsIdentityServerViewController.instantiate(with: settingsIdentityServerViewModel)
|
||||
self.settingsIdentityServerViewController = settingsIdentityServerViewController
|
||||
}
|
||||
|
||||
// MARK: - Public methods
|
||||
|
||||
func start() {
|
||||
}
|
||||
|
||||
func toPresentable() -> UIViewController {
|
||||
return self.settingsIdentityServerViewController
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
// File created from FlowTemplate
|
||||
// $ createRootCoordinator.sh Test SettingsIdentityServer
|
||||
/*
|
||||
Copyright 2019 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 SettingsIdentityServerCoordinatorBridgePresenterDelegate {
|
||||
func settingsIdentityServerCoordinatorBridgePresenterDelegateDidComplete(_ coordinatorBridgePresenter: SettingsIdentityServerCoordinatorBridgePresenter)
|
||||
}
|
||||
|
||||
/// SettingsIdentityServerCoordinatorBridgePresenter enables to start SettingsIdentityServerCoordinator from a view controller.
|
||||
/// This bridge is used while waiting for global usage of coordinator pattern.
|
||||
@objcMembers
|
||||
final class SettingsIdentityServerCoordinatorBridgePresenter: NSObject {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let session: MXSession
|
||||
private var router: NavigationRouter?
|
||||
private var coordinator: SettingsIdentityServerCoordinator?
|
||||
|
||||
// MARK: Public
|
||||
|
||||
weak var delegate: SettingsIdentityServerCoordinatorBridgePresenterDelegate?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(session: MXSession) {
|
||||
self.session = session
|
||||
super.init()
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func push(from navigationController: UINavigationController, animated: Bool, popCompletion: (() -> Void)?) {
|
||||
|
||||
let router = NavigationRouter(navigationController: navigationController)
|
||||
|
||||
let settingsIdentityServerCoordinator = SettingsIdentityServerCoordinator(session: self.session)
|
||||
|
||||
router.push(settingsIdentityServerCoordinator, animated: animated) { [weak self] in
|
||||
self?.coordinator = nil
|
||||
self?.router = nil
|
||||
popCompletion?()
|
||||
}
|
||||
|
||||
settingsIdentityServerCoordinator.start()
|
||||
|
||||
self.coordinator = settingsIdentityServerCoordinator
|
||||
self.router = router
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// File created from FlowTemplate
|
||||
// $ createRootCoordinator.sh Test SettingsIdentityServer
|
||||
/*
|
||||
Copyright 2019 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
|
||||
|
||||
/// `SettingsIdentityServerCoordinatorType` is a protocol describing a Coordinator that handle keybackup setup navigation flow.
|
||||
protocol SettingsIdentityServerCoordinatorType: Coordinator, Presentable {
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Test SettingsIdentityServer
|
||||
/*
|
||||
Copyright 2019 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
|
||||
|
||||
/// SettingsIdentityServerViewController view actions exposed to view model
|
||||
enum SettingsIdentityServerViewAction {
|
||||
case load
|
||||
case add(identityServer: String)
|
||||
case change(identityServer: String)
|
||||
case disconnect
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
<?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="YCb-yR-1Km">
|
||||
<device id="retina4_7" 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>
|
||||
<!--Settings Identity Server View Controller-->
|
||||
<scene sceneID="CLh-Ql-FIE">
|
||||
<objects>
|
||||
<viewController extendedLayoutIncludesOpaqueBars="YES" automaticallyAdjustsScrollViewInsets="NO" id="YCb-yR-1Km" customClass="SettingsIdentityServerViewController" customModule="Riot" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="trm-G2-fZS">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="8Oz-k6-Zyh">
|
||||
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="lG2-Xw-KPE">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="277"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hwn-qz-R7V">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="277"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0W7-LW-UNr">
|
||||
<rect key="frame" x="0.0" y="40" width="375" height="50"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" text="email" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="6W6-EH-SaK">
|
||||
<rect key="frame" x="20" y="16" width="36.5" height="18"/>
|
||||
<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="foo@matrix.org" textAlignment="right" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="EJ4-Ey-0lE">
|
||||
<rect key="frame" x="66.5" y="16" width="288.5" height="18"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="EJ4-Ey-0lE" firstAttribute="bottom" secondItem="6W6-EH-SaK" secondAttribute="bottom" id="Bcq-ol-tj3"/>
|
||||
<constraint firstItem="6W6-EH-SaK" firstAttribute="leading" secondItem="0W7-LW-UNr" secondAttribute="leading" constant="20" id="DDg-Rf-OJi"/>
|
||||
<constraint firstItem="EJ4-Ey-0lE" firstAttribute="top" secondItem="6W6-EH-SaK" secondAttribute="top" id="HAW-2P-1hK"/>
|
||||
<constraint firstItem="6W6-EH-SaK" firstAttribute="top" secondItem="0W7-LW-UNr" secondAttribute="top" constant="16" id="IDq-mq-3Wp"/>
|
||||
<constraint firstAttribute="bottom" secondItem="6W6-EH-SaK" secondAttribute="bottom" constant="16" id="NSd-lt-YvO"/>
|
||||
<constraint firstItem="EJ4-Ey-0lE" firstAttribute="leading" secondItem="6W6-EH-SaK" secondAttribute="trailing" constant="10" id="X39-lL-C4W"/>
|
||||
<constraint firstAttribute="trailing" secondItem="EJ4-Ey-0lE" secondAttribute="trailing" constant="20" id="nDU-dW-ZZQ"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="h8a-2s-H3K">
|
||||
<rect key="frame" x="0.0" y="115" width="375" height="50"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="kPC-YQ-MGL">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="50"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="T9R-QE-nBi"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<inset key="contentEdgeInsets" minX="10" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="Share">
|
||||
<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="operationButtonAction:" destination="YCb-yR-1Km" eventType="touchUpInside" id="nba-dR-lP3"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="kPC-YQ-MGL" secondAttribute="trailing" id="185-hA-OVD"/>
|
||||
<constraint firstItem="kPC-YQ-MGL" firstAttribute="leading" secondItem="h8a-2s-H3K" secondAttribute="leading" id="OyR-iq-Gs8"/>
|
||||
<constraint firstItem="kPC-YQ-MGL" firstAttribute="top" secondItem="h8a-2s-H3K" secondAttribute="top" id="W9z-lt-umK"/>
|
||||
<constraint firstAttribute="bottom" secondItem="kPC-YQ-MGL" secondAttribute="bottom" id="vcz-SU-JOZ"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="HLL-Fw-u3V">
|
||||
<rect key="frame" x="20" y="185" width="335" height="72"/>
|
||||
<string key="text">Manage preferences for this email address, which other users can use to discover you and use to invite you to rooms. Add or remove email addresses in Accounts.</string>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<color key="textColor" white="1" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="0W7-LW-UNr" firstAttribute="top" secondItem="hwn-qz-R7V" secondAttribute="top" constant="40" id="7YM-zk-rCu"/>
|
||||
<constraint firstAttribute="trailing" secondItem="HLL-Fw-u3V" secondAttribute="trailing" constant="20" id="Bs5-Uz-kbF"/>
|
||||
<constraint firstAttribute="trailing" secondItem="0W7-LW-UNr" secondAttribute="trailing" id="XOC-9V-o8H"/>
|
||||
<constraint firstItem="h8a-2s-H3K" firstAttribute="leading" secondItem="hwn-qz-R7V" secondAttribute="leading" id="b8m-4H-orP"/>
|
||||
<constraint firstAttribute="bottom" secondItem="HLL-Fw-u3V" secondAttribute="bottom" constant="20" id="fIC-JS-SKB"/>
|
||||
<constraint firstAttribute="width" priority="750" constant="500" id="jEc-ht-fgG"/>
|
||||
<constraint firstItem="0W7-LW-UNr" firstAttribute="leading" secondItem="hwn-qz-R7V" secondAttribute="leading" id="kbX-q7-dtp"/>
|
||||
<constraint firstItem="HLL-Fw-u3V" firstAttribute="leading" secondItem="hwn-qz-R7V" secondAttribute="leading" constant="20" id="pHb-5b-QYN"/>
|
||||
<constraint firstItem="HLL-Fw-u3V" firstAttribute="top" secondItem="h8a-2s-H3K" secondAttribute="bottom" constant="20" id="t1R-rs-kIT"/>
|
||||
<constraint firstAttribute="trailing" secondItem="h8a-2s-H3K" secondAttribute="trailing" id="vPw-01-TaS"/>
|
||||
<constraint firstItem="h8a-2s-H3K" firstAttribute="top" secondItem="0W7-LW-UNr" secondAttribute="bottom" constant="25" id="xFM-Hl-p3E"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="hwn-qz-R7V" firstAttribute="top" secondItem="lG2-Xw-KPE" secondAttribute="top" id="6UK-h7-Jfi"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="hwn-qz-R7V" secondAttribute="trailing" id="PWd-1a-pc6"/>
|
||||
<constraint firstItem="hwn-qz-R7V" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="lG2-Xw-KPE" secondAttribute="leading" id="Xde-HX-oMG"/>
|
||||
<constraint firstAttribute="bottom" secondItem="hwn-qz-R7V" secondAttribute="bottom" id="cjT-2e-tp7"/>
|
||||
<constraint firstItem="hwn-qz-R7V" firstAttribute="centerX" secondItem="lG2-Xw-KPE" secondAttribute="centerX" id="tWw-7s-Eaj"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="lG2-Xw-KPE" secondAttribute="trailing" id="2Oj-q1-byd"/>
|
||||
<constraint firstItem="lG2-Xw-KPE" firstAttribute="width" secondItem="8Oz-k6-Zyh" secondAttribute="width" id="2RP-6A-FLF"/>
|
||||
<constraint firstItem="lG2-Xw-KPE" firstAttribute="leading" secondItem="8Oz-k6-Zyh" secondAttribute="leading" id="FGn-RZ-dc5"/>
|
||||
<constraint firstAttribute="bottom" secondItem="lG2-Xw-KPE" secondAttribute="bottom" id="fGL-Ig-G6s"/>
|
||||
<constraint firstItem="lG2-Xw-KPE" firstAttribute="top" secondItem="8Oz-k6-Zyh" secondAttribute="top" id="kyx-Ao-xKa"/>
|
||||
</constraints>
|
||||
</scrollView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.94509803920000002" green="0.96078431369999995" blue="0.97254901959999995" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="8Oz-k6-Zyh" firstAttribute="leading" secondItem="0Gf-da-iK5" secondAttribute="leading" id="059-y1-rPd"/>
|
||||
<constraint firstAttribute="bottom" secondItem="8Oz-k6-Zyh" secondAttribute="bottom" id="BXd-L8-T6F"/>
|
||||
<constraint firstItem="0Gf-da-iK5" firstAttribute="top" secondItem="8Oz-k6-Zyh" secondAttribute="top" id="lkR-P4-U2b"/>
|
||||
<constraint firstItem="0Gf-da-iK5" firstAttribute="trailing" secondItem="8Oz-k6-Zyh" secondAttribute="trailing" id="vL8-o9-5PR"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="0Gf-da-iK5"/>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="informationLabel" destination="HLL-Fw-u3V" id="nmD-qB-eqO"/>
|
||||
<outlet property="operationButton" destination="kPC-YQ-MGL" id="K3I-z6-S0u"/>
|
||||
<outlet property="scrollView" destination="8Oz-k6-Zyh" id="e5g-xe-zBj"/>
|
||||
<outlet property="threePidAdressLabel" destination="EJ4-Ey-0lE" id="4tq-OE-lmL"/>
|
||||
<outlet property="threePidBackgroundView" destination="0W7-LW-UNr" id="ESQ-dK-9mN"/>
|
||||
<outlet property="threePidTitleLabel" destination="6W6-EH-SaK" id="6kr-lU-l1k"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="s4k-Y2-H87" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-3772" y="-774"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
@@ -0,0 +1,178 @@
|
||||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Test SettingsIdentityServer
|
||||
/*
|
||||
Copyright 2019 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 SettingsIdentityServerViewController: UIViewController {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Outlets
|
||||
|
||||
@IBOutlet private weak var scrollView: UIScrollView!
|
||||
|
||||
@IBOutlet private weak var messageLabel: UILabel!
|
||||
@IBOutlet private weak var addOrChangeButton: UIButton!
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private var viewModel: SettingsIdentityServerViewModelType!
|
||||
private var theme: Theme!
|
||||
private var keyboardAvoider: KeyboardAvoider?
|
||||
private var errorPresenter: MXKErrorPresentation!
|
||||
private var activityPresenter: ActivityIndicatorPresenter!
|
||||
private var viewState: SettingsIdentityServerViewState?
|
||||
|
||||
private var displayMode: SettingsIdentityServerDisplayMode?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
class func instantiate(with viewModel: SettingsIdentityServerViewModelType) -> SettingsIdentityServerViewController {
|
||||
let viewController = StoryboardScene.SettingsIdentityServerViewController.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.title = "Identity server"
|
||||
|
||||
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: .load)
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
self.keyboardAvoider?.startAvoiding()
|
||||
}
|
||||
|
||||
override func viewDidDisappear(_ animated: Bool) {
|
||||
super.viewDidDisappear(animated)
|
||||
|
||||
self.keyboardAvoider?.stopAvoiding()
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// TODO:
|
||||
}
|
||||
|
||||
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() {
|
||||
self.scrollView.keyboardDismissMode = .interactive
|
||||
}
|
||||
|
||||
private func render(viewState: SettingsIdentityServerViewState) {
|
||||
switch viewState {
|
||||
case .loading:
|
||||
self.renderLoading()
|
||||
case .loaded:
|
||||
self.renderLoaded()
|
||||
case .error(let error):
|
||||
self.render(error: error)
|
||||
}
|
||||
}
|
||||
|
||||
private func renderLoading() {
|
||||
self.activityPresenter.presentActivityIndicator(on: self.view, animated: true)
|
||||
}
|
||||
|
||||
private func renderLoaded() {
|
||||
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
|
||||
}
|
||||
|
||||
private func render(error: Error) {
|
||||
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
|
||||
self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: nil)
|
||||
}
|
||||
|
||||
func presentExistingIdentityServerDataAlert(with title: String) {
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@IBAction private func addOrChangeButtonAction(_ sender: Any) {
|
||||
guard let displayMode = self.displayMode else {
|
||||
return
|
||||
}
|
||||
|
||||
let identityServer = "TODO"
|
||||
|
||||
let viewAction: SettingsIdentityServerViewAction?
|
||||
|
||||
switch displayMode {
|
||||
case .noIdentityServer:
|
||||
viewAction = .add(identityServer: identityServer)
|
||||
case .identityServer:
|
||||
viewAction = .change(identityServer: identityServer)
|
||||
default:
|
||||
viewAction = nil
|
||||
}
|
||||
|
||||
if let viewAction = viewAction {
|
||||
self.viewModel.process(viewAction: viewAction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - SettingsIdentityServerViewModelViewDelegate
|
||||
extension SettingsIdentityServerViewController: SettingsIdentityServerViewModelViewDelegate {
|
||||
|
||||
func settingsIdentityServerViewModel(_ viewModel: SettingsIdentityServerViewModelType, didUpdateViewState viewState: SettingsIdentityServerViewState) {
|
||||
self.viewState = viewState
|
||||
self.render(viewState: viewState)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Test SettingsIdentityServer
|
||||
/*
|
||||
Copyright 2019 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 SettingsIdentityServerViewModelError: Error {
|
||||
case missingIdentityServer
|
||||
case unknown
|
||||
}
|
||||
|
||||
enum IdentityServerTermsStatus {
|
||||
case noTerms
|
||||
case terms(agreed: Bool)
|
||||
}
|
||||
|
||||
enum IdentityServerValidity {
|
||||
case invalid
|
||||
case valid(status: IdentityServerTermsStatus)
|
||||
}
|
||||
|
||||
final class SettingsIdentityServerViewModel: SettingsIdentityServerViewModelType {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private let session: MXSession
|
||||
|
||||
private var validationIdentityService: MXIdentityService?
|
||||
private var validationServiceTerms: MXServiceTerms?
|
||||
|
||||
// MARK: Public
|
||||
|
||||
weak var viewDelegate: SettingsIdentityServerViewModelViewDelegate?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(session: MXSession) {
|
||||
self.session = session
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func process(viewAction: SettingsIdentityServerViewAction) {
|
||||
switch viewAction {
|
||||
case .load:
|
||||
self.load()
|
||||
case .add(identityServer: let identityServer):
|
||||
self.addIdentityServer(identityServer)
|
||||
case .change(identityServer: let identityServer):
|
||||
self.changeIdentityServer(identityServer)
|
||||
case .disconnect:
|
||||
self.disconnect()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func load() {
|
||||
self.refreshIdentityServerViewState()
|
||||
}
|
||||
|
||||
private func addIdentityServer(_ newIdentityServer: String) {
|
||||
|
||||
self.update(viewState: .loading)
|
||||
|
||||
self.checkIdentityServerValidity(identityServer: newIdentityServer) { (identityServerValidityResponse) in
|
||||
switch identityServerValidityResponse {
|
||||
case .success(let identityServerValidity):
|
||||
switch identityServerValidity {
|
||||
case .invalid:
|
||||
// Present invalid IS alert
|
||||
break
|
||||
case .valid(status: let termsStatus):
|
||||
switch termsStatus {
|
||||
case .noTerms:
|
||||
// Present no terms alert
|
||||
break
|
||||
case .terms(agreed: let termsAgreed):
|
||||
if termsAgreed {
|
||||
self.updateAccountDataAndRefreshViewState(with: newIdentityServer)
|
||||
} else {
|
||||
// Present terms
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
case .failure(let error):
|
||||
self.update(viewState: .error(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func changeIdentityServer(_ newIdentityServer: String) {
|
||||
|
||||
}
|
||||
|
||||
private func disconnect() {
|
||||
|
||||
}
|
||||
|
||||
private func updateAccountDataAndRefreshViewState(with identityServer: String) {
|
||||
self.session.setAccountDataIdentityServer(identityServer, success: {
|
||||
self.refreshIdentityServerViewState()
|
||||
}, failure: { error in
|
||||
self.update(viewState: .error(error ?? SettingsIdentityServerViewModelError.unknown))
|
||||
})
|
||||
}
|
||||
|
||||
private func refreshIdentityServerViewState() {
|
||||
if let identityService = self.session.identityService {
|
||||
let host = identityService.identityServer
|
||||
self.update(viewState: .loaded(displayMode: .identityServer(host: host)))
|
||||
} else {
|
||||
self.update(viewState: .loaded(displayMode: .noIdentityServer))
|
||||
}
|
||||
}
|
||||
|
||||
private func checkExistingDataOnIdentityServer(completion: @escaping (_ response: MXResponse<Bool>) -> Void) {
|
||||
self.session.matrixRestClient.thirdPartyIdentifiers { (thirdPartyIDresponse) in
|
||||
switch thirdPartyIDresponse {
|
||||
case .success(let thirdPartyIdentifiers):
|
||||
if thirdPartyIdentifiers.isEmpty {
|
||||
completion(.success(false))
|
||||
} else {
|
||||
let mx3Pids = SettingsIdentityServerViewModel.threePids(from: thirdPartyIdentifiers)
|
||||
self.isThreThreePidsDiscoverable(mx3Pids, completion: { discoverable3pidsResponse in
|
||||
switch discoverable3pidsResponse {
|
||||
case .success(let isThereDiscoverable3pids):
|
||||
completion(.success(isThereDiscoverable3pids))
|
||||
case .failure(let error):
|
||||
completion(.failure(error))
|
||||
}
|
||||
})
|
||||
}
|
||||
case .failure(let error):
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
private func isThreThreePidsDiscoverable(_ threePids: [MX3PID], completion: @escaping (_ response: MXResponse<Bool>) -> Void) -> MXHTTPOperation? {
|
||||
guard let identityService = self.session.identityService else {
|
||||
completion(.failure(SettingsIdentityServerViewModelError.missingIdentityServer))
|
||||
return nil
|
||||
}
|
||||
|
||||
return identityService.lookup3PIDs(threePids) { lookupResponse in
|
||||
switch lookupResponse {
|
||||
case .success(let threePids):
|
||||
completion(.success(threePids.isEmpty == false))
|
||||
case .failure(let error):
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func checkIdentityServerValidity(identityServer: String, completion: @escaping (_ response: MXResponse<IdentityServerValidity>) -> Void) {
|
||||
guard let identityServerURL = URL(string: identityServer) else {
|
||||
completion(.success(.invalid))
|
||||
return
|
||||
}
|
||||
|
||||
let restClient: MXRestClient = self.session.matrixRestClient
|
||||
|
||||
let identityService = MXIdentityService(identityServer: identityServerURL, accessToken: nil, homeserverRestClient: restClient)
|
||||
|
||||
identityService.accessToken { response in
|
||||
switch response {
|
||||
case .success(let accessToken):
|
||||
let serviceTerms = MXServiceTerms(baseUrl: identityService.identityServer, serviceType: MXServiceTypeIdentityService, matrixSession: self.session, accessToken: accessToken)
|
||||
|
||||
serviceTerms.areAllTermsAgreed({ (areAllTermsAgreed) in
|
||||
|
||||
completion(.success(IdentityServerValidity.valid(status: .terms(agreed: areAllTermsAgreed))))
|
||||
|
||||
self.validationServiceTerms = nil
|
||||
}, failure: { error in
|
||||
completion(.failure(error))
|
||||
self.validationServiceTerms = nil
|
||||
})
|
||||
|
||||
self.validationServiceTerms = serviceTerms
|
||||
|
||||
case .failure(let error):
|
||||
completion(.failure(error))
|
||||
}
|
||||
|
||||
self.validationIdentityService = nil
|
||||
}
|
||||
|
||||
self.validationIdentityService = identityService
|
||||
}
|
||||
|
||||
private func update(viewState: SettingsIdentityServerViewState) {
|
||||
self.viewDelegate?.settingsIdentityServerViewModel(self, didUpdateViewState: viewState)
|
||||
}
|
||||
|
||||
private class func threePids(from thirdPartyIdentifiers: [MXThirdPartyIdentifier]) -> [MX3PID] {
|
||||
return thirdPartyIdentifiers.map({ (thirdPartyIdentifier) -> MX3PID in
|
||||
return MX3PID(medium: MX3PID.Medium(identifier: thirdPartyIdentifier.medium), address: thirdPartyIdentifier.address)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Test SettingsIdentityServer
|
||||
/*
|
||||
Copyright 2019 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 SettingsIdentityServerViewModelViewDelegate: class {
|
||||
func settingsIdentityServerViewModel(_ viewModel: SettingsIdentityServerViewModelType, didUpdateViewState viewSate: SettingsIdentityServerViewState)
|
||||
}
|
||||
|
||||
/// Protocol describing the view model used by `SettingsIdentityServerViewController`
|
||||
protocol SettingsIdentityServerViewModelType {
|
||||
|
||||
var viewDelegate: SettingsIdentityServerViewModelViewDelegate? { get set }
|
||||
|
||||
func process(viewAction: SettingsIdentityServerViewAction)
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// File created from ScreenTemplate
|
||||
// $ createScreen.sh Test SettingsIdentityServer
|
||||
/*
|
||||
Copyright 2019 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
|
||||
|
||||
/// SettingsIdentityServerViewController view state
|
||||
enum SettingsIdentityServerViewState {
|
||||
case loading
|
||||
case loaded(displayMode: SettingsIdentityServerDisplayMode)
|
||||
case error(Error)
|
||||
}
|
||||
|
||||
enum SettingsIdentityServerDisplayMode {
|
||||
case noIdentityServer
|
||||
case identityServer(host: String)
|
||||
}
|
||||
Reference in New Issue
Block a user