2024-02-13 20:13:40 +04:00

140 lines
5.5 KiB
Swift

import Foundation
import UIKit
import Display
import ComponentFlow
import ListSectionComponent
import MapKit
import TelegramPresentationData
import AppBundle
final class MapPreviewComponent: Component {
struct Location: Equatable {
var latitude: Double
var longitude: Double
init(latitude: Double, longitude: Double) {
self.latitude = latitude
self.longitude = longitude
}
}
let theme: PresentationTheme
let location: Location
let action: (() -> Void)?
init(
theme: PresentationTheme,
location: Location,
action: (() -> Void)? = nil
) {
self.theme = theme
self.location = location
self.action = action
}
static func ==(lhs: MapPreviewComponent, rhs: MapPreviewComponent) -> Bool {
if lhs.theme !== rhs.theme {
return false
}
if lhs.location != rhs.location {
return false
}
if (lhs.action == nil) != (rhs.action == nil) {
return false
}
return true
}
final class View: HighlightTrackingButton, ListSectionComponent.ChildView {
private var component: MapPreviewComponent?
private weak var componentState: EmptyComponentState?
private var mapView: MKMapView?
private let pinShadowView: UIImageView
private let pinView: UIImageView
private let pinForegroundView: UIImageView
var customUpdateIsHighlighted: ((Bool) -> Void)?
private(set) var separatorInset: CGFloat = 0.0
override init(frame: CGRect) {
self.pinShadowView = UIImageView()
self.pinView = UIImageView()
self.pinForegroundView = UIImageView()
super.init(frame: frame)
self.addSubview(self.pinShadowView)
self.addSubview(self.pinView)
self.addSubview(self.pinForegroundView)
self.pinShadowView.image = UIImage(bundleImageName: "Chat/Message/LocationPinShadow")
self.pinView.image = UIImage(bundleImageName: "Chat/Message/LocationPinBackground")?.withRenderingMode(.alwaysTemplate)
self.pinForegroundView.image = UIImage(bundleImageName: "Chat/Message/LocationPinForeground")?.withRenderingMode(.alwaysTemplate)
self.addTarget(self, action: #selector(self.pressed), for: .touchUpInside)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc private func pressed() {
self.component?.action?()
}
func update(component: MapPreviewComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
let previousComponent = self.component
self.component = component
self.componentState = state
self.isEnabled = component.action != nil
let size = CGSize(width: availableSize.width, height: 160.0)
let mapView: MKMapView
if let current = self.mapView {
mapView = current
} else {
mapView = MKMapView()
mapView.isUserInteractionEnabled = false
self.mapView = mapView
self.insertSubview(mapView, at: 0)
}
transition.setFrame(view: mapView, frame: CGRect(origin: CGPoint(), size: size))
let defaultMapSpan = MKCoordinateSpan(latitudeDelta: 0.016, longitudeDelta: 0.016)
let region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: component.location.latitude, longitude: component.location.longitude), span: defaultMapSpan)
if previousComponent?.location != component.location {
mapView.setRegion(region, animated: false)
mapView.setVisibleMapRect(mapView.visibleMapRect, edgePadding: UIEdgeInsets(top: 70.0, left: 0.0, bottom: 0.0, right: 0.0), animated: true)
}
let pinImageSize = self.pinView.image?.size ?? CGSize(width: 62.0, height: 74.0)
let pinFrame = CGRect(origin: CGPoint(x: floor((size.width - pinImageSize.width) * 0.5), y: floor((size.height - pinImageSize.height) * 0.5)), size: pinImageSize)
transition.setFrame(view: self.pinShadowView, frame: pinFrame)
transition.setFrame(view: self.pinView, frame: pinFrame)
self.pinView.tintColor = component.theme.list.itemCheckColors.fillColor
if let image = pinForegroundView.image {
let pinIconFrame = CGRect(origin: CGPoint(x: pinFrame.minX + floor((pinFrame.width - image.size.width) * 0.5), y: pinFrame.minY + 15.0), size: image.size)
transition.setFrame(view: self.pinForegroundView, frame: pinIconFrame)
self.pinForegroundView.tintColor = component.theme.list.itemCheckColors.foregroundColor
}
return size
}
}
func makeView() -> View {
return View(frame: CGRect())
}
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)
}
}