Location view fixes

This commit is contained in:
Ilya Laktyushin 2020-10-28 21:07:06 +04:00
parent ff1392430c
commit 72074f971b
6 changed files with 2813 additions and 2742 deletions

View File

@ -5841,8 +5841,9 @@ Any member of this group will be able to see messages in the channel.";
"Notification.ProximityReached" = "%1$@ is now within %2$@ from %3$@";
"Notification.ProximityReachedYou" = "%1$@ is now within %2$@ from you";
"Location.ProximityNotification.Title" = "Notification";
"Location.ProximityNotification.Title" = "Proximity Alert";
"Location.ProximityNotification.Notify" = "Notify me within %@";
"Location.ProximityNotification.NotifyLong" = "Notify when %1$@ is within %2$@";
"Location.ProximityNotification.AlreadyClose" = "You are already closer than %@";
"Location.ProximityNotification.DistanceKM" = "KM";
"Location.ProximityNotification.DistanceMI" = "MI";

View File

@ -161,8 +161,10 @@ private var unitValues: [Int32] = {
private var smallUnitValues: [Int32] = {
var values: [Int32] = []
for i in 0 ..< 100 {
values.append(Int32(i))
values.append(0)
values.append(5)
for i in 1 ..< 10 {
values.append(Int32(i * 10))
}
return values
}()
@ -333,7 +335,7 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 3
return 2
}
private func updateDoneButtonTitle() {
@ -409,11 +411,9 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
if component == 0 {
let value = unitValues[row]
string = "\(value)"
} else if component == 1 {
} else {
let value = String(format: "%.2d", smallUnitValues[row])
string = ".\(value)"
} else {
string = self.usesMetricSystem() ? self.presentationData.strings.Location_ProximityNotification_DistanceKM : self.presentationData.strings.Location_ProximityNotification_DistanceMI
}
return NSAttributedString(string: string, font: font, textColor: self.presentationData.theme.actionSheet.primaryTextColor)
}

View File

@ -42,14 +42,14 @@ class LocationViewInteraction {
let goToCoordinate: (CLLocationCoordinate2D) -> Void
let requestDirections: () -> Void
let share: () -> Void
let setupProximityNotification: (Bool, CLLocationCoordinate2D?, MessageId?) -> Void
let setupProximityNotification: (Bool, MessageId?) -> Void
let updateSendActionHighlight: (Bool) -> Void
let sendLiveLocation: (CLLocationCoordinate2D, Int32?) -> Void
let sendLiveLocation: (Int32?) -> Void
let stopLiveLocation: () -> Void
let updateRightBarButton: (LocationViewRightBarButton) -> Void
let present: (ViewController) -> Void
init(toggleMapModeSelection: @escaping () -> Void, updateMapMode: @escaping (LocationMapMode) -> Void, toggleTrackingMode: @escaping () -> Void, goToCoordinate: @escaping (CLLocationCoordinate2D) -> Void, requestDirections: @escaping () -> Void, share: @escaping () -> Void, setupProximityNotification: @escaping (Bool, CLLocationCoordinate2D?, MessageId?) -> Void, updateSendActionHighlight: @escaping (Bool) -> Void, sendLiveLocation: @escaping (CLLocationCoordinate2D, Int32?) -> Void, stopLiveLocation: @escaping () -> Void, updateRightBarButton: @escaping (LocationViewRightBarButton) -> Void, present: @escaping (ViewController) -> Void) {
init(toggleMapModeSelection: @escaping () -> Void, updateMapMode: @escaping (LocationMapMode) -> Void, toggleTrackingMode: @escaping () -> Void, goToCoordinate: @escaping (CLLocationCoordinate2D) -> Void, requestDirections: @escaping () -> Void, share: @escaping () -> Void, setupProximityNotification: @escaping (Bool, MessageId?) -> Void, updateSendActionHighlight: @escaping (Bool) -> Void, sendLiveLocation: @escaping (Int32?) -> Void, stopLiveLocation: @escaping () -> Void, updateRightBarButton: @escaping (LocationViewRightBarButton) -> Void, present: @escaping (ViewController) -> Void) {
self.toggleMapModeSelection = toggleMapModeSelection
self.updateMapMode = updateMapMode
self.toggleTrackingMode = toggleTrackingMode
@ -173,50 +173,89 @@ public final class LocationViewController: ViewController {
})
strongSelf.present(OpenInActionSheetController(context: context, item: .location(location: location, withDirections: false), additionalAction: shareAction, openUrl: params.openUrl), in: .window(.root), with: nil)
}
}, setupProximityNotification: { [weak self] reset, coordinate, messageId in
}, setupProximityNotification: { [weak self] reset, messageId in
guard let strongSelf = self else {
return
}
if reset {
if let messageId = messageId {
let _ = requestEditLiveLocation(postbox: context.account.postbox, network: context.account.network, stateManager: context.account.stateManager, messageId: messageId, stop: false, coordinate: nil, heading: nil, proximityNotificationRadius: 0).start()
strongSelf.controllerNode.updateState { state in
var state = state
state.cancellingProximityRadius = true
return state
}
let _ = requestEditLiveLocation(postbox: context.account.postbox, network: context.account.network, stateManager: context.account.stateManager, messageId: messageId, stop: false, coordinate: nil, heading: nil, proximityNotificationRadius: 0).start(completed: { [weak self] in
guard let strongSelf = self else {
return
}
strongSelf.controllerNode.updateState { state in
var state = state
state.cancellingProximityRadius = false
return state
}
})
}
} else {
strongSelf.controllerNode.setProximityIndicator(radius: 0)
let controller = LocationDistancePickerScreen(context: context, style: .default, distances: strongSelf.controllerNode.headerNode.mapNode.distancesToAllAnnotations, updated: { [weak self] distance in
guard let strongSelf = self else {
return
}
strongSelf.controllerNode.setProximityIndicator(radius: distance)
}, completion: { [weak self] distance, completion in
guard let strongSelf = self else {
DeviceAccess.authorizeAccess(to: .location(.live), locationManager: strongSelf.locationManager, presentationData: strongSelf.presentationData, present: { c, a in
strongSelf.present(c, in: .window(.root), with: a)
}, openSettings: {
context.sharedContext.applicationBindings.openSettings()
}) { [weak self] authorized in
guard let strongSelf = self, authorized else {
return
}
strongSelf.controllerNode.setProximityIndicator(radius: 0)
if let messageId = messageId {
let _ = requestEditLiveLocation(postbox: context.account.postbox, network: context.account.network, stateManager: context.account.stateManager, messageId: messageId, stop: false, coordinate: nil, heading: nil, proximityNotificationRadius: distance).start()
} else if let coordinate = coordinate {
strongSelf.present(textAlertController(context: strongSelf.context, title: strongSelf.presentationData.strings.Location_LiveLocationRequired_Title, text: strongSelf.presentationData.strings.Location_LiveLocationRequired_Description, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Location_LiveLocationRequired_ShareLocation, action: {
completion()
strongSelf.interaction?.sendLiveLocation(coordinate, distance)
}), TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {})], actionLayout: .vertical), in: .window(.root))
}
completion()
}, willDismiss: { [weak self] in
if let strongSelf = self {
strongSelf.controllerNode.setProximityIndicator(radius: nil)
}
})
strongSelf.present(controller, in: .window(.root))
let controller = LocationDistancePickerScreen(context: context, style: .default, distances: strongSelf.controllerNode.headerNode.mapNode.distancesToAllAnnotations, updated: { [weak self] distance in
guard let strongSelf = self else {
return
}
strongSelf.controllerNode.setProximityIndicator(radius: distance)
}, completion: { [weak self] distance, completion in
guard let strongSelf = self else {
return
}
if let messageId = messageId {
strongSelf.controllerNode.updateState { state in
var state = state
state.updatingProximityRadius = distance
return state
}
let _ = requestEditLiveLocation(postbox: context.account.postbox, network: context.account.network, stateManager: context.account.stateManager, messageId: messageId, stop: false, coordinate: nil, heading: nil, proximityNotificationRadius: distance).start(completed: { [weak self] in
guard let strongSelf = self else {
return
}
strongSelf.controllerNode.updateState { state in
var state = state
state.updatingProximityRadius = nil
return state
}
})
} else {
strongSelf.present(textAlertController(context: strongSelf.context, title: strongSelf.presentationData.strings.Location_LiveLocationRequired_Title, text: strongSelf.presentationData.strings.Location_LiveLocationRequired_Description, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Location_LiveLocationRequired_ShareLocation, action: {
completion()
strongSelf.interaction?.sendLiveLocation(distance)
}), TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {})], actionLayout: .vertical), in: .window(.root))
}
completion()
}, willDismiss: { [weak self] in
if let strongSelf = self {
strongSelf.controllerNode.setProximityIndicator(radius: nil)
}
})
strongSelf.present(controller, in: .window(.root))
}
}
}, updateSendActionHighlight: { [weak self] highlighted in
guard let strongSelf = self else {
return
}
strongSelf.controllerNode.updateSendActionHighlight(highlighted)
}, sendLiveLocation: { [weak self] coordinate, distance in
}, sendLiveLocation: { [weak self] distance in
guard let strongSelf = self else {
return
}
@ -230,7 +269,10 @@ public final class LocationViewController: ViewController {
}
if let distance = distance {
params.sendLiveLocation(TelegramMediaMap(coordinate: coordinate, liveBroadcastingTimeout: 30 * 60, proximityNotificationRadius: distance))
let _ = (strongSelf.controllerNode.coordinate
|> deliverOnMainQueue).start(next: { coordinate in
params.sendLiveLocation(TelegramMediaMap(coordinate: coordinate, liveBroadcastingTimeout: 30 * 60, proximityNotificationRadius: distance))
})
} else {
let _ = (context.account.postbox.loadedPeerWithId(subject.id.peerId)
|> deliverOnMainQueue).start(next: { [weak self] peer in
@ -240,9 +282,13 @@ public final class LocationViewController: ViewController {
title = strongSelf.presentationData.strings.Map_LiveLocationPrivateDescription(user.compactDisplayTitle).0
}
let sendLiveLocationImpl: (Int32) -> Void = { [weak self, weak controller] period in
let sendLiveLocationImpl: (Int32) -> Void = { [weak controller] period in
controller?.dismissAnimated()
let _ = (strongSelf.controllerNode.coordinate
|> deliverOnMainQueue).start(next: { coordinate in
params.sendLiveLocation(TelegramMediaMap(coordinate: coordinate, liveBroadcastingTimeout: period))
})
}
controller.setItemGroups([

View File

@ -142,8 +142,8 @@ private enum LocationViewEntry: Comparable, Identifiable {
return LocationActionListItem(presentationData: ItemListPresentationData(presentationData), account: context.account, title: title, subtitle: subtitle, icon: beginTimeAndTimeout != nil ? .stopLiveLocation : .liveLocation, beginTimeAndTimeout: beginTimeAndTimeout, action: {
if beginTimeAndTimeout != nil {
interaction?.stopLiveLocation()
} else if let coordinate = coordinate {
interaction?.sendLiveLocation(coordinate, nil)
} else {
interaction?.sendLiveLocation(nil)
}
}, highlighted: { highlight in
interaction?.updateSendActionHighlight(highlight)
@ -176,12 +176,16 @@ struct LocationViewState {
var displayingMapModeOptions: Bool
var selectedLocation: LocationViewLocation
var trackingMode: LocationTrackingMode
var updatingProximityRadius: Int32?
var cancellingProximityRadius: Bool
init() {
self.mapMode = .map
self.displayingMapModeOptions = false
self.selectedLocation = .initial
self.trackingMode = .none
self.updatingProximityRadius = nil
self.cancellingProximityRadius = false
}
}
@ -274,9 +278,6 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
let _ = (liveLocations
|> take(1)
|> deliverOnMainQueue).start(next: { [weak self] messages in
guard let strongSelf = self else {
return
}
var ownMessageId: MessageId?
for message in messages {
if message.localTags.contains(.OutgoingLiveLocation) {
@ -284,7 +285,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
break
}
}
interaction.setupProximityNotification(reset, strongSelf.headerNode.mapNode.currentUserLocation?.coordinate, ownMessageId)
interaction.setupProximityNotification(reset, ownMessageId)
let _ = ApplicationSpecificNotice.incrementLocationProximityAlertTip(accountManager: context.sharedContext.accountManager, count: 4).start()
})
@ -387,29 +388,38 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
}
for message in effectiveLiveLocations {
if let channel = message.peers[message.id.peerId] as? TelegramChannel, case .broadcast = channel.info, message.threadId != nil {
continue
}
if let location = getLocation(from: message) {
if let channel = message.peers[message.id.peerId] as? TelegramChannel, case .broadcast = channel.info, message.threadId != nil {
continue
}
var liveBroadcastingTimeout: Int32 = 0
if let location = getLocation(from: message), let timeout = location.liveBroadcastingTimeout {
liveBroadcastingTimeout = timeout
}
let remainingTime = max(0, message.timestamp + liveBroadcastingTimeout - currentTime)
if message.flags.contains(.Incoming) && remainingTime != 0 && proximityNotification == nil {
proximityNotification = false
}
var liveBroadcastingTimeout: Int32 = 0
if let timeout = location.liveBroadcastingTimeout {
liveBroadcastingTimeout = timeout
}
let remainingTime = max(0, message.timestamp + liveBroadcastingTimeout - currentTime)
if message.flags.contains(.Incoming) && remainingTime != 0 && proximityNotification == nil {
proximityNotification = false
}
let subjectLocation = CLLocation(latitude: location.latitude, longitude: location.longitude)
let distance = userLocation.flatMap { subjectLocation.distance(from: $0) }
let subjectLocation = CLLocation(latitude: location.latitude, longitude: location.longitude)
let distance = userLocation.flatMap { subjectLocation.distance(from: $0) }
if message.localTags.contains(.OutgoingLiveLocation), let selfPeer = selfPeer {
userAnnotation = LocationPinAnnotation(context: context, theme: presentationData.theme, message: message, selfPeer: selfPeer, heading: location.heading)
} else {
annotations.append(LocationPinAnnotation(context: context, theme: presentationData.theme, message: message, selfPeer: selfPeer, heading: location.heading))
entries.append(.liveLocation(presentationData.theme, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, message, distance, index))
if message.localTags.contains(.OutgoingLiveLocation), let selfPeer = selfPeer {
userAnnotation = LocationPinAnnotation(context: context, theme: presentationData.theme, message: message, selfPeer: selfPeer, heading: location.heading)
} else {
annotations.append(LocationPinAnnotation(context: context, theme: presentationData.theme, message: message, selfPeer: selfPeer, heading: location.heading))
entries.append(.liveLocation(presentationData.theme, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, message, distance, index))
}
index += 1
}
index += 1
}
if let currentProximityNotification = proximityNotification, currentProximityNotification && state.cancellingProximityRadius {
proximityNotification = false
} else if let radius = state.updatingProximityRadius {
proximityNotification = true
proximityNotificationRadius = radius
}
if subject.id.peerId.namespace != Namespaces.Peer.CloudUser, proximityNotification == nil {
@ -715,4 +725,15 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
self.optionsNode.updateLayout(size: optionsFrame.size, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, transition: transition)
self.optionsNode.isUserInteractionEnabled = self.state.displayingMapModeOptions
}
var coordinate: Signal<CLLocationCoordinate2D, NoError> {
return self.headerNode.mapNode.userLocation
|> filter { location in
return location != nil
}
|> take(1)
|> map { location -> CLLocationCoordinate2D in
return location!.coordinate
}
}
}