import Foundation import UIKit import Display import ComponentFlow import SwiftSignalKit import TelegramCore import AccountContext import BundleIconComponent import MultilineTextComponent import ButtonComponent import LottieComponent final class PlaceholderComponent: Component { typealias EnvironmentType = Empty enum Mode { case request case denied } let context: AccountContext let mode: Mode let action: () -> Void init( context: AccountContext, mode: Mode, action: @escaping () -> Void ) { self.context = context self.mode = mode self.action = action } static func ==(lhs: PlaceholderComponent, rhs: PlaceholderComponent) -> Bool { if lhs.context !== rhs.context { return false } if lhs.mode != rhs.mode { return false } return true } public final class View: UIView { private let animation = ComponentView() private let title = ComponentView() private let text = ComponentView() private let button = ComponentView() private var component: PlaceholderComponent? private weak var state: EmptyComponentState? override init(frame: CGRect) { super.init(frame: frame) self.backgroundColor = UIColor(rgb: 0x1c1c1e) // if #available(iOS 13.0, *) { // self.layer.cornerCurve = .continuous // } } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func update(component: PlaceholderComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { self.component = component self.state = state let sideInset: CGFloat = 36.0 let animationHeight: CGFloat = 120.0 let title: String = "Allow Telegram to access your camera and microphone" let text: String = "This lets you share photos and record videos." let buttonTitle: String = "Open Settings" let animationSize = self.animation.update( transition: .immediate, component: AnyComponent(LottieComponent( content: LottieComponent.AppBundleContent(name: "Photos") )), environment: {}, containerSize: CGSize(width: animationHeight, height: animationHeight) ) let titleSize = self.title.update( transition: .immediate, component: AnyComponent( MultilineTextComponent( text: .plain(NSAttributedString(string: title, font: Font.semibold(17.0), textColor: UIColor.white)), horizontalAlignment: .center, maximumNumberOfLines: 0 ) ), environment: {}, containerSize: CGSize(width: availableSize.width - sideInset * 3.0, height: availableSize.height) ) let textSize = self.text.update( transition: .immediate, component: AnyComponent( MultilineTextComponent( text: .plain(NSAttributedString(string: text, font: Font.regular(15.0), textColor: UIColor(rgb: 0x98989f))), horizontalAlignment: .center, maximumNumberOfLines: 0 ) ), environment: {}, containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: availableSize.height) ) let buttonSize = self.button.update( transition: .immediate, component: AnyComponent( ButtonComponent( background: ButtonComponent.Background( color: UIColor(rgb: 0x007aff), foreground: .white, pressedColor: UIColor(rgb: 0x007aff, alpha: 0.55) ), content: AnyComponentWithIdentity( id: buttonTitle, component: AnyComponent(ButtonTextContentComponent( text: buttonTitle, badge: 0, textColor: .white, badgeBackground: .clear, badgeForeground: .clear )) ), isEnabled: true, displaysProgress: false, action: { [weak self] in if let self { self.component?.action() } } ) ), environment: {}, containerSize: CGSize(width: 240.0, height: 50.0) ) let titleSpacing: CGFloat = 12.0 let textSpacing: CGFloat = 14.0 let buttonSpacing: CGFloat = 18.0 let totalHeight = animationSize.height + titleSpacing + titleSize.height + textSpacing + textSize.height + buttonSpacing + buttonSize.height var originY = floorToScreenPixels((availableSize.height - totalHeight) / 2.0) let animationFrame = CGRect( origin: CGPoint( x: floorToScreenPixels((availableSize.width - animationSize.width) / 2.0), y: originY ), size: animationSize ) if let view = self.animation.view as? LottieComponent.View { if view.superview == nil { self.addSubview(view) Queue.mainQueue().justDispatch { view.playOnce() } } view.frame = animationFrame } originY += animationSize.height + titleSpacing let titleFrame = CGRect( origin: CGPoint( x: floorToScreenPixels((availableSize.width - titleSize.width) / 2.0), y: originY ), size: titleSize ) if let view = self.title.view { if view.superview == nil { self.addSubview(view) } view.frame = titleFrame } originY += titleSize.height + textSpacing let textFrame = CGRect( origin: CGPoint( x: floorToScreenPixels((availableSize.width - textSize.width) / 2.0), y: originY ), size: textSize ) if let view = self.text.view { if view.superview == nil { self.addSubview(view) } view.frame = textFrame } originY += textSize.height + buttonSpacing let buttonFrame = CGRect( origin: CGPoint( x: floorToScreenPixels((availableSize.width - buttonSize.width) / 2.0), y: originY ), size: buttonSize ) if let view = self.button.view { if view.superview == nil { self.addSubview(view) } view.frame = buttonFrame } return availableSize } } func makeView() -> View { return View() } public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition) } }