Implement new module

This commit is contained in:
ismailgulek
2020-09-14 19:44:07 +03:00
parent 2517d102ae
commit c2a92858de
13 changed files with 875 additions and 0 deletions
@@ -0,0 +1,21 @@
//
// 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 RoomCreationEventRowViewModel {
var title: NSAttributedString?
}
@@ -0,0 +1,72 @@
// File created from ScreenTemplate
// $ createScreen.sh Modal2/RoomCreation RoomCreationEventsModal
/*
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 RoomCreationEventsModalCoordinator: RoomCreationEventsModalCoordinatorType {
// MARK: - Properties
// MARK: Private
private let session: MXSession
private var roomCreationEventsModalViewModel: RoomCreationEventsModalViewModelType
private let roomCreationEventsModalViewController: RoomCreationEventsModalViewController
// MARK: Public
// Must be used only internally
var childCoordinators: [Coordinator] = []
weak var delegate: RoomCreationEventsModalCoordinatorDelegate?
// MARK: - Setup
init(session: MXSession, bubbleData: MXKRoomBubbleCellDataStoring, roomState: MXRoomState) {
self.session = session
let roomCreationEventsModalViewModel = RoomCreationEventsModalViewModel(session: self.session, bubbleData: bubbleData, roomState: roomState)
let roomCreationEventsModalViewController = RoomCreationEventsModalViewController.instantiate(with: roomCreationEventsModalViewModel)
self.roomCreationEventsModalViewModel = roomCreationEventsModalViewModel
self.roomCreationEventsModalViewController = roomCreationEventsModalViewController
}
// MARK: - Public methods
func start() {
self.roomCreationEventsModalViewModel.coordinatorDelegate = self
}
func toPresentable() -> UIViewController {
return self.roomCreationEventsModalViewController
}
func toSlidingModalPresentable() -> UIViewController & SlidingModalPresentable {
return self.roomCreationEventsModalViewController
}
}
// MARK: - RoomCreationEventsModalViewModelCoordinatorDelegate
extension RoomCreationEventsModalCoordinator: RoomCreationEventsModalViewModelCoordinatorDelegate {
func roomCreationEventsModalViewModelDidTapClose(_ viewModel: RoomCreationEventsModalViewModelType) {
self.delegate?.roomCreationEventsModalCoordinatorDidTapClose(self)
}
}
@@ -0,0 +1,28 @@
// File created from ScreenTemplate
// $ createScreen.sh Modal2/RoomCreation RoomCreationEventsModal
/*
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 RoomCreationEventsModalCoordinatorDelegate: class {
func roomCreationEventsModalCoordinatorDidTapClose(_ coordinator: RoomCreationEventsModalCoordinatorType)
}
/// `RoomCreationEventsModalCoordinatorType` is a protocol describing a Coordinator that handle key backup setup passphrase navigation flow.
protocol RoomCreationEventsModalCoordinatorType: Coordinator, Presentable {
var delegate: RoomCreationEventsModalCoordinatorDelegate? { get }
}
@@ -0,0 +1,26 @@
// File created from ScreenTemplate
// $ createScreen.sh Modal2/RoomCreation RoomCreationEventsModal
/*
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
/// RoomCreationEventsModalViewController view actions exposed to view model
enum RoomCreationEventsModalViewAction {
case loadData
case close
case cancel
}
@@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16096" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="V8j-Lb-PgC">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Room Creation Events Modal View Controller-->
<scene sceneID="mt5-wz-YKA">
<objects>
<viewController extendedLayoutIncludesOpaqueBars="YES" automaticallyAdjustsScrollViewInsets="NO" id="V8j-Lb-PgC" customClass="RoomCreationEventsModalViewController" 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="842"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="M84-br-bHM">
<rect key="frame" x="0.0" y="0.0" width="414" height="80"/>
<subviews>
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="YaZ-Pv-7g9" customClass="MXKImageView">
<rect key="frame" x="16" y="20" width="40" height="40"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="Xiw-Lp-Exy"/>
<constraint firstAttribute="width" constant="40" id="eG6-bm-km9"/>
</constraints>
</view>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="eyI-bY-amr">
<rect key="frame" x="370" y="16" width="28" height="28"/>
<color key="backgroundColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="28" id="g5v-BH-Kqz"/>
<constraint firstAttribute="width" constant="28" id="z1z-i6-rQP"/>
</constraints>
<state key="normal" image="close_button"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
<integer key="value" value="14"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
<connections>
<action selector="closeButtonTapped:" destination="V8j-Lb-PgC" eventType="touchUpInside" id="jfk-j7-59z"/>
</connections>
</button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="goJ-ND-Jsk">
<rect key="frame" x="64" y="20" width="298" height="24"/>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="20"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="f1E-jK-fMa">
<rect key="frame" x="64" y="44" width="298" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstItem="eyI-bY-amr" firstAttribute="top" secondItem="M84-br-bHM" secondAttribute="top" constant="16" id="10e-aB-X62"/>
<constraint firstAttribute="trailing" secondItem="f1E-jK-fMa" secondAttribute="trailing" constant="52" id="UX4-gD-R3P"/>
<constraint firstAttribute="trailing" secondItem="eyI-bY-amr" secondAttribute="trailing" constant="16" id="YbD-Uq-CyY"/>
<constraint firstItem="YaZ-Pv-7g9" firstAttribute="top" secondItem="M84-br-bHM" secondAttribute="top" constant="20" id="d1C-qB-Yx7"/>
<constraint firstItem="goJ-ND-Jsk" firstAttribute="leading" secondItem="YaZ-Pv-7g9" secondAttribute="trailing" constant="8" id="dPI-An-X2O"/>
<constraint firstAttribute="height" constant="80" id="kTG-4C-HCx"/>
<constraint firstItem="f1E-jK-fMa" firstAttribute="leading" secondItem="YaZ-Pv-7g9" secondAttribute="trailing" constant="8" id="ohi-MX-TVT"/>
<constraint firstItem="f1E-jK-fMa" firstAttribute="top" secondItem="goJ-ND-Jsk" secondAttribute="bottom" id="pB3-Q4-RbB"/>
<constraint firstItem="YaZ-Pv-7g9" firstAttribute="leading" secondItem="M84-br-bHM" secondAttribute="leading" constant="16" id="w2d-dk-54I"/>
<constraint firstItem="eyI-bY-amr" firstAttribute="leading" secondItem="goJ-ND-Jsk" secondAttribute="trailing" constant="8" id="wUn-ed-WuH"/>
<constraint firstItem="goJ-ND-Jsk" firstAttribute="top" secondItem="M84-br-bHM" secondAttribute="top" constant="20" id="ykL-gN-QoL"/>
</constraints>
</view>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="co7-sG-zRv">
<rect key="frame" x="0.0" y="80" width="414" height="762"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<connections>
<outlet property="dataSource" destination="V8j-Lb-PgC" id="HLb-bL-S6S"/>
<outlet property="delegate" destination="V8j-Lb-PgC" id="txp-Np-fls"/>
</connections>
</tableView>
</subviews>
<color key="backgroundColor" red="0.94509803921568625" green="0.96078431372549022" blue="0.97254901960784312" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="M84-br-bHM" secondAttribute="trailing" id="5vV-mz-GeY"/>
<constraint firstItem="M84-br-bHM" firstAttribute="top" secondItem="EL9-GA-lwo" secondAttribute="top" id="9KT-pS-9gG"/>
<constraint firstItem="M84-br-bHM" firstAttribute="leading" secondItem="EL9-GA-lwo" secondAttribute="leading" id="Umv-Pr-MqL"/>
<constraint firstAttribute="bottom" secondItem="co7-sG-zRv" secondAttribute="bottom" id="gIs-ai-WDM"/>
<constraint firstItem="co7-sG-zRv" firstAttribute="top" secondItem="M84-br-bHM" secondAttribute="bottom" id="hGW-eH-f44"/>
<constraint firstAttribute="trailing" secondItem="co7-sG-zRv" secondAttribute="trailing" id="iia-J4-ecO"/>
<constraint firstItem="co7-sG-zRv" firstAttribute="leading" secondItem="EL9-GA-lwo" secondAttribute="leading" id="lel-uf-nEl"/>
</constraints>
<viewLayoutGuide key="safeArea" id="bFg-jh-JZB"/>
</view>
<modalPageSheetSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
<outlet property="closeButton" destination="eyI-bY-amr" id="7Lv-N9-aHa"/>
<outlet property="mainTableView" destination="co7-sG-zRv" id="F9J-rS-nSq"/>
<outlet property="roomAvatarImageView" destination="YaZ-Pv-7g9" id="Gu2-as-fNL"/>
<outlet property="roomInfoLabel" destination="f1E-jK-fMa" id="0CH-Q8-8aD"/>
<outlet property="roomNameLabel" destination="goJ-ND-Jsk" id="wuf-gz-aK0"/>
</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>
<resources>
<image name="close_button" width="16" height="16"/>
</resources>
</document>
@@ -0,0 +1,229 @@
// File created from ScreenTemplate
// $ createScreen.sh Modal2/RoomCreation RoomCreationEventsModal
/*
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 RoomCreationEventsModalViewController: UIViewController {
// MARK: - Constants
private enum Constants {
static let defaultStyleCellReuseIdentifier = "default"
}
// MARK: - Properties
// MARK: Outlets
@IBOutlet private weak var mainTableView: UITableView!
@IBOutlet private weak var roomAvatarImageView: MXKImageView! {
didSet {
roomAvatarImageView.layer.cornerRadius = roomAvatarImageView.frame.width/2
}
}
@IBOutlet private weak var roomNameLabel: UILabel!
@IBOutlet private weak var roomInfoLabel: UILabel!
@IBOutlet private weak var closeButton: UIButton!
// MARK: Private
private var viewModel: RoomCreationEventsModalViewModelType!
private var theme: Theme!
private var errorPresenter: MXKErrorPresentation!
private var activityPresenter: ActivityIndicatorPresenter!
// MARK: - Setup
class func instantiate(with viewModel: RoomCreationEventsModalViewModelType) -> RoomCreationEventsModalViewController {
let viewController = StoryboardScene.RoomCreationEventsModalViewController.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)
roomNameLabel.text = viewModel.roomName
roomInfoLabel.text = viewModel.roomInfo
viewModel.setAvatar(in: roomAvatarImageView)
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return self.theme.statusBarStyle
}
// MARK: - Private
private func update(theme: Theme) {
self.theme = theme
self.view.backgroundColor = theme.backgroundColor
self.mainTableView.backgroundColor = theme.backgroundColor
if let navigationBar = self.navigationController?.navigationBar {
theme.applyStyle(onNavigationBar: navigationBar)
}
// TODO: Set view colors here
theme.applyStyle(onButton: self.closeButton)
roomNameLabel.textColor = theme.textPrimaryColor
roomInfoLabel.textColor = theme.textSecondaryColor
self.mainTableView.reloadData()
}
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.mainTableView.separatorStyle = .none
self.mainTableView.tableFooterView = UIView()
}
private func render(viewState: RoomCreationEventsModalViewState) {
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)
}
// MARK: - Actions
@IBAction private func closeButtonTapped(_ sender: Any) {
self.viewModel.process(viewAction: .close)
}
}
// MARK: - RoomCreationEventsModalViewModelViewDelegate
extension RoomCreationEventsModalViewController: RoomCreationEventsModalViewModelViewDelegate {
func roomCreationEventsModalViewModel(_ viewModel: RoomCreationEventsModalViewModelType, didUpdateViewState viewSate: RoomCreationEventsModalViewState) {
self.render(viewState: viewSate)
}
}
// MARK: - SlidingModalPresentable
extension RoomCreationEventsModalViewController: SlidingModalPresentable {
func allowsDismissOnBackgroundTap() -> Bool {
return true
}
func layoutHeightFittingWidth(_ width: CGFloat) -> CGFloat {
return mainTableView.contentSize.height + 80
// TODO: Fix hard-coded
// return 500
}
}
// MARK: - UITableViewDataSource
extension RoomCreationEventsModalViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModel.numberOfRows
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let viewModel = viewModel.rowViewModel(at: indexPath) else {
return UITableViewCell(style: .default, reuseIdentifier: nil)
}
var cell: UITableViewCell! = tableView.dequeueReusableCell(withIdentifier: Constants.defaultStyleCellReuseIdentifier)
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: Constants.defaultStyleCellReuseIdentifier)
}
if let title = viewModel.title {
let mutableTitle = NSMutableAttributedString(attributedString: title)
mutableTitle.setAttributes([
NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16),
NSAttributedString.Key.foregroundColor: theme.textSecondaryColor
], range: NSRange(location: 0, length: mutableTitle.length))
cell.textLabel?.attributedText = mutableTitle
} else {
cell.textLabel?.attributedText = nil
}
cell.textLabel?.numberOfLines = 0
cell.backgroundColor = theme.backgroundColor
cell.contentView.backgroundColor = .clear
cell.tintColor = theme.tintColor
cell.selectionStyle = .none
return cell
}
}
// MARK: - UITableViewDelegate
extension RoomCreationEventsModalViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
}
@@ -0,0 +1,134 @@
// File created from ScreenTemplate
// $ createScreen.sh Modal2/RoomCreation RoomCreationEventsModal
/*
Copyright 2020 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import Foundation
final class RoomCreationEventsModalViewModel: RoomCreationEventsModalViewModelType {
// MARK: - Properties
// MARK: Private
private let session: MXSession
private let bubbleData: MXKRoomBubbleCellDataStoring
private let roomState: MXRoomState
private var currentOperation: MXHTTPOperation?
private lazy var eventFormatter: EventFormatter = {
return EventFormatter(matrixSession: self.session)
}()
private var events: [MXEvent] = []
// MARK: Public
weak var viewDelegate: RoomCreationEventsModalViewModelViewDelegate?
weak var coordinatorDelegate: RoomCreationEventsModalViewModelCoordinatorDelegate?
var numberOfRows: Int {
return events.count
}
func rowViewModel(at indexPath: IndexPath) -> RoomCreationEventRowViewModel? {
let event = events[indexPath.row]
let formatterError = UnsafeMutablePointer<MXKEventFormatterError>.allocate(capacity: 1)
return RoomCreationEventRowViewModel(title: eventFormatter.attributedString(from: event, with: roomState, error: formatterError))
}
var roomName: String? {
if let name = roomState.name, name.count > 0 {
return name
}
if let aliases = roomState.aliases, aliases.count > 0 {
return aliases.first
}
return nil
}
var roomInfo: String? {
guard let creationEvent = events.first(where: { $0.eventType == .roomCreate }) else {
return nil
}
let timestamp = creationEvent.originServerTs
let date = Date(timeIntervalSince1970: TimeInterval(timestamp/1000))
let formatter = DateFormatter()
formatter.dateStyle = .full
return formatter.string(from: date)
}
func setAvatar(in avatarImageView: MXKImageView) {
let avatarImage = AvatarGenerator.generateAvatar(forMatrixItem: roomState.roomId, withDisplayName: roomName)
if let avatarUrl = roomState.avatar {
avatarImageView.enableInMemoryCache = true
avatarImageView.setImageURI(avatarUrl,
withType: nil,
andImageOrientation: .up,
toFitViewSize: avatarImageView.frame.size,
with: MXThumbnailingMethodCrop,
previewImage: avatarImage,
mediaManager: session.mediaManager)
} else {
avatarImageView.image = avatarImage
}
}
// MARK: - Setup
init(session: MXSession, bubbleData: MXKRoomBubbleCellDataStoring, roomState: MXRoomState) {
self.session = session
self.bubbleData = bubbleData
self.roomState = roomState
// shape-up events
events.append(contentsOf: bubbleData.events)
var nextBubbleData = bubbleData.nextCollapsableCellData
while nextBubbleData != nil {
events.append(contentsOf: nextBubbleData!.events)
nextBubbleData = nextBubbleData?.nextCollapsableCellData
}
}
deinit {
self.cancelOperations()
}
// MARK: - Public
func process(viewAction: RoomCreationEventsModalViewAction) {
switch viewAction {
case .loadData:
self.loadData()
case .close:
self.coordinatorDelegate?.roomCreationEventsModalViewModelDidTapClose(self)
case .cancel:
self.cancelOperations()
}
}
// MARK: - Private
private func loadData() {
self.update(viewState: .loading)
}
private func update(viewState: RoomCreationEventsModalViewState) {
self.viewDelegate?.roomCreationEventsModalViewModel(self, didUpdateViewState: viewState)
}
private func cancelOperations() {
self.currentOperation?.cancel()
}
}
@@ -0,0 +1,41 @@
// File created from ScreenTemplate
// $ createScreen.sh Modal2/RoomCreation RoomCreationEventsModal
/*
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 RoomCreationEventsModalViewModelViewDelegate: class {
func roomCreationEventsModalViewModel(_ viewModel: RoomCreationEventsModalViewModelType, didUpdateViewState viewSate: RoomCreationEventsModalViewState)
}
protocol RoomCreationEventsModalViewModelCoordinatorDelegate: class {
func roomCreationEventsModalViewModelDidTapClose(_ viewModel: RoomCreationEventsModalViewModelType)
}
/// Protocol describing the view model used by `RoomCreationEventsModalViewController`
protocol RoomCreationEventsModalViewModelType {
var viewDelegate: RoomCreationEventsModalViewModelViewDelegate? { get set }
var coordinatorDelegate: RoomCreationEventsModalViewModelCoordinatorDelegate? { get set }
func process(viewAction: RoomCreationEventsModalViewAction)
var numberOfRows: Int { get }
func rowViewModel(at indexPath: IndexPath) -> RoomCreationEventRowViewModel?
var roomName: String? { get }
var roomInfo: String? { get }
func setAvatar(in avatarImageView: MXKImageView)
}
@@ -0,0 +1,26 @@
// File created from ScreenTemplate
// $ createScreen.sh Modal2/RoomCreation RoomCreationEventsModal
/*
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
/// RoomCreationEventsModalViewController view state
enum RoomCreationEventsModalViewState {
case loading
case loaded(_ displayName: String)
case error(Error)
}