import Foundation import UIKit import Display import AsyncDisplayKit import TelegramCore import SyncCore import TelegramPresentationData import TextFormat import AccountContext import AlertUI import PresentationDataUtils import AppBundle import Markdown import PhoneNumberFormat private final class ChangePhoneNumberIntroControllerNode: ASDisplayNode { var presentationData: PresentationData let iconNode: ASImageNode let labelNode: ASTextNode let buttonNode: HighlightableButtonNode var dismiss: (() -> Void)? var action: (() -> Void)? init(presentationData: PresentationData) { self.presentationData = presentationData self.iconNode = ASImageNode() self.labelNode = ASTextNode() self.buttonNode = HighlightableButtonNode() super.init() self.setViewBlock({ return UITracingLayerView() }) self.iconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Settings/ChangePhoneIntroIcon"), color: presentationData.theme.list.freeMonoIconColor) let textColor = self.presentationData.theme.list.freeTextColor self.labelNode.attributedText = parseMarkdownIntoAttributedString(self.presentationData.strings.PhoneNumberHelp_Help, attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: Font.regular(14.0), textColor: textColor), bold: MarkdownAttributeSet(font: Font.semibold(14.0), textColor: textColor), link: MarkdownAttributeSet(font: Font.regular(14.0), textColor: textColor), linkAttribute: { _ in return nil }), textAlignment: .center) self.buttonNode.setTitle(self.presentationData.strings.PhoneNumberHelp_ChangeNumber, with: Font.regular(19.0), with: self.presentationData.theme.list.itemAccentColor, for: .normal) self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside) self.addSubnode(self.iconNode) self.addSubnode(self.labelNode) self.addSubnode(self.buttonNode) self.backgroundColor = self.presentationData.theme.list.blocksBackgroundColor } func animateIn() { self.layer.animatePosition(from: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), to: self.layer.position, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring) } func animateOut() { self.layer.animatePosition(from: self.layer.position, to: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), duration: 0.2, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false, completion: { [weak self] _ in if let strongSelf = self { strongSelf.dismiss?() } }) } func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) { var insets = layout.insets(options: [.statusBar]) insets.top += navigationBarHeight let availableHeight = layout.size.height - insets.top - insets.bottom let largeScreen = availableHeight >= 420.0 let contentHeight: CGFloat = largeScreen ? 420.0 : 400.0 let iconSize = self.iconNode.measure(CGSize(width: 400.0, height: 400.0)) let labelSize = self.labelNode.updateLayout(CGSize(width: 295.0, height: CGFloat.greatestFiniteMagnitude)) let buttonSize = self.buttonNode.measure(CGSize(width: 295.0, height: CGFloat.greatestFiniteMagnitude)) transition.updateFrame(node: self.iconNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - iconSize.width) / 2.0), y: insets.top + floor((availableHeight - contentHeight) / 2.0) + floor(iconSize.height * (largeScreen ? CGFloat(0.2) : CGFloat(0.5)))), size: iconSize)) transition.updateFrame(node: self.labelNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - labelSize.width) / 2.0), y: insets.top + floor((availableHeight - contentHeight) / 2.0) + floor((contentHeight - labelSize.height) / 2.0) + floor((contentHeight - iconSize.height - buttonSize.height) * 0.11)), size: labelSize)) transition.updateFrame(node: self.buttonNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - buttonSize.width) / 2.0), y: insets.top + floor((availableHeight - contentHeight) / 2.0) + contentHeight - buttonSize.height), size: buttonSize)) } @objc func buttonPressed() { self.action?() } } public final class ChangePhoneNumberIntroController: ViewController { private let context: AccountContext private var didPlayPresentationAnimation = false private var presentationData: PresentationData public init(context: AccountContext, phoneNumber: String) { self.context = context self.presentationData = context.sharedContext.currentPresentationData.with { $0 } super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData)) self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait) self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style let formattedPhone = formatPhoneNumber(phoneNumber) self.title = formattedPhone self.navigationItem.backBarButtonItem = UIBarButtonItem(title: presentationData.strings.Common_Back, style: .plain, target: nil, action: nil) //self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(self.cancelPressed)) } required init(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } public override func loadDisplayNode() { self.displayNode = ChangePhoneNumberIntroControllerNode(presentationData: self.presentationData) (self.displayNode as! ChangePhoneNumberIntroControllerNode).dismiss = { [weak self] in self?.presentingViewController?.dismiss(animated: false, completion: nil) } (self.displayNode as! ChangePhoneNumberIntroControllerNode).action = { [weak self] in self?.proceed() } self.displayNodeDidLoad() } public override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) /*if !self.didPlayPresentationAnimation { self.didPlayPresentationAnimation = true (self.displayNode as! ChangePhoneNumberIntroControllerNode).animateIn() }*/ } override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { super.containerLayoutUpdated(layout, transition: transition) (self.displayNode as! ChangePhoneNumberIntroControllerNode).containerLayoutUpdated(layout, navigationBarHeight: self.navigationLayout(layout: layout).navigationFrame.maxY, transition: transition) } @objc func cancelPressed() { (self.displayNode as! ChangePhoneNumberIntroControllerNode).animateOut() } func proceed() { self.present(textAlertController(context: self.context, title: nil, text: self.presentationData.strings.PhoneNumberHelp_Alert, actions: [TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: self.presentationData.strings.TwoFactorSetup_Email_Action, action: { [weak self] in if let strongSelf = self { (strongSelf.navigationController as? NavigationController)?.replaceTopController(ChangePhoneNumberController(context: strongSelf.context), animated: true) } })]), in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) } }