Swiftgram/TelegramUI/SecureIdAuthListFieldNode.swift
2018-06-16 20:03:02 +03:00

252 lines
10 KiB
Swift

import Foundation
import AsyncDisplayKit
import Display
import TelegramCore
private let titleFont = Font.regular(17.0)
private let textFont = Font.regular(15.0)
private func fieldsText(_ fields: String...) -> String {
var result = ""
for field in fields {
if !field.isEmpty {
if !result.isEmpty {
result.append(", ")
}
result.append(field)
}
}
return result
}
private func fieldsText(_ fields: [String]) -> String {
var result = ""
for field in fields {
if !field.isEmpty {
if !result.isEmpty {
result.append(", ")
}
result.append(field)
}
}
return result
}
private func fieldTitleAndText(field: SecureIdAuthListContentField, strings: PresentationStrings, values: [SecureIdValueWithContext]) -> (String, String) {
let title: String
let placeholder: String
var text: String = ""
switch field {
case .identity:
title = strings.SecureId_FormFieldIdentity
placeholder = strings.SecureId_FormFieldIdentityPlaceholder
let keyList: [(SecureIdValueKey, String)] = [
(.passport, "Passport"),
(.personalDetails, "Personal Details"),
(.internalPassport, "Internal Passport"),
(.driversLicense, "Driver's License"),
(.idCard, "ID Card")
]
var fields: [String] = []
for (key, valueTitle) in keyList {
if findValue(values, key: key) != nil {
fields.append(valueTitle)
}
}
if !fields.isEmpty {
text = fieldsText(fields)
}
case .address:
title = strings.SecureId_FormFieldAddress
placeholder = strings.SecureId_FormFieldAddressPlaceholder
let keyList: [(SecureIdValueKey, String)] = [
(.address, "Address"),
(.passportRegistration, "Passport Registration"),
(.temporaryRegistration, "Temporary Registration"),
(.utilityBill, "Utility Bill"),
(.bankStatement, "Bank Statement"),
(.rentalAgreement, "Rental Agreement")
]
var fields: [String] = []
for (key, valueTitle) in keyList {
if findValue(values, key: key) != nil {
fields.append(valueTitle)
}
}
if !fields.isEmpty {
text = fieldsText(fields)
}
case .phone:
title = strings.SecureId_FormFieldPhone
placeholder = strings.SecureId_FormFieldPhonePlaceholder
if let value = findValue(values, key: .phone), case let .phone(phoneValue) = value.1 {
if !text.isEmpty {
text.append(", ")
}
text = formatPhoneNumber(phoneValue.phone)
}
case .email:
title = strings.SecureId_FormFieldEmail
placeholder = strings.SecureId_FormFieldEmailPlaceholder
if let value = findValue(values, key: .email), case let .email(emailValue) = value.1 {
if !text.isEmpty {
text.append(", ")
}
text = formatPhoneNumber(emailValue.email)
}
}
return (title, text.isEmpty ? placeholder : text)
}
enum SecureIdAuthListContentField {
case identity
case address
case phone
case email
}
final class SecureIdAuthListFieldNode: ASDisplayNode {
private let selected: () -> Void
private let topSeparatorNode: ASDisplayNode
private let bottomSeparatorNode: ASDisplayNode
private let highlightedBackgroundNode: ASDisplayNode
private let titleNode: ImmediateTextNode
private let textNode: ImmediateTextNode
private let disclosureNode: ASImageNode
private let buttonNode: HighlightableButtonNode
private var validLayout: (CGFloat, Bool, Bool)?
private let field: SecureIdAuthListContentField
private let theme: PresentationTheme
private let strings: PresentationStrings
init(theme: PresentationTheme, strings: PresentationStrings, field: SecureIdAuthListContentField, values: [SecureIdValueWithContext], selected: @escaping () -> Void) {
self.field = field
self.theme = theme
self.strings = strings
self.selected = selected
self.topSeparatorNode = ASDisplayNode()
self.topSeparatorNode.isLayerBacked = true
self.topSeparatorNode.backgroundColor = theme.list.itemBlocksSeparatorColor
self.bottomSeparatorNode = ASDisplayNode()
self.bottomSeparatorNode.isLayerBacked = true
self.bottomSeparatorNode.backgroundColor = theme.list.itemBlocksSeparatorColor
self.highlightedBackgroundNode = ASDisplayNode()
self.highlightedBackgroundNode.isLayerBacked = true
self.highlightedBackgroundNode.backgroundColor = theme.list.itemHighlightedBackgroundColor
self.highlightedBackgroundNode.alpha = 0.0
self.titleNode = ImmediateTextNode()
self.titleNode.displaysAsynchronously = false
self.titleNode.isLayerBacked = true
self.titleNode.maximumNumberOfLines = 1
self.textNode = ImmediateTextNode()
self.textNode.displaysAsynchronously = false
self.textNode.isLayerBacked = true
self.textNode.maximumNumberOfLines = 1
self.disclosureNode = ASImageNode()
self.disclosureNode.isLayerBacked = true
self.disclosureNode.displayWithoutProcessing = true
self.disclosureNode.displaysAsynchronously = false
self.disclosureNode.image = PresentationResourcesItemList.disclosureArrowImage(theme)
self.buttonNode = HighlightableButtonNode()
super.init()
self.addSubnode(self.topSeparatorNode)
self.addSubnode(self.bottomSeparatorNode)
self.addSubnode(self.highlightedBackgroundNode)
self.addSubnode(self.titleNode)
self.addSubnode(self.textNode)
self.addSubnode(self.disclosureNode)
self.addSubnode(self.buttonNode)
self.updateValues(values)
self.buttonNode.highligthedChanged = { [weak self] highlighted in
if let strongSelf = self {
if highlighted {
strongSelf.highlightedBackgroundNode.layer.removeAnimation(forKey: "opacity")
strongSelf.highlightedBackgroundNode.alpha = 1.0
strongSelf.view.superview?.bringSubview(toFront: strongSelf.view)
} else {
strongSelf.highlightedBackgroundNode.alpha = 0.0
strongSelf.highlightedBackgroundNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2)
}
}
}
self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside)
}
func updateValues(_ values: [SecureIdValueWithContext]) {
let (title, text) = fieldTitleAndText(field: self.field, strings: self.strings, values: values)
let textColor = self.theme.list.itemSecondaryTextColor
self.titleNode.attributedText = NSAttributedString(string: title, font: titleFont, textColor: self.theme.list.itemPrimaryTextColor)
self.textNode.attributedText = NSAttributedString(string: text, font: textFont, textColor: textColor)
self.disclosureNode.isHidden = false
if let (width, hasPrevious, hasNext) = self.validLayout {
let _ = self.updateLayout(width: width, hasPrevious: hasPrevious, hasNext: hasNext, transition: .immediate)
}
}
func updateLayout(width: CGFloat, hasPrevious: Bool, hasNext: Bool, transition: ContainedViewLayoutTransition) -> CGFloat {
self.validLayout = (width, hasPrevious, hasNext)
let leftInset: CGFloat = 16.0
let rightInset: CGFloat = 16.0
let height: CGFloat = 64.0
let rightTextInset = rightInset + 24.0
let titleTextSpacing: CGFloat = 5.0
let titleSize = self.titleNode.updateLayout(CGSize(width: width - leftInset - rightTextInset, height: 100.0))
let textSize = self.textNode.updateLayout(CGSize(width: width - leftInset - rightTextInset, height: 100.0))
let textOrigin = floor((height - titleSize.height - titleTextSpacing - textSize.height) / 2.0)
let titleFrame = CGRect(origin: CGPoint(x: leftInset, y: textOrigin), size: titleSize)
self.titleNode.frame = titleFrame
let textFrame = CGRect(origin: CGPoint(x: leftInset, y: titleFrame.maxY + titleTextSpacing), size: textSize)
self.textNode.frame = textFrame
transition.updateFrame(node: self.topSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: UIScreenPixel)))
transition.updateAlpha(node: self.topSeparatorNode, alpha: hasPrevious ? 0.0 : 1.0)
let bottomSeparatorInset: CGFloat = hasNext ? leftInset : 0.0
transition.updateFrame(node: self.bottomSeparatorNode, frame: CGRect(origin: CGPoint(x: bottomSeparatorInset, y: height - UIScreenPixel), size: CGSize(width: width - bottomSeparatorInset, height: UIScreenPixel)))
transition.updateFrame(node: self.buttonNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: height)))
transition.updateFrame(node: self.highlightedBackgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -(hasPrevious ? UIScreenPixel : 0.0)), size: CGSize(width: width, height: height + (hasPrevious ? UIScreenPixel : 0.0))))
if let image = self.disclosureNode.image {
self.disclosureNode.frame = CGRect(origin: CGPoint(x: width - 15.0 - image.size.width, y: floor((height - image.size.height) / 2.0)), size: image.size)
}
return height
}
@objc private func buttonPressed() {
self.selected()
}
}