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.ProximityReached" = "%1$@ is now within %2$@ from %3$@";
"Notification.ProximityReachedYou" = "%1$@ is now within %2$@ from you"; "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.Notify" = "Notify me within %@";
"Location.ProximityNotification.NotifyLong" = "Notify when %1$@ is within %2$@";
"Location.ProximityNotification.AlreadyClose" = "You are already closer than %@"; "Location.ProximityNotification.AlreadyClose" = "You are already closer than %@";
"Location.ProximityNotification.DistanceKM" = "KM"; "Location.ProximityNotification.DistanceKM" = "KM";
"Location.ProximityNotification.DistanceMI" = "MI"; "Location.ProximityNotification.DistanceMI" = "MI";

View File

@ -161,8 +161,10 @@ private var unitValues: [Int32] = {
private var smallUnitValues: [Int32] = { private var smallUnitValues: [Int32] = {
var values: [Int32] = [] var values: [Int32] = []
for i in 0 ..< 100 { values.append(0)
values.append(Int32(i)) values.append(5)
for i in 1 ..< 10 {
values.append(Int32(i * 10))
} }
return values return values
}() }()
@ -333,7 +335,7 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
} }
func numberOfComponents(in pickerView: UIPickerView) -> Int { func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 3 return 2
} }
private func updateDoneButtonTitle() { private func updateDoneButtonTitle() {
@ -409,11 +411,9 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
if component == 0 { if component == 0 {
let value = unitValues[row] let value = unitValues[row]
string = "\(value)" string = "\(value)"
} else if component == 1 { } else {
let value = String(format: "%.2d", smallUnitValues[row]) let value = String(format: "%.2d", smallUnitValues[row])
string = ".\(value)" 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) 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 goToCoordinate: (CLLocationCoordinate2D) -> Void
let requestDirections: () -> Void let requestDirections: () -> Void
let share: () -> Void let share: () -> Void
let setupProximityNotification: (Bool, CLLocationCoordinate2D?, MessageId?) -> Void let setupProximityNotification: (Bool, MessageId?) -> Void
let updateSendActionHighlight: (Bool) -> Void let updateSendActionHighlight: (Bool) -> Void
let sendLiveLocation: (CLLocationCoordinate2D, Int32?) -> Void let sendLiveLocation: (Int32?) -> Void
let stopLiveLocation: () -> Void let stopLiveLocation: () -> Void
let updateRightBarButton: (LocationViewRightBarButton) -> Void let updateRightBarButton: (LocationViewRightBarButton) -> Void
let present: (ViewController) -> 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.toggleMapModeSelection = toggleMapModeSelection
self.updateMapMode = updateMapMode self.updateMapMode = updateMapMode
self.toggleTrackingMode = toggleTrackingMode self.toggleTrackingMode = toggleTrackingMode
@ -173,16 +173,39 @@ 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) 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 { guard let strongSelf = self else {
return return
} }
if reset { if reset {
if let messageId = messageId { 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 { } 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) strongSelf.controllerNode.setProximityIndicator(radius: 0)
let controller = LocationDistancePickerScreen(context: context, style: .default, distances: strongSelf.controllerNode.headerNode.mapNode.distancesToAllAnnotations, updated: { [weak self] distance in let controller = LocationDistancePickerScreen(context: context, style: .default, distances: strongSelf.controllerNode.headerNode.mapNode.distancesToAllAnnotations, updated: { [weak self] distance in
@ -196,11 +219,26 @@ public final class LocationViewController: ViewController {
} }
if let messageId = messageId { 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() strongSelf.controllerNode.updateState { state in
} else if let coordinate = coordinate { 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: { 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() completion()
strongSelf.interaction?.sendLiveLocation(coordinate, distance) strongSelf.interaction?.sendLiveLocation(distance)
}), TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {})], actionLayout: .vertical), in: .window(.root)) }), TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {})], actionLayout: .vertical), in: .window(.root))
} }
completion() completion()
@ -211,12 +249,13 @@ public final class LocationViewController: ViewController {
}) })
strongSelf.present(controller, in: .window(.root)) strongSelf.present(controller, in: .window(.root))
} }
}
}, updateSendActionHighlight: { [weak self] highlighted in }, updateSendActionHighlight: { [weak self] highlighted in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
strongSelf.controllerNode.updateSendActionHighlight(highlighted) strongSelf.controllerNode.updateSendActionHighlight(highlighted)
}, sendLiveLocation: { [weak self] coordinate, distance in }, sendLiveLocation: { [weak self] distance in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
@ -230,7 +269,10 @@ public final class LocationViewController: ViewController {
} }
if let distance = distance { if let distance = distance {
let _ = (strongSelf.controllerNode.coordinate
|> deliverOnMainQueue).start(next: { coordinate in
params.sendLiveLocation(TelegramMediaMap(coordinate: coordinate, liveBroadcastingTimeout: 30 * 60, proximityNotificationRadius: distance)) params.sendLiveLocation(TelegramMediaMap(coordinate: coordinate, liveBroadcastingTimeout: 30 * 60, proximityNotificationRadius: distance))
})
} else { } else {
let _ = (context.account.postbox.loadedPeerWithId(subject.id.peerId) let _ = (context.account.postbox.loadedPeerWithId(subject.id.peerId)
|> deliverOnMainQueue).start(next: { [weak self] peer in |> 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 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() controller?.dismissAnimated()
let _ = (strongSelf.controllerNode.coordinate
|> deliverOnMainQueue).start(next: { coordinate in
params.sendLiveLocation(TelegramMediaMap(coordinate: coordinate, liveBroadcastingTimeout: period)) params.sendLiveLocation(TelegramMediaMap(coordinate: coordinate, liveBroadcastingTimeout: period))
})
} }
controller.setItemGroups([ 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: { return LocationActionListItem(presentationData: ItemListPresentationData(presentationData), account: context.account, title: title, subtitle: subtitle, icon: beginTimeAndTimeout != nil ? .stopLiveLocation : .liveLocation, beginTimeAndTimeout: beginTimeAndTimeout, action: {
if beginTimeAndTimeout != nil { if beginTimeAndTimeout != nil {
interaction?.stopLiveLocation() interaction?.stopLiveLocation()
} else if let coordinate = coordinate { } else {
interaction?.sendLiveLocation(coordinate, nil) interaction?.sendLiveLocation(nil)
} }
}, highlighted: { highlight in }, highlighted: { highlight in
interaction?.updateSendActionHighlight(highlight) interaction?.updateSendActionHighlight(highlight)
@ -176,12 +176,16 @@ struct LocationViewState {
var displayingMapModeOptions: Bool var displayingMapModeOptions: Bool
var selectedLocation: LocationViewLocation var selectedLocation: LocationViewLocation
var trackingMode: LocationTrackingMode var trackingMode: LocationTrackingMode
var updatingProximityRadius: Int32?
var cancellingProximityRadius: Bool
init() { init() {
self.mapMode = .map self.mapMode = .map
self.displayingMapModeOptions = false self.displayingMapModeOptions = false
self.selectedLocation = .initial self.selectedLocation = .initial
self.trackingMode = .none self.trackingMode = .none
self.updatingProximityRadius = nil
self.cancellingProximityRadius = false
} }
} }
@ -274,9 +278,6 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
let _ = (liveLocations let _ = (liveLocations
|> take(1) |> take(1)
|> deliverOnMainQueue).start(next: { [weak self] messages in |> deliverOnMainQueue).start(next: { [weak self] messages in
guard let strongSelf = self else {
return
}
var ownMessageId: MessageId? var ownMessageId: MessageId?
for message in messages { for message in messages {
if message.localTags.contains(.OutgoingLiveLocation) { if message.localTags.contains(.OutgoingLiveLocation) {
@ -284,7 +285,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
break break
} }
} }
interaction.setupProximityNotification(reset, strongSelf.headerNode.mapNode.currentUserLocation?.coordinate, ownMessageId) interaction.setupProximityNotification(reset, ownMessageId)
let _ = ApplicationSpecificNotice.incrementLocationProximityAlertTip(accountManager: context.sharedContext.accountManager, count: 4).start() let _ = ApplicationSpecificNotice.incrementLocationProximityAlertTip(accountManager: context.sharedContext.accountManager, count: 4).start()
}) })
@ -387,12 +388,13 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
} }
for message in effectiveLiveLocations { for message in effectiveLiveLocations {
if let location = getLocation(from: message) {
if let channel = message.peers[message.id.peerId] as? TelegramChannel, case .broadcast = channel.info, message.threadId != nil { if let channel = message.peers[message.id.peerId] as? TelegramChannel, case .broadcast = channel.info, message.threadId != nil {
continue continue
} }
var liveBroadcastingTimeout: Int32 = 0 var liveBroadcastingTimeout: Int32 = 0
if let location = getLocation(from: message), let timeout = location.liveBroadcastingTimeout { if let timeout = location.liveBroadcastingTimeout {
liveBroadcastingTimeout = timeout liveBroadcastingTimeout = timeout
} }
let remainingTime = max(0, message.timestamp + liveBroadcastingTimeout - currentTime) let remainingTime = max(0, message.timestamp + liveBroadcastingTimeout - currentTime)
@ -411,6 +413,14 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
} }
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 { if subject.id.peerId.namespace != Namespaces.Peer.CloudUser, proximityNotification == nil {
proximityNotification = false proximityNotification = false
@ -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.updateLayout(size: optionsFrame.size, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, transition: transition)
self.optionsNode.isUserInteractionEnabled = self.state.displayingMapModeOptions 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
}
}
} }