Swiftgram/submodules/AuthTransferUI/Sources/AuthTransferConfirmationScreen.swift
2019-11-29 18:53:11 +04:00

167 lines
9.1 KiB
Swift

import Foundation
import UIKit
import AppBundle
import AsyncDisplayKit
import Display
import SolidRoundedButtonNode
import SwiftSignalKit
import OverlayStatusController
import AnimatedStickerNode
import TelegramPresentationData
import TelegramCore
import AccountContext
final class AuthTransferConfirmationNode: ASDisplayNode {
private let context: AccountContext
private var presentationData: PresentationData
private let tokenInfo: AuthTransferTokenInfo
private let containerNode: ASDisplayNode
private let backgroundNode: ASImageNode
private let iconNode: ASImageNode
private let titleNode: ImmediateTextNode
private let appNameNode: ImmediateTextNode
private let locationInfoNode: ImmediateTextNode
private let acceptButtonNode: SolidRoundedButtonNode
private let cancelButtonNode: SolidRoundedButtonNode
private var validLayout: (ContainerViewLayout, CGFloat)?
init(context: AccountContext, presentationData: PresentationData, tokenInfo: AuthTransferTokenInfo, accept: @escaping () -> Void, cancel: @escaping () -> Void) {
self.context = context
self.presentationData = presentationData
self.tokenInfo = tokenInfo
self.containerNode = ASDisplayNode()
self.backgroundNode = ASImageNode()
self.backgroundNode.displayWithoutProcessing = true
self.backgroundNode.displaysAsynchronously = false
self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 24.0, color: self.presentationData.theme.list.plainBackgroundColor)
self.iconNode = ASImageNode()
self.iconNode.displayWithoutProcessing = true
self.iconNode.displaysAsynchronously = false
self.iconNode.image = UIImage(bundleImageName: "Settings/TransferAuthLaptop")
self.titleNode = ImmediateTextNode()
self.titleNode.textAlignment = .center
self.titleNode.maximumNumberOfLines = 2
self.appNameNode = ImmediateTextNode()
self.appNameNode.textAlignment = .center
self.appNameNode.maximumNumberOfLines = 2
self.locationInfoNode = ImmediateTextNode()
self.locationInfoNode.textAlignment = .center
self.locationInfoNode.maximumNumberOfLines = 0
self.acceptButtonNode = SolidRoundedButtonNode(title: presentationData.strings.AuthSessions_AddDevice_ConfirmDevice, icon: nil, theme: SolidRoundedButtonTheme(backgroundColor: self.presentationData.theme.list.itemDestructiveColor, foregroundColor: self.presentationData.theme.list.itemCheckColors.foregroundColor), height: 50.0, cornerRadius: 10.0, gloss: false)
self.cancelButtonNode = SolidRoundedButtonNode(title: self.presentationData.strings.Common_Cancel, icon: nil, theme: SolidRoundedButtonTheme(backgroundColor: self.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: self.presentationData.theme.list.itemCheckColors.foregroundColor), height: 50.0, cornerRadius: 10.0, gloss: false)
super.init()
self.addSubnode(self.containerNode)
self.containerNode.addSubnode(self.backgroundNode)
self.containerNode.addSubnode(self.iconNode)
self.containerNode.addSubnode(self.titleNode)
self.containerNode.addSubnode(self.appNameNode)
self.containerNode.addSubnode(self.locationInfoNode)
self.containerNode.addSubnode(self.acceptButtonNode)
self.containerNode.addSubnode(self.cancelButtonNode)
let titleFont = Font.bold(24.0)
let subtitleFont = Font.regular(16.0)
let textColor = self.presentationData.theme.list.itemPrimaryTextColor
let seccondaryTextColor = self.presentationData.theme.list.itemSecondaryTextColor
self.titleNode.attributedText = NSAttributedString(string: "\(tokenInfo.appName)", font: titleFont, textColor: textColor)
self.appNameNode.attributedText = NSAttributedString(string: "\(tokenInfo.deviceModel), \(tokenInfo.platform) \(tokenInfo.systemVersion)", font: subtitleFont, textColor: seccondaryTextColor)
self.locationInfoNode.attributedText = NSAttributedString(string: "\(tokenInfo.region)\nIP: \(tokenInfo.ip)", font: subtitleFont, textColor: seccondaryTextColor)
self.acceptButtonNode.pressed = { [weak self] in
accept()
}
self.cancelButtonNode.pressed = {
cancel()
}
}
override func didLoad() {
super.didLoad()
}
func animateIn() {
self.containerNode.layer.animatePosition(from: CGPoint(x: 0.0, y: self.containerNode.bounds.height), to: CGPoint(), duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
}
func animateOut(completion: @escaping () -> Void) {
self.containerNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: self.containerNode.bounds.height), duration: 0.3, removeOnCompletion: false, additive: true, completion: { _ in
completion()
})
}
func updateLayout(layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
var insets = layout.insets(options: [])
let sideInset: CGFloat = 22.0
let buttonSideInset: CGFloat = 16.0
let bottomInset = insets.bottom + 10.0
let buttonWidth = layout.size.width - buttonSideInset * 2.0
let buttonHeight: CGFloat = 50.0
let buttonSpacing: CGFloat = 20.0
let contentButtonSpacing: CGFloat = 35.0
let titleSpacing: CGFloat = 1.0
let locationSpacing: CGFloat = 35.0
let iconSpacing: CGFloat = 35.0
let topInset: CGFloat = 35.0
let iconSize = self.iconNode.image?.size ?? CGSize(width: 10.0, height: 1.0)
let titleSize = self.titleNode.updateLayout(CGSize(width: layout.size.width - sideInset * 2.0, height: .greatestFiniteMagnitude))
let appNameSize = self.appNameNode.updateLayout(CGSize(width: layout.size.width - sideInset * 2.0, height: .greatestFiniteMagnitude))
let locationSize = self.locationInfoNode.updateLayout(CGSize(width: layout.size.width - sideInset * 2.0, height: .greatestFiniteMagnitude))
var contentHeight: CGFloat = 0.0
contentHeight += topInset + iconSize.height
contentHeight += iconSpacing + titleSize.height
contentHeight += titleSpacing + appNameSize.height
contentHeight += locationSpacing + locationSize.height
contentHeight += contentButtonSpacing + bottomInset + buttonHeight + buttonSpacing + buttonHeight
let iconFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - iconSize.width) / 2.0), y: topInset), size: iconSize)
transition.updateFrame(node: self.iconNode, frame: iconFrame)
let titleFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - titleSize.width) / 2.0), y: iconFrame.maxY + iconSpacing), size: titleSize)
transition.updateFrame(node: self.titleNode, frame: titleFrame)
let appNameFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - appNameSize.width) / 2.0), y: titleFrame.maxY + titleSpacing), size: appNameSize)
transition.updateFrame(node: self.appNameNode, frame: appNameFrame)
let locationFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - locationSize.width) / 2.0), y: appNameFrame.maxY + locationSpacing), size: locationSize)
transition.updateFrame(node: self.locationInfoNode, frame: locationFrame)
let cancelButtonFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - buttonWidth) / 2.0), y: contentHeight - bottomInset - buttonHeight), size: CGSize(width: buttonWidth, height: buttonHeight))
transition.updateFrame(node: self.cancelButtonNode, frame: cancelButtonFrame)
self.cancelButtonNode.updateLayout(width: cancelButtonFrame.width, transition: transition)
let acceptButtonFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - buttonWidth) / 2.0), y: cancelButtonFrame.minY - buttonSpacing - buttonHeight), size: CGSize(width: buttonWidth, height: buttonHeight))
transition.updateFrame(node: self.acceptButtonNode, frame: acceptButtonFrame)
self.acceptButtonNode.updateLayout(width: acceptButtonFrame.width, transition: transition)
transition.updateFrame(node: self.containerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - contentHeight), size: CGSize(width: layout.size.width, height: contentHeight)))
transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: layout.size.width, height: contentHeight + 24.0)))
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if let result = self.cancelButtonNode.view.hitTest(self.view.convert(point, to: self.cancelButtonNode.view), with: event) {
return result
}
if let result = self.acceptButtonNode.view.hitTest(self.view.convert(point, to: self.acceptButtonNode.view), with: event) {
return result
}
return super.hitTest(point, with: event)
}
}