mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-22 17:42:45 +02:00
Create DM key verification cells.
This commit is contained in:
+223
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
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
|
||||
|
||||
@objcMembers
|
||||
class KeyVerificationBaseBubbleCell: MXKRoomBubbleTableViewCell {
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
private enum Sizing {
|
||||
static var sizes = Set<SizingViewHeight>()
|
||||
}
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Public
|
||||
|
||||
weak var keyVerificationCellInnerContentView: KeyVerificationCellInnerContentView?
|
||||
weak var bubbleCellWithoutSenderInfoContentView: BubbleCellWithoutSenderInfoContentView?
|
||||
|
||||
override var bubbleInfoContainer: UIView! {
|
||||
get {
|
||||
guard let infoContainer = self.bubbleCellWithoutSenderInfoContentView?.bubbleInfoContainer else {
|
||||
fatalError("[KeyVerificationBaseBubbleCell] bubbleInfoContainer should not be used before set")
|
||||
}
|
||||
return infoContainer
|
||||
}
|
||||
set {
|
||||
super.bubbleInfoContainer = newValue
|
||||
}
|
||||
}
|
||||
|
||||
override var bubbleOverlayContainer: UIView! {
|
||||
get {
|
||||
guard let overlayContainer = self.bubbleCellWithoutSenderInfoContentView?.bubbleOverlayContainer else {
|
||||
fatalError("[KeyVerificationBaseBubbleCell] bubbleOverlayContainer should not be used before set")
|
||||
}
|
||||
return overlayContainer
|
||||
}
|
||||
set {
|
||||
super.bubbleInfoContainer = newValue
|
||||
}
|
||||
}
|
||||
|
||||
override var bubbleInfoContainerTopConstraint: NSLayoutConstraint! {
|
||||
get {
|
||||
guard let infoContainerTopConstraint = self.bubbleCellWithoutSenderInfoContentView?.bubbleInfoContainerTopConstraint else {
|
||||
fatalError("[KeyVerificationBaseBubbleCell] bubbleInfoContainerTopConstraint should not be used before set")
|
||||
}
|
||||
return infoContainerTopConstraint
|
||||
}
|
||||
set {
|
||||
super.bubbleInfoContainerTopConstraint = newValue
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
self.commonInit()
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
private func commonInit() {
|
||||
|
||||
self.selectionStyle = .none
|
||||
self.setupContentView()
|
||||
self.update(theme: ThemeService.shared().theme)
|
||||
|
||||
super.setupViews()
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func update(theme: Theme) {
|
||||
self.bubbleCellWithoutSenderInfoContentView?.update(theme: theme)
|
||||
self.keyVerificationCellInnerContentView?.update(theme: theme)
|
||||
}
|
||||
|
||||
func buildUserInfoText(with userId: String, userDisplayName: String?) -> String {
|
||||
|
||||
let userInfoText: String
|
||||
|
||||
if let userDisplayName = userDisplayName {
|
||||
userInfoText = "\(userId) (\(userDisplayName))"
|
||||
} else {
|
||||
userInfoText = userId
|
||||
}
|
||||
|
||||
return userInfoText
|
||||
}
|
||||
|
||||
func senderId(from bubbleCellData: MXKRoomBubbleCellData) -> String {
|
||||
return bubbleCellData.senderId ?? ""
|
||||
}
|
||||
|
||||
func senderDisplayName(from bubbleCellData: MXKRoomBubbleCellData) -> String? {
|
||||
let senderId = self.senderId(from: bubbleCellData)
|
||||
guard let senderDisplayName = bubbleCellData.senderDisplayName, senderId != senderDisplayName else {
|
||||
return nil
|
||||
}
|
||||
return senderDisplayName
|
||||
}
|
||||
|
||||
class func sizingView() -> MXKRoomBubbleTableViewCell {
|
||||
fatalError("[KeyVerificationBaseBubbleCell] Subclass should implement this method")
|
||||
}
|
||||
|
||||
// TODO: Implement thiscmethod in subclasses
|
||||
class func sizingHeightHashValue(from bubbleData: MXKRoomBubbleCellData) -> Int {
|
||||
return bubbleData.hashValue
|
||||
}
|
||||
|
||||
// MARK: - Overrides
|
||||
|
||||
override class func defaultReuseIdentifier() -> String! {
|
||||
return String(describing: self)
|
||||
}
|
||||
|
||||
override func didEndDisplay() {
|
||||
super.didEndDisplay()
|
||||
self.removeReadReceiptsView()
|
||||
}
|
||||
|
||||
override class func height(for cellData: MXKCellData!, withMaximumWidth maxWidth: CGFloat) -> CGFloat {
|
||||
guard let cellData = cellData else {
|
||||
return 0
|
||||
}
|
||||
|
||||
guard let roomBubbleCellData = cellData as? MXKRoomBubbleCellData else {
|
||||
return 0
|
||||
}
|
||||
|
||||
let height: CGFloat
|
||||
|
||||
let sizingViewHeight = self.findOrCreateSizingViewHeight(from: roomBubbleCellData)
|
||||
|
||||
if let cachedHeight = sizingViewHeight.heights[maxWidth] {
|
||||
height = cachedHeight
|
||||
} else {
|
||||
height = self.contentViewHeight(for: roomBubbleCellData, fitting: maxWidth)
|
||||
sizingViewHeight.heights[maxWidth] = height
|
||||
}
|
||||
|
||||
return height
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func setupContentView() {
|
||||
if self.bubbleCellWithoutSenderInfoContentView == nil {
|
||||
|
||||
let bubbleCellWithoutSenderInfoContentView = BubbleCellWithoutSenderInfoContentView.instantiate()
|
||||
|
||||
let innerContentView = KeyVerificationCellInnerContentView.instantiate()
|
||||
|
||||
bubbleCellWithoutSenderInfoContentView.innerContentView.vc_addSubViewMatchingParent(innerContentView)
|
||||
|
||||
self.contentView.vc_addSubViewMatchingParent(bubbleCellWithoutSenderInfoContentView)
|
||||
|
||||
self.bubbleCellWithoutSenderInfoContentView = bubbleCellWithoutSenderInfoContentView
|
||||
self.keyVerificationCellInnerContentView = innerContentView
|
||||
}
|
||||
}
|
||||
|
||||
private static func findOrCreateSizingViewHeight(from bubbleData: MXKRoomBubbleCellData) -> SizingViewHeight {
|
||||
|
||||
let sizingViewHeight: SizingViewHeight
|
||||
let bubbleDataHashValue = bubbleData.hashValue
|
||||
|
||||
if let foundSizingViewHeight = self.Sizing.sizes.first(where: { (sizingViewHeight) -> Bool in
|
||||
return sizingViewHeight.uniqueIdentifier == bubbleDataHashValue
|
||||
}) {
|
||||
sizingViewHeight = foundSizingViewHeight
|
||||
} else {
|
||||
sizingViewHeight = SizingViewHeight(uniqueIdentifier: bubbleDataHashValue)
|
||||
}
|
||||
|
||||
return sizingViewHeight
|
||||
}
|
||||
|
||||
private static func contentViewHeight(for cellData: MXKCellData, fitting width: CGFloat) -> CGFloat {
|
||||
let sizingView = self.sizingView()
|
||||
|
||||
sizingView.render(cellData)
|
||||
sizingView.layoutIfNeeded()
|
||||
|
||||
let fittingSize = CGSize(width: width, height: UIView.layoutFittingCompressedSize.height)
|
||||
let height = sizingView.systemLayoutSizeFitting(fittingSize).height
|
||||
|
||||
return height
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - BubbleCellReadReceiptsDisplayable
|
||||
extension KeyVerificationBaseBubbleCell: BubbleCellReadReceiptsDisplayable {
|
||||
|
||||
func addReadReceiptsView(_ readReceiptsView: UIView) {
|
||||
self.bubbleCellWithoutSenderInfoContentView?.addReadReceiptsView(readReceiptsView)
|
||||
}
|
||||
|
||||
func removeReadReceiptsView() {
|
||||
self.bubbleCellWithoutSenderInfoContentView?.removeReadReceiptsView()
|
||||
}
|
||||
}
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
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
|
||||
import Reusable
|
||||
|
||||
final class KeyVerificationCellInnerContentView: UIView, NibLoadable {
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
private enum Constants {
|
||||
static let cornerRadius: CGFloat = 8.0
|
||||
static let buttonBackgroundColorAlpha: CGFloat = 0.8
|
||||
static let buttonCornerRadius: CGFloat = 6.0
|
||||
}
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Outlets
|
||||
|
||||
@IBOutlet private weak var badgeImageView: UIImageView!
|
||||
@IBOutlet private weak var titleLabel: UILabel!
|
||||
|
||||
@IBOutlet private weak var userInformationsLabel: UILabel!
|
||||
|
||||
@IBOutlet private weak var requestStatusLabel: UILabel!
|
||||
|
||||
@IBOutlet private weak var acceptButton: UIButton!
|
||||
@IBOutlet private weak var declineButton: UIButton!
|
||||
|
||||
// MARK: Public
|
||||
|
||||
var isButtonsHidden: Bool {
|
||||
get {
|
||||
return self.acceptButton.isHidden && self.declineButton.isHidden
|
||||
}
|
||||
set {
|
||||
self.acceptButton.isHidden = newValue
|
||||
self.declineButton.isHidden = newValue
|
||||
}
|
||||
}
|
||||
|
||||
var isRequestStatusHidden: Bool {
|
||||
get {
|
||||
return self.requestStatusLabel.isHidden
|
||||
}
|
||||
set {
|
||||
self.requestStatusLabel.isHidden = newValue
|
||||
}
|
||||
}
|
||||
|
||||
var badgeImage: UIImage? {
|
||||
get {
|
||||
return self.badgeImageView.image
|
||||
}
|
||||
set {
|
||||
self.badgeImageView.image = newValue
|
||||
}
|
||||
}
|
||||
|
||||
var title: String? {
|
||||
get {
|
||||
return self.titleLabel.text
|
||||
}
|
||||
set {
|
||||
self.titleLabel.text = newValue
|
||||
}
|
||||
}
|
||||
|
||||
var requestStatusText: String? {
|
||||
get {
|
||||
return self.requestStatusLabel.text
|
||||
}
|
||||
set {
|
||||
self.requestStatusLabel.text = newValue
|
||||
}
|
||||
}
|
||||
|
||||
var acceptActionHandler: (() -> Void)?
|
||||
|
||||
var declineActionHandler: (() -> Void)?
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
static func instantiate() -> KeyVerificationCellInnerContentView {
|
||||
let view = KeyVerificationCellInnerContentView.loadFromNib()
|
||||
return view
|
||||
}
|
||||
|
||||
// MARK: - Life cycle
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
self.layer.masksToBounds = true
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
self.layer.cornerRadius = Constants.cornerRadius
|
||||
|
||||
if self.isButtonsHidden == false {
|
||||
self.acceptButton.layer.cornerRadius = Constants.buttonCornerRadius
|
||||
self.declineButton.layer.cornerRadius = Constants.buttonCornerRadius
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
func update(theme: Theme) {
|
||||
self.backgroundColor = theme.headerBackgroundColor
|
||||
self.titleLabel.textColor = theme.textPrimaryColor
|
||||
self.userInformationsLabel.textColor = theme.textSecondaryColor
|
||||
|
||||
self.acceptButton.vc_setBackgroundColor(theme.tintColor.withAlphaComponent(Constants.buttonBackgroundColorAlpha), for: .normal)
|
||||
self.declineButton.vc_setBackgroundColor(theme.noticeColor.withAlphaComponent(Constants.buttonBackgroundColorAlpha), for: .normal)
|
||||
}
|
||||
|
||||
func updateSenderInfo(with userId: String, userDisplayName: String?) {
|
||||
self.userInformationsLabel.text = self.buildUserInfoText(with: userId, userDisplayName: userDisplayName)
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func buildUserInfoText(with userId: String, userDisplayName: String?) -> String {
|
||||
|
||||
let userInfoText: String
|
||||
|
||||
if let userDisplayName = userDisplayName {
|
||||
userInfoText = "\(userId) (\(userDisplayName))"
|
||||
} else {
|
||||
userInfoText = userId
|
||||
}
|
||||
|
||||
return userInfoText
|
||||
}
|
||||
|
||||
@IBAction private func declineButtonAction(_ sender: Any) {
|
||||
self.declineActionHandler?()
|
||||
}
|
||||
|
||||
@IBAction private func acceptButtonAction(_ sender: Any) {
|
||||
self.acceptActionHandler?()
|
||||
}
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina6_1" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="iN0-l3-epB" customClass="KeyVerificationCellInnerContentView" customModule="Riot" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="313" height="159"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" spacing="17" translatesAutoresizingMaskIntoConstraints="NO" id="2Sr-GM-aAU">
|
||||
<rect key="frame" x="10" y="10" width="293" height="139"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" spacing="4" translatesAutoresizingMaskIntoConstraints="NO" id="5gD-pX-GFz">
|
||||
<rect key="frame" x="70" y="0.0" width="153.5" height="18"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="encryption_normal" translatesAutoresizingMaskIntoConstraints="NO" id="EHJ-3L-OPJ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="16" height="18"/>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Verification request" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="BOd-4B-LQX">
|
||||
<rect key="frame" x="20" y="0.0" width="133.5" height="18"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</stackView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="User (@user:matrix.org)" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="e1n-WP-GTb">
|
||||
<rect key="frame" x="83.5" y="35" width="126" height="13.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
||||
<color key="textColor" red="0.1803921568627451" green="0.18431372549019609" blue="0.19607843137254902" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Waiting..." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="e6I-aZ-RRO">
|
||||
<rect key="frame" x="118" y="65.5" width="57" height="16"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="13"/>
|
||||
<color key="textColor" red="0.38039215686274508" green="0.4392156862745098" blue="0.54509803921568623" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" distribution="equalSpacing" alignment="center" spacing="30" translatesAutoresizingMaskIntoConstraints="NO" id="WxG-vh-Bn0">
|
||||
<rect key="frame" x="44.5" y="98.5" width="204" height="40.5"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="atD-LF-sGH">
|
||||
<rect key="frame" x="0.0" y="11.5" width="105" height="18"/>
|
||||
<inset key="contentEdgeInsets" minX="10" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="Decline (60)">
|
||||
<color key="titleColor" red="1" green="0.29411764705882354" blue="0.33333333333333331" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="declineButtonAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="dS6-Xr-6jZ"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="irs-8W-qcs">
|
||||
<rect key="frame" x="135" y="11.5" width="69" height="18"/>
|
||||
<inset key="contentEdgeInsets" minX="10" minY="0.0" maxX="10" maxY="0.0"/>
|
||||
<state key="normal" title="Accept">
|
||||
<color key="titleColor" red="0.011764705882352941" green="0.70196078431372544" blue="0.50588235294117645" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="acceptButtonAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="IQ6-be-vJt"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</stackView>
|
||||
</subviews>
|
||||
</stackView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.95294117647058818" green="0.97254901960784312" blue="0.99215686274509807" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="2Sr-GM-aAU" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="10" id="M7S-MY-Jxk"/>
|
||||
<constraint firstItem="2Sr-GM-aAU" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="10" id="SfH-5W-p30"/>
|
||||
<constraint firstAttribute="trailing" secondItem="2Sr-GM-aAU" secondAttribute="trailing" constant="10" id="rVw-1F-ch3"/>
|
||||
<constraint firstAttribute="bottom" secondItem="2Sr-GM-aAU" secondAttribute="bottom" constant="10" id="vL2-dm-qbe"/>
|
||||
</constraints>
|
||||
<nil key="simulatedTopBarMetrics"/>
|
||||
<nil key="simulatedBottomBarMetrics"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<connections>
|
||||
<outlet property="acceptButton" destination="irs-8W-qcs" id="LKq-qE-bbg"/>
|
||||
<outlet property="badgeImageView" destination="EHJ-3L-OPJ" id="eNW-bg-eYy"/>
|
||||
<outlet property="declineButton" destination="atD-LF-sGH" id="CfI-FW-ySy"/>
|
||||
<outlet property="requestStatusLabel" destination="e6I-aZ-RRO" id="zQf-qy-3Rq"/>
|
||||
<outlet property="titleLabel" destination="BOd-4B-LQX" id="4sw-3J-faF"/>
|
||||
<outlet property="userInformationsLabel" destination="e1n-WP-GTb" id="jhY-gH-QnO"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="-408" y="-225"/>
|
||||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="encryption_normal" width="16" height="16"/>
|
||||
</resources>
|
||||
</document>
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
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 KeyVerificationConclusionBubbleCell: KeyVerificationBaseBubbleCell {
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
private enum Sizing {
|
||||
static let view = KeyVerificationConclusionBubbleCell(style: .default, reuseIdentifier: nil)
|
||||
}
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
self.commonInit()
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
private func commonInit() {
|
||||
self.keyVerificationCellInnerContentView?.isButtonsHidden = true
|
||||
self.keyVerificationCellInnerContentView?.isRequestStatusHidden = true
|
||||
}
|
||||
|
||||
// MARK: - Overrides
|
||||
|
||||
override func render(_ cellData: MXKCellData!) {
|
||||
super.render(cellData)
|
||||
|
||||
guard let keyVerificationCellInnerContentView = self.keyVerificationCellInnerContentView,
|
||||
let bubbleData = self.bubbleData,
|
||||
let viewData = self.viewData(from: bubbleData) else {
|
||||
NSLog("[KeyVerificationConclusionBubbleCell] Fail to render \(String(describing: cellData))")
|
||||
return
|
||||
}
|
||||
|
||||
keyVerificationCellInnerContentView.badgeImage = viewData.badgeImage
|
||||
keyVerificationCellInnerContentView.title = viewData.title
|
||||
keyVerificationCellInnerContentView.updateSenderInfo(with: viewData.senderId, userDisplayName: viewData.senderDisplayName)
|
||||
}
|
||||
|
||||
override class func sizingView() -> MXKRoomBubbleTableViewCell {
|
||||
return self.Sizing.view
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
// TODO: Handle view data filling
|
||||
private func viewData(from bubbleData: MXKRoomBubbleCellData) -> KeyVerificationConclusionViewData? {
|
||||
guard let event = bubbleData.bubbleComponents.first?.event else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let viewData: KeyVerificationConclusionViewData?
|
||||
|
||||
let senderId = self.senderId(from: bubbleData)
|
||||
let senderDisplayName = self.senderDisplayName(from: bubbleData)
|
||||
let title: String?
|
||||
let badgeImage: UIImage?
|
||||
|
||||
switch event.eventType {
|
||||
case .keyVerificationDone:
|
||||
title = "Verified"
|
||||
badgeImage = Asset.Images.encryptionTrusted.image
|
||||
case .keyVerificationCancel:
|
||||
title = "Cancelled"
|
||||
badgeImage = Asset.Images.encryptionNormal.image
|
||||
default:
|
||||
badgeImage = nil
|
||||
title = nil
|
||||
}
|
||||
|
||||
if let title = title, let badgeImage = badgeImage {
|
||||
viewData = KeyVerificationConclusionViewData(badgeImage: badgeImage,
|
||||
title: title,
|
||||
senderId: senderId,
|
||||
senderDisplayName: senderDisplayName)
|
||||
} else {
|
||||
viewData = nil
|
||||
}
|
||||
|
||||
return viewData
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
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
|
||||
|
||||
struct KeyVerificationConclusionViewData {
|
||||
let badgeImage: UIImage
|
||||
let title: String
|
||||
let senderId: String
|
||||
let senderDisplayName: String?
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
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 KeyVerificationIncomingRequestApprovalBubbleCell: KeyVerificationBaseBubbleCell {
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
private enum Sizing {
|
||||
static let view = KeyVerificationConclusionBubbleCell(style: .default, reuseIdentifier: nil)
|
||||
}
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
self.commonInit()
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
private func commonInit() {
|
||||
guard let keyVerificationCellInnerContentView = self.keyVerificationCellInnerContentView else {
|
||||
fatalError("[KeyVerificationIncomingRequestApprovalBubbleCell] keyVerificationCellInnerContentView should not be nil")
|
||||
}
|
||||
|
||||
keyVerificationCellInnerContentView.isButtonsHidden = false
|
||||
keyVerificationCellInnerContentView.isRequestStatusHidden = true
|
||||
keyVerificationCellInnerContentView.badgeImage = Asset.Images.encryptionNormal.image
|
||||
}
|
||||
|
||||
// MARK: - Overrides
|
||||
|
||||
override func prepareForReuse() {
|
||||
super.prepareForReuse()
|
||||
|
||||
self.keyVerificationCellInnerContentView?.acceptActionHandler = nil
|
||||
self.keyVerificationCellInnerContentView?.declineActionHandler = nil
|
||||
}
|
||||
|
||||
override func render(_ cellData: MXKCellData!) {
|
||||
super.render(cellData)
|
||||
|
||||
guard let keyVerificationCellInnerContentView = self.keyVerificationCellInnerContentView,
|
||||
let bubbleData = self.bubbleData,
|
||||
let viewData = self.viewData(from: bubbleData) else {
|
||||
NSLog("[KeyVerificationIncomingRequestApprovalBubbleCell] Fail to render \(String(describing: cellData))")
|
||||
return
|
||||
}
|
||||
|
||||
keyVerificationCellInnerContentView.title = viewData.title
|
||||
keyVerificationCellInnerContentView.updateSenderInfo(with: viewData.senderId, userDisplayName: viewData.senderDisplayName)
|
||||
|
||||
keyVerificationCellInnerContentView.acceptActionHandler = { [weak self] in
|
||||
// TODO: Use correct action identifier
|
||||
self?.delegate?.cell(self, didRecognizeAction: kMXKRoomBubbleCellTapOnContentView, userInfo: nil)
|
||||
}
|
||||
|
||||
keyVerificationCellInnerContentView.declineActionHandler = { [weak self] in
|
||||
// TODO: Use correct action identifier
|
||||
self?.delegate?.cell(self, didRecognizeAction: kMXKRoomBubbleCellTapOnContentView, userInfo: nil)
|
||||
}
|
||||
}
|
||||
|
||||
override class func sizingView() -> MXKRoomBubbleTableViewCell {
|
||||
return self.Sizing.view
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
// TODO: Handle view data filling
|
||||
private func viewData(from bubbleData: MXKRoomBubbleCellData) -> KeyVerificationIncomingRequestApprovalViewData? {
|
||||
|
||||
let senderId = self.senderId(from: bubbleData)
|
||||
let senderDisplayName = self.senderDisplayName(from: bubbleData)
|
||||
let title = "Verification request"
|
||||
|
||||
return KeyVerificationIncomingRequestApprovalViewData(title: title,
|
||||
senderId: senderId,
|
||||
senderDisplayName: senderDisplayName)
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
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
|
||||
|
||||
struct KeyVerificationIncomingRequestApprovalViewData {
|
||||
let title: String
|
||||
let senderId: String
|
||||
let senderDisplayName: String?
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
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 KeyVerificationRequestStatusBubbleCell: KeyVerificationBaseBubbleCell {
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
private enum Sizing {
|
||||
static let view = KeyVerificationRequestStatusBubbleCell(style: .default, reuseIdentifier: nil)
|
||||
}
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
self.commonInit()
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
private func commonInit() {
|
||||
guard let keyVerificationCellInnerContentView = self.keyVerificationCellInnerContentView else {
|
||||
fatalError("[KeyVerificationRequestStatusBubbleCell] keyVerificationCellInnerContentView should not be nil")
|
||||
}
|
||||
|
||||
keyVerificationCellInnerContentView.isButtonsHidden = true
|
||||
keyVerificationCellInnerContentView.isRequestStatusHidden = false
|
||||
keyVerificationCellInnerContentView.badgeImage = Asset.Images.encryptionNormal.image
|
||||
}
|
||||
|
||||
// MARK: - Overrides
|
||||
|
||||
override func render(_ cellData: MXKCellData!) {
|
||||
super.render(cellData)
|
||||
|
||||
guard let keyVerificationCellInnerContentView = self.keyVerificationCellInnerContentView,
|
||||
let bubbleData = self.bubbleData,
|
||||
let viewData = self.viewData(from: bubbleData) else {
|
||||
NSLog("[KeyVerificationRequestStatusBubbleCell] Fail to render \(String(describing: cellData))")
|
||||
return
|
||||
}
|
||||
|
||||
keyVerificationCellInnerContentView.title = viewData.title
|
||||
keyVerificationCellInnerContentView.updateSenderInfo(with: viewData.senderId, userDisplayName: viewData.senderDisplayName)
|
||||
keyVerificationCellInnerContentView.requestStatusText = viewData.statusText
|
||||
}
|
||||
|
||||
override class func sizingView() -> MXKRoomBubbleTableViewCell {
|
||||
return self.Sizing.view
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
// TODO: Handle view data filling
|
||||
private func viewData(from bubbleData: MXKRoomBubbleCellData) -> KeyVerificationRequestStatusViewData? {
|
||||
|
||||
let senderId = self.senderId(from: bubbleData)
|
||||
let senderDisplayName = self.senderDisplayName(from: bubbleData)
|
||||
let title: String
|
||||
let statusText: String = "You accepted"
|
||||
|
||||
if senderId.isEmpty == false {
|
||||
title = "Verification request"
|
||||
} else {
|
||||
title = "Verification sent"
|
||||
}
|
||||
|
||||
return KeyVerificationRequestStatusViewData(title: title,
|
||||
senderId: senderId,
|
||||
senderDisplayName: senderDisplayName,
|
||||
statusText: statusText)
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
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
|
||||
|
||||
struct KeyVerificationRequestStatusViewData {
|
||||
let title: String
|
||||
let senderId: String
|
||||
let senderDisplayName: String?
|
||||
let statusText: String
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
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
|
||||
|
||||
final class SizingViewHeight: Hashable, Equatable {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
let uniqueIdentifier: Int
|
||||
var heights: [CGFloat /* width */: CGFloat /* height */] = [:]
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(uniqueIdentifier: Int) {
|
||||
self.uniqueIdentifier = uniqueIdentifier
|
||||
}
|
||||
|
||||
// MARK: - Hashable
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(self.uniqueIdentifier)
|
||||
}
|
||||
|
||||
// MARK: - Equatable
|
||||
|
||||
static func == (lhs: SizingViewHeight, rhs: SizingViewHeight) -> Bool {
|
||||
return lhs.uniqueIdentifier == rhs.uniqueIdentifier
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user