mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
182 lines
6.6 KiB
Swift
182 lines
6.6 KiB
Swift
import Foundation
|
||
import UIKit
|
||
import Display
|
||
import ComponentFlow
|
||
|
||
final class ZoomComponent: Component {
|
||
let availableValues: [Float]
|
||
let value: Float
|
||
let tag: AnyObject?
|
||
|
||
init(
|
||
availableValues: [Float],
|
||
value: Float,
|
||
tag: AnyObject?
|
||
) {
|
||
self.availableValues = availableValues
|
||
self.value = value
|
||
self.tag = tag
|
||
}
|
||
|
||
static func ==(lhs: ZoomComponent, rhs: ZoomComponent) -> Bool {
|
||
if lhs.availableValues != rhs.availableValues {
|
||
return false
|
||
}
|
||
if lhs.value != rhs.value {
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
|
||
final class View: UIView, UIGestureRecognizerDelegate, ComponentTaggedView {
|
||
final class ItemView: HighlightTrackingButton {
|
||
init() {
|
||
super.init(frame: .zero)
|
||
|
||
self.backgroundColor = UIColor(rgb: 0x000000, alpha: 0.3)
|
||
if #available(iOS 13.0, *) {
|
||
self.layer.cornerCurve = .circular
|
||
}
|
||
self.layer.cornerRadius = 18.5
|
||
}
|
||
|
||
required init(coder: NSCoder) {
|
||
preconditionFailure()
|
||
}
|
||
|
||
func update(value: String, selected: Bool) {
|
||
self.setAttributedTitle(NSAttributedString(string: value, font: Font.with(size: 13.0, design: .round, weight: .semibold), textColor: selected ? UIColor(rgb: 0xf8d74a) : .white, paragraphAlignment: .center), for: .normal)
|
||
}
|
||
}
|
||
|
||
private let backgroundView: BlurredBackgroundView
|
||
private var itemViews: [ItemView] = []
|
||
|
||
private var component: ZoomComponent?
|
||
public func matches(tag: Any) -> Bool {
|
||
if let component = self.component, let componentTag = component.tag {
|
||
let tag = tag as AnyObject
|
||
if componentTag === tag {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
init() {
|
||
self.backgroundView = BlurredBackgroundView(color: UIColor(rgb: 0x222222, alpha: 0.3))
|
||
self.backgroundView.clipsToBounds = true
|
||
self.backgroundView.layer.cornerRadius = 43.0 / 2.0
|
||
|
||
super.init(frame: CGRect())
|
||
|
||
self.layer.allowsGroupOpacity = true
|
||
|
||
self.addSubview(self.backgroundView)
|
||
|
||
let pressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.handlePress(_:)))
|
||
pressGestureRecognizer.minimumPressDuration = 0.01
|
||
pressGestureRecognizer.delegate = self
|
||
self.addGestureRecognizer(pressGestureRecognizer)
|
||
|
||
let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.handlePan(_:)))
|
||
panGestureRecognizer.delegate = self
|
||
self.addGestureRecognizer(panGestureRecognizer)
|
||
}
|
||
|
||
required init?(coder aDecoder: NSCoder) {
|
||
preconditionFailure()
|
||
}
|
||
|
||
@objc func handlePress(_ gestureRecognizer: UILongPressGestureRecognizer) {
|
||
|
||
}
|
||
|
||
@objc func handlePan(_ gestureRecognizer: UIPanGestureRecognizer) {
|
||
|
||
}
|
||
|
||
override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
|
||
return true
|
||
}
|
||
|
||
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
||
return true
|
||
}
|
||
|
||
func animateIn() {
|
||
self.backgroundView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||
}
|
||
|
||
func animateOut() {
|
||
self.backgroundView.alpha = 0.0
|
||
self.backgroundView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3)
|
||
}
|
||
|
||
func update(component: ZoomComponent, availableSize: CGSize, transition: Transition) -> CGSize {
|
||
self.component = component
|
||
|
||
let sideInset: CGFloat = 3.0
|
||
let spacing: CGFloat = 3.0
|
||
let buttonSize = CGSize(width: 37.0, height: 37.0)
|
||
let size: CGSize = CGSize(width: buttonSize.width * CGFloat(component.availableValues.count) + spacing * CGFloat(component.availableValues.count - 1) + sideInset * 2.0, height: 43.0)
|
||
|
||
if let screenTransition = transition.userData(CameraScreenTransition.self) {
|
||
switch screenTransition {
|
||
case .animateIn:
|
||
self.animateIn()
|
||
case .animateOut:
|
||
self.animateOut()
|
||
}
|
||
}
|
||
|
||
var i = 0
|
||
var itemFrame = CGRect(origin: CGPoint(x: sideInset, y: 3.0), size: buttonSize)
|
||
for value in component.availableValues {
|
||
let itemView: ItemView
|
||
if self.itemViews.count == i {
|
||
itemView = ItemView()
|
||
self.addSubview(itemView)
|
||
self.itemViews.append(itemView)
|
||
} else {
|
||
itemView = self.itemViews[i]
|
||
}
|
||
let text: String
|
||
if value > 0.5 {
|
||
if value == 1.0 {
|
||
text = "1×"
|
||
} else {
|
||
text = "\(Int(value))"
|
||
}
|
||
} else {
|
||
text = String(format: "%0.1f", value)
|
||
}
|
||
itemView.update(value: text, selected: value == 1.0)
|
||
itemView.bounds = CGRect(origin: .zero, size: itemFrame.size)
|
||
itemView.center = CGPoint(x: itemFrame.midX, y: itemFrame.midY)
|
||
if value == 1.0 {
|
||
itemView.transform = CGAffineTransformIdentity
|
||
} else {
|
||
itemView.transform = CGAffineTransform(scaleX: 0.7, y: 0.7)
|
||
}
|
||
|
||
i += 1
|
||
itemFrame = itemFrame.offsetBy(dx: buttonSize.width + spacing, dy: 0.0)
|
||
}
|
||
|
||
transition.setFrame(view: self.backgroundView, frame: CGRect(origin: .zero, size: size))
|
||
self.backgroundView.update(size: size, transition: transition.containedViewLayoutTransition)
|
||
|
||
return size
|
||
}
|
||
}
|
||
|
||
func makeView() -> View {
|
||
return View()
|
||
}
|
||
|
||
func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
|
||
return view.update(component: self, availableSize: availableSize, transition: transition)
|
||
}
|
||
}
|