Files
Swiftgram/submodules/TelegramUI/Components/CameraScreen/Sources/PlaceholderComponent.swift

223 lines
8.2 KiB
Swift

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<Empty>()
private let title = ComponentView<Empty>()
private let text = ComponentView<Empty>()
private let button = ComponentView<Empty>()
private var component: PlaceholderComponent?
private weak var state: EmptyComponentState?
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor(rgb: 0x1c1c1e)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func update(component: PlaceholderComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
self.component = component
self.state = state
let sideInset: CGFloat = 36.0
let animationHeight: CGFloat = 120.0
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
let title = presentationData.strings.Story_Camera_AccessPlaceholderTitle
let text = presentationData.strings.Story_Camera_AccessPlaceholderText
let buttonTitle = presentationData.strings.Story_Camera_AccessOpenSettings
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<Empty>, transition: Transition) -> CGSize {
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
}
}