mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2026-02-08 12:24:39 +00:00
Story search
This commit is contained in:
@@ -26,10 +26,10 @@ private func generateSmallBackgroundImage(color: UIColor) -> UIImage? {
|
||||
})
|
||||
}
|
||||
|
||||
class LocationPinAnnotation: NSObject, MKAnnotation {
|
||||
public class LocationPinAnnotation: NSObject, MKAnnotation {
|
||||
let context: AccountContext
|
||||
let theme: PresentationTheme
|
||||
var coordinate: CLLocationCoordinate2D {
|
||||
public var coordinate: CLLocationCoordinate2D {
|
||||
willSet {
|
||||
self.willChangeValue(forKey: "coordinate")
|
||||
}
|
||||
@@ -55,10 +55,10 @@ class LocationPinAnnotation: NSObject, MKAnnotation {
|
||||
|
||||
var isSelf = false
|
||||
var selfPeer: EnginePeer?
|
||||
var title: String? = ""
|
||||
var subtitle: String? = ""
|
||||
public var title: String? = ""
|
||||
public var subtitle: String? = ""
|
||||
|
||||
init(context: AccountContext, theme: PresentationTheme, peer: EnginePeer?) {
|
||||
public init(context: AccountContext, theme: PresentationTheme, peer: EnginePeer?) {
|
||||
self.context = context
|
||||
self.theme = theme
|
||||
self.location = nil
|
||||
@@ -71,7 +71,7 @@ class LocationPinAnnotation: NSObject, MKAnnotation {
|
||||
super.init()
|
||||
}
|
||||
|
||||
init(context: AccountContext, theme: PresentationTheme, location: TelegramMediaMap, queryId: Int64?, resultId: String?, forcedSelection: Bool = false) {
|
||||
public init(context: AccountContext, theme: PresentationTheme, location: TelegramMediaMap, queryId: Int64?, resultId: String?, forcedSelection: Bool = false) {
|
||||
self.context = context
|
||||
self.theme = theme
|
||||
self.location = location
|
||||
@@ -84,7 +84,7 @@ class LocationPinAnnotation: NSObject, MKAnnotation {
|
||||
super.init()
|
||||
}
|
||||
|
||||
init(context: AccountContext, theme: PresentationTheme, message: EngineMessage, selfPeer: EnginePeer?, isSelf: Bool, heading: Int32?) {
|
||||
public init(context: AccountContext, theme: PresentationTheme, message: EngineMessage, selfPeer: EnginePeer?, isSelf: Bool, heading: Int32?) {
|
||||
self.context = context
|
||||
self.theme = theme
|
||||
self.location = nil
|
||||
@@ -104,7 +104,7 @@ class LocationPinAnnotation: NSObject, MKAnnotation {
|
||||
super.init()
|
||||
}
|
||||
|
||||
var id: String {
|
||||
public var id: String {
|
||||
if let message = self.message {
|
||||
return "\(message.id.id)"
|
||||
} else if let peer = self.peer {
|
||||
@@ -157,7 +157,7 @@ private func removePulseAnimations(layer: CALayer) {
|
||||
layer.removeAnimation(forKey: "pulse-opacity")
|
||||
}
|
||||
|
||||
class LocationPinAnnotationView: MKAnnotationView {
|
||||
public class LocationPinAnnotationView: MKAnnotationView {
|
||||
let shadowNode: ASImageNode
|
||||
let pulseNode: ASImageNode
|
||||
let backgroundNode: ASImageNode
|
||||
@@ -178,17 +178,17 @@ class LocationPinAnnotationView: MKAnnotationView {
|
||||
|
||||
var headingKvoToken: NSKeyValueObservation?
|
||||
|
||||
override class var layerClass: AnyClass {
|
||||
override public class var layerClass: AnyClass {
|
||||
return LocationPinAnnotationLayer.self
|
||||
}
|
||||
|
||||
func setZPosition(_ zPosition: CGFloat?) {
|
||||
public func setZPosition(_ zPosition: CGFloat?) {
|
||||
if let layer = self.layer as? LocationPinAnnotationLayer {
|
||||
layer.customZPosition = zPosition
|
||||
}
|
||||
}
|
||||
|
||||
init(annotation: LocationPinAnnotation) {
|
||||
public init(annotation: LocationPinAnnotation) {
|
||||
self.shadowNode = ASImageNode()
|
||||
self.shadowNode.image = UIImage(bundleImageName: "Location/PinShadow")
|
||||
if let image = self.shadowNode.image {
|
||||
@@ -244,7 +244,7 @@ class LocationPinAnnotationView: MKAnnotationView {
|
||||
self.annotation = annotation
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
required public init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
@@ -252,7 +252,7 @@ class LocationPinAnnotationView: MKAnnotationView {
|
||||
self.headingKvoToken?.invalidate()
|
||||
}
|
||||
|
||||
var defaultZPosition: CGFloat {
|
||||
public var defaultZPosition: CGFloat {
|
||||
if let annotation = self.annotation as? LocationPinAnnotation {
|
||||
if annotation.forcedSelection {
|
||||
return 0.0
|
||||
@@ -266,7 +266,7 @@ class LocationPinAnnotationView: MKAnnotationView {
|
||||
}
|
||||
}
|
||||
|
||||
override var annotation: MKAnnotation? {
|
||||
override public var annotation: MKAnnotation? {
|
||||
didSet {
|
||||
if let annotation = self.annotation as? LocationPinAnnotation {
|
||||
if let message = annotation.message {
|
||||
@@ -363,14 +363,14 @@ class LocationPinAnnotationView: MKAnnotationView {
|
||||
}
|
||||
}
|
||||
|
||||
override func prepareForReuse() {
|
||||
override public func prepareForReuse() {
|
||||
self.previousPeerId = nil
|
||||
self.smallNode.isHidden = true
|
||||
self.backgroundNode.isHidden = false
|
||||
self.appeared = false
|
||||
}
|
||||
|
||||
override func setSelected(_ selected: Bool, animated: Bool) {
|
||||
override public func setSelected(_ selected: Bool, animated: Bool) {
|
||||
super.setSelected(selected, animated: animated)
|
||||
|
||||
if let annotation = self.annotation as? LocationPinAnnotation {
|
||||
@@ -547,7 +547,7 @@ class LocationPinAnnotationView: MKAnnotationView {
|
||||
}
|
||||
|
||||
var previousPeerId: EnginePeer.Id?
|
||||
func setPeer(context: AccountContext, theme: PresentationTheme, peer: EnginePeer) {
|
||||
public func setPeer(context: AccountContext, theme: PresentationTheme, peer: EnginePeer) {
|
||||
let avatarNode: AvatarNode
|
||||
if let currentAvatarNode = self.avatarNode {
|
||||
avatarNode = currentAvatarNode
|
||||
@@ -566,7 +566,7 @@ class LocationPinAnnotationView: MKAnnotationView {
|
||||
}
|
||||
}
|
||||
|
||||
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
|
||||
override public func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
|
||||
super.traitCollectionDidChange(previousTraitCollection)
|
||||
|
||||
if let labelNode = self.labelNode {
|
||||
@@ -589,7 +589,7 @@ class LocationPinAnnotationView: MKAnnotationView {
|
||||
}
|
||||
|
||||
var isRaised = false
|
||||
func setRaised(_ raised: Bool, animated: Bool, completion: @escaping () -> Void = {}) {
|
||||
public func setRaised(_ raised: Bool, animated: Bool, completion: @escaping () -> Void = {}) {
|
||||
guard raised != self.isRaised else {
|
||||
return
|
||||
}
|
||||
@@ -625,7 +625,7 @@ class LocationPinAnnotationView: MKAnnotationView {
|
||||
}
|
||||
}
|
||||
|
||||
func setCustom(_ custom: Bool, animated: Bool) {
|
||||
public func setCustom(_ custom: Bool, animated: Bool) {
|
||||
if let annotation = self.annotation as? LocationPinAnnotation {
|
||||
self.iconNode.setSignal(venueIcon(engine: annotation.context.engine, type: "", background: false))
|
||||
}
|
||||
@@ -676,7 +676,7 @@ class LocationPinAnnotationView: MKAnnotationView {
|
||||
self.dotNode.isHidden = !custom
|
||||
}
|
||||
|
||||
func animateAppearance() {
|
||||
public func animateAppearance() {
|
||||
guard let annotation = self.annotation as? LocationPinAnnotation, annotation.location != nil && !annotation.forcedSelection else {
|
||||
return
|
||||
}
|
||||
@@ -694,7 +694,7 @@ class LocationPinAnnotationView: MKAnnotationView {
|
||||
}
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
override public func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
guard !self.animating else {
|
||||
|
||||
@@ -11,7 +11,7 @@ import AppBundle
|
||||
import SolidRoundedButtonNode
|
||||
import ShimmerEffect
|
||||
|
||||
final class LocationInfoListItem: ListViewItem {
|
||||
public final class LocationInfoListItem: ListViewItem {
|
||||
let presentationData: ItemListPresentationData
|
||||
let engine: TelegramEngine
|
||||
let location: TelegramMediaMap
|
||||
@@ -75,7 +75,7 @@ final class LocationInfoListItem: ListViewItem {
|
||||
}
|
||||
}
|
||||
|
||||
final class LocationInfoListItemNode: ListViewItemNode {
|
||||
public final class LocationInfoListItemNode: ListViewItemNode {
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private var titleNode: TextNode?
|
||||
private var subtitleNode: TextNode?
|
||||
@@ -91,7 +91,7 @@ final class LocationInfoListItemNode: ListViewItemNode {
|
||||
private var layoutParams: ListViewItemLayoutParams?
|
||||
private var absoluteLocation: (CGRect, CGSize)?
|
||||
|
||||
required init() {
|
||||
required public init() {
|
||||
self.backgroundNode = ASDisplayNode()
|
||||
self.backgroundNode.isLayerBacked = true
|
||||
self.buttonNode = HighlightableButtonNode()
|
||||
@@ -127,7 +127,7 @@ final class LocationInfoListItemNode: ListViewItemNode {
|
||||
self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside)
|
||||
}
|
||||
|
||||
override func layoutForParams(_ params: ListViewItemLayoutParams, item: ListViewItem, previousItem: ListViewItem?, nextItem: ListViewItem?) {
|
||||
override public func layoutForParams(_ params: ListViewItemLayoutParams, item: ListViewItem, previousItem: ListViewItem?, nextItem: ListViewItem?) {
|
||||
if let item = self.item {
|
||||
let makeLayout = self.asyncLayout()
|
||||
let (nodeLayout, nodeApply) = makeLayout(item, params)
|
||||
@@ -137,7 +137,7 @@ final class LocationInfoListItemNode: ListViewItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
func asyncLayout() -> (_ item: LocationInfoListItem, _ params: ListViewItemLayoutParams) -> (ListViewItemNodeLayout, () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void)) {
|
||||
public func asyncLayout() -> (_ item: LocationInfoListItem, _ params: ListViewItemLayoutParams) -> (ListViewItemNodeLayout, () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void)) {
|
||||
let currentItem = self.item
|
||||
|
||||
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
||||
@@ -205,6 +205,8 @@ final class LocationInfoListItemNode: ListViewItemNode {
|
||||
strongSelf.backgroundNode.backgroundColor = item.presentationData.theme.list.plainBackgroundColor
|
||||
}
|
||||
|
||||
strongSelf.backgroundNode.isHidden = params.isStandalone
|
||||
|
||||
let arguments = VenueIconArguments(defaultBackgroundColor: item.presentationData.theme.chat.inputPanel.actionControlFillColor, defaultForegroundColor: item.presentationData.theme.chat.inputPanel.actionControlForegroundColor)
|
||||
if let updatedLocation = updatedLocation {
|
||||
strongSelf.venueIconNode.setSignal(venueIcon(engine: item.engine, type: updatedLocation.venue?.type ?? "", background: true))
|
||||
@@ -384,11 +386,11 @@ final class LocationInfoListItemNode: ListViewItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
override func animateInsertion(_ currentTimestamp: Double, duration: Double, options: ListViewItemAnimationOptions) {
|
||||
override public func animateInsertion(_ currentTimestamp: Double, duration: Double, options: ListViewItemAnimationOptions) {
|
||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration * 0.5)
|
||||
}
|
||||
|
||||
override func animateRemoved(_ currentTimestamp: Double, duration: Double) {
|
||||
override public func animateRemoved(_ currentTimestamp: Double, duration: Double) {
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration * 0.5, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ private func generateShadowImage(theme: PresentationTheme, highlighted: Bool) ->
|
||||
})?.stretchableImage(withLeftCapWidth: 13, topCapHeight: 0)
|
||||
}
|
||||
|
||||
final class LocationMapHeaderNode: ASDisplayNode {
|
||||
public final class LocationMapHeaderNode: ASDisplayNode {
|
||||
private var presentationData: PresentationData
|
||||
private let toggleMapModeSelection: () -> Void
|
||||
private let goToUserLocation: () -> Void
|
||||
@@ -44,8 +44,8 @@ final class LocationMapHeaderNode: ASDisplayNode {
|
||||
private var displayingPlacesButton = false
|
||||
private var proximityNotification: Bool?
|
||||
|
||||
let mapNode: LocationMapNode
|
||||
var trackingMode: LocationTrackingMode = .none
|
||||
public let mapNode: LocationMapNode
|
||||
public var trackingMode: LocationTrackingMode = .none
|
||||
|
||||
private let optionsBackgroundNode: ASImageNode
|
||||
private let optionsSeparatorNode: ASDisplayNode
|
||||
@@ -59,7 +59,7 @@ final class LocationMapHeaderNode: ASDisplayNode {
|
||||
|
||||
private var validLayout: (ContainerViewLayout, CGFloat, CGFloat, CGFloat, CGSize)?
|
||||
|
||||
init(presentationData: PresentationData, toggleMapModeSelection: @escaping () -> Void, goToUserLocation: @escaping () -> Void, setupProximityNotification: @escaping (Bool) -> Void = { _ in }, showPlacesInThisArea: @escaping () -> Void = {}) {
|
||||
public init(presentationData: PresentationData, toggleMapModeSelection: @escaping () -> Void, goToUserLocation: @escaping () -> Void, setupProximityNotification: @escaping (Bool) -> Void = { _ in }, showPlacesInThisArea: @escaping () -> Void = {}) {
|
||||
self.presentationData = presentationData
|
||||
self.toggleMapModeSelection = toggleMapModeSelection
|
||||
self.goToUserLocation = goToUserLocation
|
||||
@@ -131,7 +131,7 @@ final class LocationMapHeaderNode: ASDisplayNode {
|
||||
self.placesButtonNode.addTarget(self, action: #selector(self.placesPressed), forControlEvents: .touchUpInside)
|
||||
}
|
||||
|
||||
func updateState(mapMode: LocationMapMode, trackingMode: LocationTrackingMode, displayingMapModeOptions: Bool, displayingPlacesButton: Bool, proximityNotification: Bool?, animated: Bool) {
|
||||
public func updateState(mapMode: LocationMapMode, trackingMode: LocationTrackingMode, displayingMapModeOptions: Bool, displayingPlacesButton: Bool, proximityNotification: Bool?, animated: Bool) {
|
||||
self.mapNode.mapMode = mapMode
|
||||
self.trackingMode = trackingMode
|
||||
self.infoButtonNode.isSelected = displayingMapModeOptions
|
||||
@@ -149,7 +149,7 @@ final class LocationMapHeaderNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
func updatePresentationData(_ presentationData: PresentationData) {
|
||||
public func updatePresentationData(_ presentationData: PresentationData) {
|
||||
self.presentationData = presentationData
|
||||
|
||||
self.optionsBackgroundNode.image = generateBackgroundImage(theme: presentationData.theme)
|
||||
@@ -177,13 +177,13 @@ final class LocationMapHeaderNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
func updateLayout(layout: ContainerViewLayout, navigationBarHeight: CGFloat, topPadding: CGFloat, offset: CGFloat, size: CGSize, transition: ContainedViewLayoutTransition) {
|
||||
public func updateLayout(layout: ContainerViewLayout, navigationBarHeight: CGFloat, topPadding: CGFloat, offset: CGFloat, size: CGSize, transition: ContainedViewLayoutTransition) {
|
||||
self.validLayout = (layout, navigationBarHeight, topPadding, offset, size)
|
||||
|
||||
let mapHeight: CGFloat = floor(layout.size.height * 1.3)
|
||||
let mapFrame = CGRect(x: 0.0, y: floorToScreenPixels((size.height - mapHeight + navigationBarHeight) / 2.0) + offset, width: size.width, height: mapHeight)
|
||||
transition.updateFrame(node: self.mapNode, frame: mapFrame)
|
||||
self.mapNode.updateLayout(size: mapFrame.size)
|
||||
self.mapNode.updateLayout(size: mapFrame.size, topPadding: layout.intrinsicInsets.top)
|
||||
|
||||
let inset: CGFloat = 6.0
|
||||
|
||||
@@ -191,6 +191,8 @@ final class LocationMapHeaderNode: ASDisplayNode {
|
||||
let placesButtonFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - placesButtonSize.width) / 2.0), y: self.displayingPlacesButton ? navigationBarHeight + topPadding + inset : 0.0), size: placesButtonSize)
|
||||
transition.updateFrame(node: self.placesBackgroundNode, frame: placesButtonFrame)
|
||||
transition.updateFrame(node: self.placesButtonNode, frame: CGRect(origin: CGPoint(), size: placesButtonSize))
|
||||
transition.updateAlpha(node: self.placesBackgroundNode, alpha: self.displayingPlacesButton ? 1.0 : 0.0)
|
||||
transition.updateAlpha(node: self.placesButtonNode, alpha: self.displayingPlacesButton ? 1.0 : 0.0)
|
||||
|
||||
transition.updateFrame(node: self.shadowNode, frame: CGRect(x: 0.0, y: size.height - 14.0, width: size.width, height: 14.0))
|
||||
|
||||
@@ -214,7 +216,7 @@ final class LocationMapHeaderNode: ASDisplayNode {
|
||||
alphaTransition.updateAlpha(node: self.optionsBackgroundNode, alpha: optionsAlpha)
|
||||
}
|
||||
|
||||
var forceIsHidden: Bool = false {
|
||||
public var forceIsHidden: Bool = false {
|
||||
didSet {
|
||||
if let (layout, navigationBarHeight, topPadding, offset, size) = self.validLayout {
|
||||
self.updateLayout(layout: layout, navigationBarHeight: navigationBarHeight, topPadding: topPadding, offset: offset, size: size, transition: .immediate)
|
||||
@@ -222,11 +224,11 @@ final class LocationMapHeaderNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
func updateHighlight(_ highlighted: Bool) {
|
||||
public func updateHighlight(_ highlighted: Bool) {
|
||||
self.shadowNode.image = generateShadowImage(theme: self.presentationData.theme, highlighted: highlighted)
|
||||
}
|
||||
|
||||
func proximityButtonFrame() -> CGRect? {
|
||||
public func proximityButtonFrame() -> CGRect? {
|
||||
if self.notificationButtonNode.alpha > 0.0 {
|
||||
return self.optionsBackgroundNode.view.convert(self.notificationButtonNode.frame, to: self.view)
|
||||
} else {
|
||||
|
||||
@@ -5,8 +5,6 @@ import Display
|
||||
import SwiftSignalKit
|
||||
import MapKit
|
||||
|
||||
let defaultMapSpan = MKCoordinateSpan(latitudeDelta: 0.016, longitudeDelta: 0.016)
|
||||
let viewMapSpan = MKCoordinateSpan(latitudeDelta: 0.008, longitudeDelta: 0.008)
|
||||
private let pinOffset = CGPoint(x: 0.0, y: 33.0)
|
||||
|
||||
public enum LocationMapMode {
|
||||
@@ -128,7 +126,10 @@ private func generateProximityDim(size: CGSize) -> UIImage {
|
||||
})!
|
||||
}
|
||||
|
||||
final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
public final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
public static let defaultMapSpan = MKCoordinateSpan(latitudeDelta: 0.016, longitudeDelta: 0.016)
|
||||
public static let viewMapSpan = MKCoordinateSpan(latitudeDelta: 0.008, longitudeDelta: 0.008)
|
||||
|
||||
class ProximityCircleRenderer: MKCircleRenderer {
|
||||
override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) {
|
||||
super.draw(mapRect, zoomScale: zoomScale, in: context)
|
||||
@@ -204,7 +205,7 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
|
||||
private var circleOverlay: MKCircle?
|
||||
var activeProximityRadius: Double? {
|
||||
public var activeProximityRadius: Double? {
|
||||
didSet {
|
||||
if let activeProximityRadius = self.activeProximityRadius {
|
||||
if let circleOverlay = self.circleOverlay {
|
||||
@@ -225,7 +226,7 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
override init() {
|
||||
override public init() {
|
||||
self.pickerAnnotationContainerView = PickerAnnotationContainerView()
|
||||
self.pickerAnnotationContainerView.isHidden = true
|
||||
|
||||
@@ -236,7 +237,7 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
})
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
override public func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
self.headingArrowView = UIImageView()
|
||||
@@ -292,7 +293,7 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
var trackingMode: LocationTrackingMode = .none {
|
||||
public var trackingMode: LocationTrackingMode = .none {
|
||||
didSet {
|
||||
self.mapView?.userTrackingMode = self.trackingMode.userTrackingMode
|
||||
if self.trackingMode == .followWithHeading && self.headingArrowView?.image != nil {
|
||||
@@ -303,11 +304,18 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
var topPadding: CGFloat = 0.0
|
||||
var mapOffset: CGFloat = 0.0
|
||||
func setMapCenter(coordinate: CLLocationCoordinate2D, radius: Double, insets: UIEdgeInsets, offset: CGFloat, animated: Bool = false) {
|
||||
var hasValidLayout: Bool = false
|
||||
var pendingSetMapCenter: (coordinate: CLLocationCoordinate2D, span: MKCoordinateSpan, offset: CGPoint, isUserLocation: Bool, hidePicker: Bool, animated: Bool)?
|
||||
|
||||
public func setMapCenter(coordinate: CLLocationCoordinate2D, radius: Double, insets: UIEdgeInsets, offset: CGFloat, animated: Bool = false) {
|
||||
self.mapOffset = offset
|
||||
self.ignoreRegionChanges = true
|
||||
|
||||
var insets = insets
|
||||
insets.top += self.topPadding
|
||||
|
||||
let mapRect = MKMapRect(region: MKCoordinateRegion(center: coordinate, latitudinalMeters: radius * 2.0, longitudinalMeters: radius * 2.0))
|
||||
self.mapView?.setVisibleMapRect(mapRect, edgePadding: insets, animated: animated)
|
||||
self.ignoreRegionChanges = false
|
||||
@@ -315,16 +323,34 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
self.proximityDimView.center = CGPoint(x: self.bounds.midX, y: self.bounds.midY + offset)
|
||||
}
|
||||
|
||||
func setMapCenter(coordinate: CLLocationCoordinate2D, span: MKCoordinateSpan = defaultMapSpan, offset: CGPoint = CGPoint(), isUserLocation: Bool = false, hidePicker: Bool = false, animated: Bool = false) {
|
||||
public func setMapCenter(coordinate: CLLocationCoordinate2D, span: MKCoordinateSpan = defaultMapSpan, offset: CGPoint = CGPoint(), isUserLocation: Bool = false, hidePicker: Bool = false, animated: Bool = false) {
|
||||
self.pendingSetMapCenter = (
|
||||
coordinate, span, offset, isUserLocation, hidePicker, animated
|
||||
)
|
||||
|
||||
if self.hasValidLayout {
|
||||
self.applyPendingSetMapCenter()
|
||||
}
|
||||
}
|
||||
|
||||
private func applyPendingSetMapCenter() {
|
||||
if !self.hasValidLayout {
|
||||
return
|
||||
}
|
||||
guard let (coordinate, span, offset, isUserLocation, hidePicker, animated) = self.pendingSetMapCenter else {
|
||||
return
|
||||
}
|
||||
self.pendingSetMapCenter = nil
|
||||
|
||||
let region = MKCoordinateRegion(center: coordinate, span: span)
|
||||
self.ignoreRegionChanges = true
|
||||
if offset == CGPoint() {
|
||||
if offset == CGPoint() && self.topPadding == 0.0 {
|
||||
self.mapView?.setRegion(region, animated: animated)
|
||||
} else {
|
||||
let mapRect = MKMapRect(region: region)
|
||||
self.mapView?.setVisibleMapRect(mapRect, edgePadding: UIEdgeInsets(top: offset.y, left: offset.x, bottom: 0.0, right: 0.0), animated: animated)
|
||||
self.mapView?.setVisibleMapRect(mapRect, edgePadding: UIEdgeInsets(top: offset.y + self.topPadding, left: offset.x, bottom: 0.0, right: 0.0), animated: animated)
|
||||
}
|
||||
self.ignoreRegionChanges = false
|
||||
self.ignoreRegionChanges = false
|
||||
|
||||
if isUserLocation {
|
||||
if !self.returnedToUserLocation {
|
||||
@@ -339,7 +365,7 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
|
||||
public func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
|
||||
guard !self.ignoreRegionChanges, let scrollView = mapView.subviews.first, let gestureRecognizers = scrollView.gestureRecognizers else {
|
||||
return
|
||||
}
|
||||
@@ -356,7 +382,7 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
|
||||
public func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
|
||||
let wasDragging = self.isDragging
|
||||
if self.isDragging {
|
||||
self.isDragging = false
|
||||
@@ -372,7 +398,7 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
|
||||
public func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
|
||||
guard let location = userLocation.location else {
|
||||
return
|
||||
}
|
||||
@@ -380,11 +406,11 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
self.locationPromise.set(.single(location))
|
||||
}
|
||||
|
||||
func mapView(_ mapView: MKMapView, didFailToLocateUserWithError error: Error) {
|
||||
public func mapView(_ mapView: MKMapView, didFailToLocateUserWithError error: Error) {
|
||||
self.locationPromise.set(.single(nil))
|
||||
}
|
||||
|
||||
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
|
||||
public func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
|
||||
if annotation === mapView.userLocation {
|
||||
return nil
|
||||
}
|
||||
@@ -400,7 +426,7 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
return nil
|
||||
}
|
||||
|
||||
func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
|
||||
public func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
|
||||
for view in views {
|
||||
if view.annotation is MKUserLocation {
|
||||
self.defaultUserLocationAnnotation = view.annotation
|
||||
@@ -424,7 +450,7 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
|
||||
public func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
|
||||
guard let annotation = view.annotation as? LocationPinAnnotation else {
|
||||
return
|
||||
}
|
||||
@@ -440,7 +466,7 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
|
||||
public func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
|
||||
if let view = view as? LocationPinAnnotationView {
|
||||
Queue.mainQueue().after(0.2) {
|
||||
view.setZPosition(view.defaultZPosition)
|
||||
@@ -459,7 +485,7 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
|
||||
public func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
|
||||
if let circle = overlay as? MKCircle {
|
||||
let renderer = ProximityCircleRenderer(circle: circle)
|
||||
renderer.fillColor = .clear
|
||||
@@ -472,7 +498,7 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
var distancesToAllAnnotations: Signal<[Double], NoError> {
|
||||
public var distancesToAllAnnotations: Signal<[Double], NoError> {
|
||||
let poll = Signal<[LocationPinAnnotation], NoError> { [weak self] subscriber in
|
||||
if let strongSelf = self {
|
||||
subscriber.putNext(strongSelf.annotations)
|
||||
@@ -497,30 +523,30 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
var currentUserLocation: CLLocation? {
|
||||
public var currentUserLocation: CLLocation? {
|
||||
return self.mapView?.userLocation.location
|
||||
}
|
||||
|
||||
var userLocation: Signal<CLLocation?, NoError> {
|
||||
public var userLocation: Signal<CLLocation?, NoError> {
|
||||
return .single(self.currentUserLocation)
|
||||
|> then (self.locationPromise.get())
|
||||
}
|
||||
|
||||
var mapCenterCoordinate: CLLocationCoordinate2D? {
|
||||
public var mapCenterCoordinate: CLLocationCoordinate2D? {
|
||||
guard let mapView = self.mapView else {
|
||||
return nil
|
||||
}
|
||||
return mapView.convert(CGPoint(x: (mapView.frame.width + pinOffset.x) / 2.0, y: (mapView.frame.height + pinOffset.y) / 2.0), toCoordinateFrom: mapView)
|
||||
}
|
||||
|
||||
var mapSpan: MKCoordinateSpan? {
|
||||
public var mapSpan: MKCoordinateSpan? {
|
||||
guard let mapView = self.mapView else {
|
||||
return nil
|
||||
}
|
||||
return mapView.region.span
|
||||
}
|
||||
|
||||
func resetAnnotationSelection() {
|
||||
public func resetAnnotationSelection() {
|
||||
guard let mapView = self.mapView else {
|
||||
return
|
||||
}
|
||||
@@ -529,8 +555,8 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
var pickerAnnotationView: LocationPinAnnotationView? = nil
|
||||
var hasPickerAnnotation: Bool = false {
|
||||
public var pickerAnnotationView: LocationPinAnnotationView? = nil
|
||||
public var hasPickerAnnotation: Bool = false {
|
||||
didSet {
|
||||
if self.hasPickerAnnotation, let annotation = self.userLocationAnnotation {
|
||||
let pickerAnnotationView = LocationPinAnnotationView(annotation: annotation)
|
||||
@@ -544,7 +570,7 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func switchToPicking(raise: Bool = false, animated: Bool) {
|
||||
public func switchToPicking(raise: Bool = false, animated: Bool) {
|
||||
guard self.hasPickerAnnotation else {
|
||||
return
|
||||
}
|
||||
@@ -561,8 +587,8 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
self.resetScheduledPin()
|
||||
}
|
||||
|
||||
var customUserLocationAnnotationView: LocationPinAnnotationView? = nil
|
||||
var userLocationAnnotation: LocationPinAnnotation? = nil {
|
||||
public var customUserLocationAnnotationView: LocationPinAnnotationView? = nil
|
||||
public var userLocationAnnotation: LocationPinAnnotation? = nil {
|
||||
didSet {
|
||||
if let annotation = self.userLocationAnnotation {
|
||||
self.customUserLocationAnnotationView?.removeFromSuperview()
|
||||
@@ -582,7 +608,7 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
var userHeading: CGFloat? = nil {
|
||||
public var userHeading: CGFloat? = nil {
|
||||
didSet {
|
||||
if let heading = self.userHeading {
|
||||
self.headingArrowView?.isHidden = false
|
||||
@@ -594,7 +620,7 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
var annotations: [LocationPinAnnotation] = [] {
|
||||
public var annotations: [LocationPinAnnotation] = [] {
|
||||
didSet {
|
||||
guard let mapView = self.mapView else {
|
||||
return
|
||||
@@ -709,7 +735,7 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
self.pinDisposable.set(nil)
|
||||
}
|
||||
|
||||
func showAll(animated: Bool = true) {
|
||||
public func showAll(animated: Bool = true) {
|
||||
guard let mapView = self.mapView else {
|
||||
return
|
||||
}
|
||||
@@ -736,11 +762,17 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func updateLayout(size: CGSize) {
|
||||
self.proximityDimView.frame = CGRect(origin: CGPoint(x: 0.0, y: self.mapOffset), size: size)
|
||||
public func updateLayout(size: CGSize, topPadding: CGFloat) {
|
||||
self.hasValidLayout = true
|
||||
|
||||
self.topPadding = topPadding
|
||||
|
||||
self.proximityDimView.frame = CGRect(origin: CGPoint(x: 0.0, y: self.topPadding + self.mapOffset), size: size)
|
||||
self.pickerAnnotationContainerView.frame = CGRect(x: 0.0, y: floorToScreenPixels((size.height - size.width) / 2.0), width: size.width, height: size.width)
|
||||
if let pickerAnnotationView = self.pickerAnnotationView {
|
||||
pickerAnnotationView.center = CGPoint(x: self.pickerAnnotationContainerView.frame.width / 2.0, y: self.pickerAnnotationContainerView.frame.height / 2.0)
|
||||
}
|
||||
|
||||
self.applyPendingSetMapCenter()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,14 +6,14 @@ import TelegramCore
|
||||
import TelegramPresentationData
|
||||
import SegmentedControlNode
|
||||
|
||||
final class LocationOptionsNode: ASDisplayNode {
|
||||
public final class LocationOptionsNode: ASDisplayNode {
|
||||
private var presentationData: PresentationData
|
||||
|
||||
private let backgroundNode: NavigationBackgroundNode
|
||||
private let separatorNode: ASDisplayNode
|
||||
private let segmentedControlNode: SegmentedControlNode
|
||||
|
||||
init(presentationData: PresentationData, updateMapMode: @escaping (LocationMapMode) -> Void) {
|
||||
public init(presentationData: PresentationData, hasBackground: Bool = true, updateMapMode: @escaping (LocationMapMode) -> Void) {
|
||||
self.presentationData = presentationData
|
||||
|
||||
self.backgroundNode = NavigationBackgroundNode(color: self.presentationData.theme.rootController.navigationBar.blurredBackgroundColor)
|
||||
@@ -24,8 +24,11 @@ final class LocationOptionsNode: ASDisplayNode {
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.backgroundNode)
|
||||
self.addSubnode(self.separatorNode)
|
||||
if hasBackground {
|
||||
self.addSubnode(self.backgroundNode)
|
||||
self.addSubnode(self.separatorNode)
|
||||
}
|
||||
|
||||
self.addSubnode(self.segmentedControlNode)
|
||||
|
||||
self.segmentedControlNode.selectedIndexChanged = { index in
|
||||
@@ -42,14 +45,14 @@ final class LocationOptionsNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
func updatePresentationData(_ presentationData: PresentationData) {
|
||||
public func updatePresentationData(_ presentationData: PresentationData) {
|
||||
self.presentationData = presentationData
|
||||
self.backgroundNode.updateColor(color: self.presentationData.theme.rootController.navigationBar.blurredBackgroundColor, transition: .immediate)
|
||||
self.separatorNode.backgroundColor = self.presentationData.theme.rootController.navigationBar.separatorColor
|
||||
self.segmentedControlNode.updateTheme(SegmentedControlTheme(theme: self.presentationData.theme))
|
||||
}
|
||||
|
||||
func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
public func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: size))
|
||||
self.backgroundNode.update(size: size, transition: transition)
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ func stringForEstimatedDuration(strings: PresentationStrings, time: Double, form
|
||||
}
|
||||
}
|
||||
|
||||
func throttledUserLocation(_ userLocation: Signal<CLLocation?, NoError>) -> Signal<CLLocation?, NoError> {
|
||||
public func throttledUserLocation(_ userLocation: Signal<CLLocation?, NoError>) -> Signal<CLLocation?, NoError> {
|
||||
return userLocation
|
||||
|> reduceLeft(value: nil) { current, updated, emit -> CLLocation? in
|
||||
if let current = current {
|
||||
@@ -126,13 +126,13 @@ func throttledUserLocation(_ userLocation: Signal<CLLocation?, NoError>) -> Sign
|
||||
}
|
||||
}
|
||||
|
||||
enum ExpectedTravelTime: Equatable {
|
||||
public enum ExpectedTravelTime: Equatable {
|
||||
case unknown
|
||||
case calculating
|
||||
case ready(Double)
|
||||
}
|
||||
|
||||
func getExpectedTravelTime(coordinate: CLLocationCoordinate2D, transportType: MKDirectionsTransportType) -> Signal<ExpectedTravelTime, NoError> {
|
||||
public func getExpectedTravelTime(coordinate: CLLocationCoordinate2D, transportType: MKDirectionsTransportType) -> Signal<ExpectedTravelTime, NoError> {
|
||||
return Signal { subscriber in
|
||||
subscriber.putNext(.calculating)
|
||||
|
||||
|
||||
@@ -41,159 +41,159 @@ private struct LocationViewTransaction {
|
||||
let animated: Bool
|
||||
}
|
||||
|
||||
private enum LocationViewEntryId: Hashable {
|
||||
public enum LocationViewEntryId: Hashable {
|
||||
case info
|
||||
case toggleLiveLocation(Bool)
|
||||
case liveLocation(UInt32)
|
||||
}
|
||||
|
||||
private enum LocationViewEntry: Comparable, Identifiable {
|
||||
public enum LocationViewEntry: Comparable, Identifiable {
|
||||
case info(PresentationTheme, TelegramMediaMap, String?, Double?, ExpectedTravelTime, ExpectedTravelTime, ExpectedTravelTime, Bool)
|
||||
case toggleLiveLocation(PresentationTheme, String, String, Double?, Double?, Bool, EngineMessage.Id?)
|
||||
case liveLocation(PresentationTheme, PresentationDateTimeFormat, PresentationPersonNameOrder, EngineMessage, Double?, ExpectedTravelTime, ExpectedTravelTime, ExpectedTravelTime, Int)
|
||||
|
||||
var stableId: LocationViewEntryId {
|
||||
public var stableId: LocationViewEntryId {
|
||||
switch self {
|
||||
case .info:
|
||||
return .info
|
||||
case let .toggleLiveLocation(_, _, _, _, _, additional, _):
|
||||
return .toggleLiveLocation(additional)
|
||||
case let .liveLocation(_, _, _, message, _, _, _, _, _):
|
||||
return .liveLocation(message.stableId)
|
||||
case .info:
|
||||
return .info
|
||||
case let .toggleLiveLocation(_, _, _, _, _, additional, _):
|
||||
return .toggleLiveLocation(additional)
|
||||
case let .liveLocation(_, _, _, message, _, _, _, _, _):
|
||||
return .liveLocation(message.stableId)
|
||||
}
|
||||
}
|
||||
|
||||
static func ==(lhs: LocationViewEntry, rhs: LocationViewEntry) -> Bool {
|
||||
public static func ==(lhs: LocationViewEntry, rhs: LocationViewEntry) -> Bool {
|
||||
switch lhs {
|
||||
case let .info(lhsTheme, lhsLocation, lhsAddress, lhsDistance, lhsDrivingTime, lhsTransitTime, lhsWalkingTime, lhsHasEta):
|
||||
if case let .info(rhsTheme, rhsLocation, rhsAddress, rhsDistance, rhsDrivingTime, rhsTransitTime, rhsWalkingTime, rhsHasEta) = rhs, lhsTheme === rhsTheme, lhsLocation.venue?.id == rhsLocation.venue?.id, lhsAddress == rhsAddress, lhsDistance == rhsDistance, lhsDrivingTime == rhsDrivingTime, lhsTransitTime == rhsTransitTime, lhsWalkingTime == rhsWalkingTime, lhsHasEta == rhsHasEta {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .toggleLiveLocation(lhsTheme, lhsTitle, lhsSubtitle, lhsBeginTimestamp, lhsTimeout, lhsAdditional, lhsMessageId):
|
||||
if case let .toggleLiveLocation(rhsTheme, rhsTitle, rhsSubtitle, rhsBeginTimestamp, rhsTimeout, rhsAdditional, rhsMessageId) = rhs, lhsTheme === rhsTheme, lhsTitle == rhsTitle, lhsSubtitle == rhsSubtitle, lhsBeginTimestamp == rhsBeginTimestamp, lhsTimeout == rhsTimeout, lhsAdditional == rhsAdditional, lhsMessageId == rhsMessageId {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .liveLocation(lhsTheme, lhsDateTimeFormat, lhsNameDisplayOrder, lhsMessage, lhsDistance, lhsDrivingTime, lhsTransitTime, lhsWalkingTime, lhsIndex):
|
||||
if case let .liveLocation(rhsTheme, rhsDateTimeFormat, rhsNameDisplayOrder, rhsMessage, rhsDistance, rhsDrivingTime, rhsTransitTime, rhsWalkingTime, rhsIndex) = rhs, lhsTheme === rhsTheme, lhsDateTimeFormat == rhsDateTimeFormat, lhsNameDisplayOrder == rhsNameDisplayOrder, areMessagesEqual(lhsMessage, rhsMessage), lhsDistance == rhsDistance, lhsDrivingTime == rhsDrivingTime, lhsTransitTime == rhsTransitTime, lhsWalkingTime == rhsWalkingTime, lhsIndex == rhsIndex {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static func <(lhs: LocationViewEntry, rhs: LocationViewEntry) -> Bool {
|
||||
switch lhs {
|
||||
case .info:
|
||||
switch rhs {
|
||||
case .info:
|
||||
return false
|
||||
case .toggleLiveLocation, .liveLocation:
|
||||
return true
|
||||
}
|
||||
case let .toggleLiveLocation(_, _, _, _, _, lhsAdditional, _):
|
||||
switch rhs {
|
||||
case .info:
|
||||
return false
|
||||
case let .toggleLiveLocation(_, _, _, _, _, rhsAdditional, _):
|
||||
return !lhsAdditional && rhsAdditional
|
||||
case .liveLocation:
|
||||
return true
|
||||
case let .info(lhsTheme, lhsLocation, lhsAddress, lhsDistance, lhsDrivingTime, lhsTransitTime, lhsWalkingTime, lhsHasEta):
|
||||
if case let .info(rhsTheme, rhsLocation, rhsAddress, rhsDistance, rhsDrivingTime, rhsTransitTime, rhsWalkingTime, rhsHasEta) = rhs, lhsTheme === rhsTheme, lhsLocation.venue?.id == rhsLocation.venue?.id, lhsAddress == rhsAddress, lhsDistance == rhsDistance, lhsDrivingTime == rhsDrivingTime, lhsTransitTime == rhsTransitTime, lhsWalkingTime == rhsWalkingTime, lhsHasEta == rhsHasEta {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .toggleLiveLocation(lhsTheme, lhsTitle, lhsSubtitle, lhsBeginTimestamp, lhsTimeout, lhsAdditional, lhsMessageId):
|
||||
if case let .toggleLiveLocation(rhsTheme, rhsTitle, rhsSubtitle, rhsBeginTimestamp, rhsTimeout, rhsAdditional, rhsMessageId) = rhs, lhsTheme === rhsTheme, lhsTitle == rhsTitle, lhsSubtitle == rhsSubtitle, lhsBeginTimestamp == rhsBeginTimestamp, lhsTimeout == rhsTimeout, lhsAdditional == rhsAdditional, lhsMessageId == rhsMessageId {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .liveLocation(lhsTheme, lhsDateTimeFormat, lhsNameDisplayOrder, lhsMessage, lhsDistance, lhsDrivingTime, lhsTransitTime, lhsWalkingTime, lhsIndex):
|
||||
if case let .liveLocation(rhsTheme, rhsDateTimeFormat, rhsNameDisplayOrder, rhsMessage, rhsDistance, rhsDrivingTime, rhsTransitTime, rhsWalkingTime, rhsIndex) = rhs, lhsTheme === rhsTheme, lhsDateTimeFormat == rhsDateTimeFormat, lhsNameDisplayOrder == rhsNameDisplayOrder, areMessagesEqual(lhsMessage, rhsMessage), lhsDistance == rhsDistance, lhsDrivingTime == rhsDrivingTime, lhsTransitTime == rhsTransitTime, lhsWalkingTime == rhsWalkingTime, lhsIndex == rhsIndex {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static func <(lhs: LocationViewEntry, rhs: LocationViewEntry) -> Bool {
|
||||
switch lhs {
|
||||
case .info:
|
||||
switch rhs {
|
||||
case .info:
|
||||
return false
|
||||
case .toggleLiveLocation, .liveLocation:
|
||||
return true
|
||||
}
|
||||
case let .toggleLiveLocation(_, _, _, _, _, lhsAdditional, _):
|
||||
switch rhs {
|
||||
case .info:
|
||||
return false
|
||||
case let .toggleLiveLocation(_, _, _, _, _, rhsAdditional, _):
|
||||
return !lhsAdditional && rhsAdditional
|
||||
case .liveLocation:
|
||||
return true
|
||||
}
|
||||
case let .liveLocation(_, _, _, _, _, _, _, _, lhsIndex):
|
||||
switch rhs {
|
||||
case .info, .toggleLiveLocation:
|
||||
return false
|
||||
case let .liveLocation(_, _, _, _, _, _, _, _, rhsIndex):
|
||||
return lhsIndex < rhsIndex
|
||||
}
|
||||
case let .liveLocation(_, _, _, _, _, _, _, _, lhsIndex):
|
||||
switch rhs {
|
||||
case .info, .toggleLiveLocation:
|
||||
return false
|
||||
case let .liveLocation(_, _, _, _, _, _, _, _, rhsIndex):
|
||||
return lhsIndex < rhsIndex
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func item(context: AccountContext, presentationData: PresentationData, interaction: LocationViewInteraction?) -> ListViewItem {
|
||||
switch self {
|
||||
case let .info(_, location, address, distance, drivingTime, transitTime, walkingTime, hasEta):
|
||||
let addressString: String?
|
||||
if let address = address {
|
||||
addressString = address
|
||||
} else {
|
||||
addressString = presentationData.strings.Map_Locating
|
||||
}
|
||||
let distanceString: String?
|
||||
if let distance = distance {
|
||||
distanceString = distance < 10 ? presentationData.strings.Map_YouAreHere : presentationData.strings.Map_DistanceAway(stringForDistance(strings: presentationData.strings, distance: distance)).string
|
||||
} else {
|
||||
distanceString = nil
|
||||
}
|
||||
return LocationInfoListItem(presentationData: ItemListPresentationData(presentationData), engine: context.engine, location: location, address: addressString, distance: distanceString, drivingTime: drivingTime, transitTime: transitTime, walkingTime: walkingTime, hasEta: hasEta, action: {
|
||||
interaction?.goToCoordinate(location.coordinate)
|
||||
}, drivingAction: {
|
||||
interaction?.requestDirections(location, nil, .driving)
|
||||
}, transitAction: {
|
||||
interaction?.requestDirections(location, nil, .transit)
|
||||
}, walkingAction: {
|
||||
interaction?.requestDirections(location, nil, .walking)
|
||||
})
|
||||
case let .toggleLiveLocation(_, title, subtitle, beginTimstamp, timeout, additional, messageId):
|
||||
var beginTimeAndTimeout: (Double, Double)?
|
||||
if let beginTimstamp = beginTimstamp, let timeout = timeout {
|
||||
beginTimeAndTimeout = (beginTimstamp, timeout)
|
||||
} else {
|
||||
beginTimeAndTimeout = nil
|
||||
}
|
||||
case let .info(_, location, address, distance, drivingTime, transitTime, walkingTime, hasEta):
|
||||
let addressString: String?
|
||||
if let address = address {
|
||||
addressString = address
|
||||
} else {
|
||||
addressString = presentationData.strings.Map_Locating
|
||||
}
|
||||
let distanceString: String?
|
||||
if let distance = distance {
|
||||
distanceString = distance < 10 ? presentationData.strings.Map_YouAreHere : presentationData.strings.Map_DistanceAway(stringForDistance(strings: presentationData.strings, distance: distance)).string
|
||||
} else {
|
||||
distanceString = nil
|
||||
}
|
||||
return LocationInfoListItem(presentationData: ItemListPresentationData(presentationData), engine: context.engine, location: location, address: addressString, distance: distanceString, drivingTime: drivingTime, transitTime: transitTime, walkingTime: walkingTime, hasEta: hasEta, action: {
|
||||
interaction?.goToCoordinate(location.coordinate)
|
||||
}, drivingAction: {
|
||||
interaction?.requestDirections(location, nil, .driving)
|
||||
}, transitAction: {
|
||||
interaction?.requestDirections(location, nil, .transit)
|
||||
}, walkingAction: {
|
||||
interaction?.requestDirections(location, nil, .walking)
|
||||
})
|
||||
case let .toggleLiveLocation(_, title, subtitle, beginTimstamp, timeout, additional, messageId):
|
||||
var beginTimeAndTimeout: (Double, Double)?
|
||||
if let beginTimstamp = beginTimstamp, let timeout = timeout {
|
||||
beginTimeAndTimeout = (beginTimstamp, timeout)
|
||||
} else {
|
||||
beginTimeAndTimeout = nil
|
||||
}
|
||||
|
||||
let icon: LocationActionListItemIcon
|
||||
if let timeout, Int32(timeout) != liveLocationIndefinitePeriod, !additional {
|
||||
icon = .extendLiveLocation
|
||||
} else if beginTimeAndTimeout != nil {
|
||||
icon = .stopLiveLocation
|
||||
} else {
|
||||
icon = .liveLocation
|
||||
}
|
||||
let icon: LocationActionListItemIcon
|
||||
if let timeout, Int32(timeout) != liveLocationIndefinitePeriod, !additional {
|
||||
icon = .extendLiveLocation
|
||||
} else if beginTimeAndTimeout != nil {
|
||||
icon = .stopLiveLocation
|
||||
} else {
|
||||
icon = .liveLocation
|
||||
}
|
||||
|
||||
return LocationActionListItem(presentationData: ItemListPresentationData(presentationData), engine: context.engine, title: title, subtitle: subtitle, icon: icon, beginTimeAndTimeout: !additional ? beginTimeAndTimeout : nil, action: {
|
||||
if beginTimeAndTimeout != nil {
|
||||
if let timeout, Int32(timeout) != liveLocationIndefinitePeriod {
|
||||
if additional {
|
||||
interaction?.stopLiveLocation()
|
||||
} else {
|
||||
interaction?.sendLiveLocation(nil, true, messageId)
|
||||
}
|
||||
} else {
|
||||
return LocationActionListItem(presentationData: ItemListPresentationData(presentationData), engine: context.engine, title: title, subtitle: subtitle, icon: icon, beginTimeAndTimeout: !additional ? beginTimeAndTimeout : nil, action: {
|
||||
if beginTimeAndTimeout != nil {
|
||||
if let timeout, Int32(timeout) != liveLocationIndefinitePeriod {
|
||||
if additional {
|
||||
interaction?.stopLiveLocation()
|
||||
} else {
|
||||
interaction?.sendLiveLocation(nil, true, messageId)
|
||||
}
|
||||
} else {
|
||||
interaction?.sendLiveLocation(nil, false, nil)
|
||||
interaction?.stopLiveLocation()
|
||||
}
|
||||
}, highlighted: { highlight in
|
||||
interaction?.updateSendActionHighlight(highlight)
|
||||
})
|
||||
case let .liveLocation(_, dateTimeFormat, nameDisplayOrder, message, distance, drivingTime, transitTime, walkingTime, _):
|
||||
var title: String?
|
||||
if let author = message.author {
|
||||
title = author.displayTitle(strings: presentationData.strings, displayOrder: nameDisplayOrder)
|
||||
} else {
|
||||
interaction?.sendLiveLocation(nil, false, nil)
|
||||
}
|
||||
return LocationLiveListItem(presentationData: ItemListPresentationData(presentationData), dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, context: context, message: message, distance: distance, drivingTime: drivingTime, transitTime: transitTime, walkingTime: walkingTime, action: {
|
||||
if let location = getLocation(from: message) {
|
||||
interaction?.goToCoordinate(location.coordinate)
|
||||
}
|
||||
}, longTapAction: {}, drivingAction: {
|
||||
if let location = getLocation(from: message) {
|
||||
interaction?.requestDirections(location, title, .driving)
|
||||
}
|
||||
}, transitAction: {
|
||||
if let location = getLocation(from: message) {
|
||||
interaction?.requestDirections(location, title, .transit)
|
||||
}
|
||||
}, walkingAction: {
|
||||
if let location = getLocation(from: message) {
|
||||
interaction?.requestDirections(location, title, .walking)
|
||||
}
|
||||
})
|
||||
}, highlighted: { highlight in
|
||||
interaction?.updateSendActionHighlight(highlight)
|
||||
})
|
||||
case let .liveLocation(_, dateTimeFormat, nameDisplayOrder, message, distance, drivingTime, transitTime, walkingTime, _):
|
||||
var title: String?
|
||||
if let author = message.author {
|
||||
title = author.displayTitle(strings: presentationData.strings, displayOrder: nameDisplayOrder)
|
||||
}
|
||||
return LocationLiveListItem(presentationData: ItemListPresentationData(presentationData), dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, context: context, message: message, distance: distance, drivingTime: drivingTime, transitTime: transitTime, walkingTime: walkingTime, action: {
|
||||
if let location = getLocation(from: message) {
|
||||
interaction?.goToCoordinate(location.coordinate)
|
||||
}
|
||||
}, longTapAction: {}, drivingAction: {
|
||||
if let location = getLocation(from: message) {
|
||||
interaction?.requestDirections(location, title, .driving)
|
||||
}
|
||||
}, transitAction: {
|
||||
if let location = getLocation(from: message) {
|
||||
interaction?.requestDirections(location, title, .transit)
|
||||
}
|
||||
}, walkingAction: {
|
||||
if let location = getLocation(from: message) {
|
||||
interaction?.requestDirections(location, title, .walking)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -208,22 +208,22 @@ private func preparedTransition(from fromEntries: [LocationViewEntry], to toEntr
|
||||
return LocationViewTransaction(deletions: deletions, insertions: insertions, updates: updates, gotTravelTimes: gotTravelTimes, count: toEntries.count, animated: animated)
|
||||
}
|
||||
|
||||
enum LocationViewLocation: Equatable {
|
||||
public enum LocationViewLocation: Equatable {
|
||||
case initial
|
||||
case user
|
||||
case coordinate(CLLocationCoordinate2D, Bool)
|
||||
case custom
|
||||
}
|
||||
|
||||
struct LocationViewState {
|
||||
var mapMode: LocationMapMode
|
||||
var displayingMapModeOptions: Bool
|
||||
var selectedLocation: LocationViewLocation
|
||||
var trackingMode: LocationTrackingMode
|
||||
var updatingProximityRadius: Int32?
|
||||
var cancellingProximityRadius: Bool
|
||||
public struct LocationViewState {
|
||||
public var mapMode: LocationMapMode
|
||||
public var displayingMapModeOptions: Bool
|
||||
public var selectedLocation: LocationViewLocation
|
||||
public var trackingMode: LocationTrackingMode
|
||||
public var updatingProximityRadius: Int32?
|
||||
public var cancellingProximityRadius: Bool
|
||||
|
||||
init() {
|
||||
public init() {
|
||||
self.mapMode = .map
|
||||
self.displayingMapModeOptions = false
|
||||
self.selectedLocation = .initial
|
||||
@@ -614,12 +614,12 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
||||
switch state.selectedLocation {
|
||||
case .initial:
|
||||
if previousState?.selectedLocation != .initial {
|
||||
strongSelf.headerNode.mapNode.setMapCenter(coordinate: location.coordinate, span: viewMapSpan, animated: previousState != nil)
|
||||
strongSelf.headerNode.mapNode.setMapCenter(coordinate: location.coordinate, span: LocationMapNode.viewMapSpan, animated: previousState != nil)
|
||||
}
|
||||
case let .coordinate(coordinate, defaultSpan):
|
||||
if let previousState = previousState, case let .coordinate(previousCoordinate, _) = previousState.selectedLocation, previousCoordinate == coordinate {
|
||||
} else {
|
||||
strongSelf.headerNode.mapNode.setMapCenter(coordinate: coordinate, span: defaultSpan ? defaultMapSpan : viewMapSpan, animated: true)
|
||||
strongSelf.headerNode.mapNode.setMapCenter(coordinate: coordinate, span: defaultSpan ? LocationMapNode.defaultMapSpan : LocationMapNode.viewMapSpan, animated: true)
|
||||
}
|
||||
case .user:
|
||||
if previousState?.selectedLocation != .user, let userLocation = userLocation {
|
||||
|
||||
Reference in New Issue
Block a user