Location view fixes

This commit is contained in:
Ilya Laktyushin 2020-10-27 20:16:42 +04:00
parent 28e2c78c81
commit 24e18d6f7a
4 changed files with 100 additions and 12 deletions

View File

@ -59,6 +59,7 @@ public final class DeviceLocationManager: NSObject {
self.manager.distanceFilter = 5.0 self.manager.distanceFilter = 5.0
self.manager.activityType = .other self.manager.activityType = .other
self.manager.pausesLocationUpdatesAutomatically = false self.manager.pausesLocationUpdatesAutomatically = false
self.manager.headingFilter = 2.0
} }
public func push(mode: DeviceLocationMode, updated: @escaping (CLLocation, Double?) -> Void) -> Disposable { public func push(mode: DeviceLocationMode, updated: @escaping (CLLocation, Double?) -> Void) -> Disposable {

View File

@ -147,12 +147,17 @@ public final class ChatMessageLiveLocationPositionNode: ASDisplayNode {
var hasPulse = false var hasPulse = false
var heading: Double? var heading: Double?
var coordinate: (Double, Double)? var coordinate: (Double, Double)?
func degToRad(_ degrees: Double) -> Double {
return degrees * Double.pi / 180.0
}
switch mode { switch mode {
case let .liveLocation(_, active, latitude, longitude, headingValue): case let .liveLocation(_, active, latitude, longitude, headingValue):
backgroundImage = avatarBackgroundImage backgroundImage = avatarBackgroundImage
hasPulse = active hasPulse = active
coordinate = (latitude, longitude) coordinate = (latitude, longitude)
heading = headingValue.flatMap { Double($0) } heading = headingValue.flatMap { degToRad(Double($0)) }
case let .location(location): case let .location(location):
let venueType = location?.venue?.type ?? "" let venueType = location?.venue?.type ?? ""
let color = venueType.isEmpty ? theme.list.itemAccentColor : venueIconColor(type: venueType) let color = venueType.isEmpty ? theme.list.itemAccentColor : venueIconColor(type: venueType)
@ -162,10 +167,6 @@ public final class ChatMessageLiveLocationPositionNode: ASDisplayNode {
} }
} }
func degToRad(_ degrees: Double) -> Double {
return degrees * Double.pi / 180.0
}
if heading == nil, let currentCoordinate = currentCoordinate, let coordinate = coordinate { if heading == nil, let currentCoordinate = currentCoordinate, let coordinate = coordinate {
let lat1 = degToRad(currentCoordinate.0) let lat1 = degToRad(currentCoordinate.0)
let lon1 = degToRad(currentCoordinate.1) let lon1 = degToRad(currentCoordinate.1)
@ -248,7 +249,7 @@ public final class ChatMessageLiveLocationPositionNode: ASDisplayNode {
strongSelf.arrowNode.isHidden = heading == nil || !hasPulse strongSelf.arrowNode.isHidden = heading == nil || !hasPulse
strongSelf.arrowNode.position = CGPoint(x: 31.0, y: 64.0) strongSelf.arrowNode.position = CGPoint(x: 31.0, y: 64.0)
strongSelf.arrowNode.transform = CATransform3DMakeRotation(CGFloat(heading ?? 0.0 / 180.0 * Double.pi), 0.0, 0.0, 1.0) strongSelf.arrowNode.transform = CATransform3DMakeRotation(CGFloat(heading ?? 0), 0.0, 0.0, 1.0)
} }
}) })
} }

View File

@ -43,7 +43,7 @@ class LocationPinAnnotation: NSObject, MKAnnotation {
let peer: Peer? let peer: Peer?
let message: Message? let message: Message?
let forcedSelection: Bool let forcedSelection: Bool
var heading: Int32? { @objc dynamic var heading: NSNumber? {
willSet { willSet {
self.willChangeValue(forKey: "heading") self.willChangeValue(forKey: "heading")
} }
@ -91,7 +91,7 @@ class LocationPinAnnotation: NSObject, MKAnnotation {
} }
self.selfPeer = selfPeer self.selfPeer = selfPeer
self.forcedSelection = false self.forcedSelection = false
self.heading = heading self.heading = heading.flatMap { NSNumber(value: $0) }
super.init() super.init()
} }
@ -167,6 +167,8 @@ class LocationPinAnnotationView: MKAnnotationView {
var hasPulse = false var hasPulse = false
var headingKvoToken: NSKeyValueObservation?
override class var layerClass: AnyClass { override class var layerClass: AnyClass {
return LocationPinAnnotationLayer.self return LocationPinAnnotationLayer.self
} }
@ -233,6 +235,14 @@ class LocationPinAnnotationView: MKAnnotationView {
self.annotation = annotation self.annotation = annotation
} }
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
self.headingKvoToken?.invalidate()
}
var defaultZPosition: CGFloat { var defaultZPosition: CGFloat {
if let annotation = self.annotation as? LocationPinAnnotation { if let annotation = self.annotation as? LocationPinAnnotation {
if annotation.forcedSelection { if annotation.forcedSelection {
@ -247,10 +257,6 @@ class LocationPinAnnotationView: MKAnnotationView {
} }
} }
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override var annotation: MKAnnotation? { override var annotation: MKAnnotation? {
didSet { didSet {
if let annotation = self.annotation as? LocationPinAnnotation { if let annotation = self.annotation as? LocationPinAnnotation {
@ -270,6 +276,18 @@ class LocationPinAnnotationView: MKAnnotationView {
self.shadowNode.isHidden = true self.shadowNode.isHidden = true
self.smallNode.isHidden = false self.smallNode.isHidden = false
} }
if let headingKvoToken = self.headingKvoToken {
self.headingKvoToken = nil
headingKvoToken.invalidate()
}
self.headingKvoToken = annotation.observe(\.heading, options: .new) { [weak self] (_, change) in
guard let heading = change.newValue else {
return
}
self?.updateHeading(heading)
}
} }
else if let peer = annotation.peer { else if let peer = annotation.peer {
self.iconNode.isHidden = true self.iconNode.isHidden = true
@ -278,6 +296,12 @@ class LocationPinAnnotationView: MKAnnotationView {
self.setPeer(context: annotation.context, theme: annotation.theme, peer: peer) self.setPeer(context: annotation.context, theme: annotation.theme, peer: peer)
self.setSelected(true, animated: false) self.setSelected(true, animated: false)
if let headingKvoToken = self.headingKvoToken {
self.headingKvoToken = nil
headingKvoToken.invalidate()
}
self.updateHeading(nil)
} else if let location = annotation.location { } else if let location = annotation.location {
let venueType = location.venue?.type ?? "" let venueType = location.venue?.type ?? ""
let color = venueType.isEmpty ? annotation.theme.list.itemAccentColor : venueIconColor(type: venueType) let color = venueType.isEmpty ? annotation.theme.list.itemAccentColor : venueIconColor(type: venueType)
@ -299,15 +323,36 @@ class LocationPinAnnotationView: MKAnnotationView {
self.setSelected(true, animated: false) self.setSelected(true, animated: false)
} }
if let avatarNode = self.avatarNode {
self.avatarNode = nil
avatarNode.removeFromSupernode()
}
if self.initialized && !self.appeared { if self.initialized && !self.appeared {
self.appeared = true self.appeared = true
self.animateAppearance() self.animateAppearance()
} }
if let headingKvoToken = self.headingKvoToken {
self.headingKvoToken = nil
headingKvoToken.invalidate()
}
self.updateHeading(nil)
} }
} }
} }
} }
private func updateHeading(_ heading: NSNumber?) {
if let heading = heading?.int32Value {
self.arrowNode.isHidden = false
self.arrowNode.transform = CATransform3DMakeRotation(CGFloat(heading) / 180.0 * CGFloat.pi, 0.0, 0.0, 1.0)
} else {
self.arrowNode.isHidden = true
self.arrowNode.transform = CATransform3DIdentity
}
}
override func prepareForReuse() { override func prepareForReuse() {
self.smallNode.isHidden = true self.smallNode.isHidden = true
self.backgroundNode.isHidden = false self.backgroundNode.isHidden = false

View File

@ -372,6 +372,11 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
var trackingMode: LocationTrackingMode = .none { var trackingMode: LocationTrackingMode = .none {
didSet { didSet {
self.mapView?.userTrackingMode = self.trackingMode.userTrackingMode self.mapView?.userTrackingMode = self.trackingMode.userTrackingMode
if self.trackingMode == .followWithHeading && self.headingArrowView?.image != nil {
self.headingArrowView?.image = nil
} else if self.trackingMode != .followWithHeading && self.headingArrowView?.image == nil {
self.headingArrowView?.image = generateHeadingArrowImage()
}
} }
} }
@ -676,9 +681,45 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
} }
if let updatedAnnotation = dict[annotation.id] { if let updatedAnnotation = dict[annotation.id] {
func degToRad(_ degrees: Double) -> Double {
return degrees * Double.pi / 180.0
}
func radToDeg(_ radians: Double) -> Double {
return radians / Double.pi * 180.0
}
let currentCoordinate = annotation.coordinate
let coordinate = updatedAnnotation.coordinate
var heading = updatedAnnotation.heading
if heading == nil {
let previous = CLLocation(latitude: currentCoordinate.latitude, longitude: currentCoordinate.longitude)
let new = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
if new.distance(from: previous) > 10 {
let lat1 = degToRad(currentCoordinate.latitude)
let lon1 = degToRad(currentCoordinate.longitude)
let lat2 = degToRad(coordinate.latitude)
let lon2 = degToRad(coordinate.longitude)
let dLat = lat2 - lat1
let dLon = lon2 - lon1
if dLat != 0 && dLon != 0 {
let y = sin(dLon) * cos(lat2)
let x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon)
heading = NSNumber(value: radToDeg(atan2(y, x)))
}
} else {
heading = annotation.heading
}
}
UIView.animate(withDuration: 0.2) { UIView.animate(withDuration: 0.2) {
annotation.coordinate = updatedAnnotation.coordinate annotation.coordinate = updatedAnnotation.coordinate
} }
annotation.heading = heading
dict[annotation.id] = nil dict[annotation.id] = nil
} else { } else {
annotationsToRemove.insert(annotation) annotationsToRemove.insert(annotation)