Don't show directions for story locations

This commit is contained in:
Ilya Laktyushin 2023-08-07 02:03:40 +02:00
parent fe779298f2
commit 9ddb8fa2d6
4 changed files with 106 additions and 94 deletions

View File

@ -20,12 +20,13 @@ final class LocationInfoListItem: ListViewItem {
let drivingTime: ExpectedTravelTime
let transitTime: ExpectedTravelTime
let walkingTime: ExpectedTravelTime
let hasEta: Bool
let action: () -> Void
let drivingAction: () -> Void
let transitAction: () -> Void
let walkingAction: () -> Void
public init(presentationData: ItemListPresentationData, engine: TelegramEngine, location: TelegramMediaMap, address: String?, distance: String?, drivingTime: ExpectedTravelTime, transitTime: ExpectedTravelTime, walkingTime: ExpectedTravelTime, action: @escaping () -> Void, drivingAction: @escaping () -> Void, transitAction: @escaping () -> Void, walkingAction: @escaping () -> Void) {
public init(presentationData: ItemListPresentationData, engine: TelegramEngine, location: TelegramMediaMap, address: String?, distance: String?, drivingTime: ExpectedTravelTime, transitTime: ExpectedTravelTime, walkingTime: ExpectedTravelTime, hasEta: Bool, action: @escaping () -> Void, drivingAction: @escaping () -> Void, transitAction: @escaping () -> Void, walkingAction: @escaping () -> Void) {
self.presentationData = presentationData
self.engine = engine
self.location = location
@ -34,6 +35,7 @@ final class LocationInfoListItem: ListViewItem {
self.drivingTime = drivingTime
self.transitTime = transitTime
self.walkingTime = walkingTime
self.hasEta = hasEta
self.action = action
self.drivingAction = drivingAction
self.transitAction = transitAction
@ -179,7 +181,8 @@ final class LocationInfoListItemNode: ListViewItemNode {
let titleSpacing: CGFloat = 1.0
let bottomInset: CGFloat = 4.0
let contentSize = CGSize(width: params.width, height: max(100.0, verticalInset * 2.0 + titleLayout.size.height + titleSpacing + subtitleLayout.size.height + bottomInset))
let textContentSize = verticalInset * 2.0 + titleLayout.size.height + titleSpacing + subtitleLayout.size.height + bottomInset
let contentSize = CGSize(width: params.width, height: item.hasEta ? max(100.0, textContentSize) : textContentSize)
let nodeLayout = ListViewItemNodeLayout(contentSize: contentSize, insets: UIEdgeInsets())
return (nodeLayout, { [weak self] in
@ -280,95 +283,99 @@ final class LocationInfoListItemNode: ListViewItemNode {
var directionsWidth: CGFloat = 93.0
if item.drivingTime == .unknown && item.transitTime == .unknown && item.walkingTime == .unknown {
strongSelf.drivingButtonNode?.icon = nil
strongSelf.drivingButtonNode?.title = item.presentationData.strings.Map_GetDirections
if let drivingButtonNode = strongSelf.drivingButtonNode {
let buttonSize = drivingButtonNode.sizeThatFits(contentSize)
directionsWidth = buttonSize.width
}
if let previousDrivingTime = currentItem?.drivingTime, case .calculating = previousDrivingTime {
strongSelf.drivingButtonNode?.alpha = 1.0
strongSelf.drivingButtonNode?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
}
} else {
if case let .ready(drivingTime) = item.drivingTime {
strongSelf.drivingButtonNode?.title = stringForEstimatedDuration(strings: item.presentationData.strings, time: drivingTime, format: { $0 })
if item.hasEta {
if item.drivingTime == .unknown && item.transitTime == .unknown && item.walkingTime == .unknown {
strongSelf.drivingButtonNode?.icon = nil
strongSelf.drivingButtonNode?.title = item.presentationData.strings.Map_GetDirections
if let drivingButtonNode = strongSelf.drivingButtonNode {
let buttonSize = drivingButtonNode.sizeThatFits(contentSize)
directionsWidth = buttonSize.width
}
if let previousDrivingTime = currentItem?.drivingTime, case .calculating = previousDrivingTime {
strongSelf.drivingButtonNode?.alpha = 1.0
strongSelf.drivingButtonNode?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
}
}
if case let .ready(transitTime) = item.transitTime {
strongSelf.transitButtonNode?.title = stringForEstimatedDuration(strings: item.presentationData.strings, time: transitTime, format: { $0 })
if let previousTransitTime = currentItem?.transitTime, case .calculating = previousTransitTime {
strongSelf.transitButtonNode?.alpha = 1.0
strongSelf.transitButtonNode?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
}
}
if case let .ready(walkingTime) = item.walkingTime {
strongSelf.walkingButtonNode?.title = stringForEstimatedDuration(strings: item.presentationData.strings, time: walkingTime, format: { $0 })
if let previousWalkingTime = currentItem?.walkingTime, case .calculating = previousWalkingTime {
strongSelf.walkingButtonNode?.alpha = 1.0
strongSelf.walkingButtonNode?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
}
}
}
let directionsSpacing: CGFloat = 8.0
if case .calculating = item.drivingTime, case .calculating = item.transitTime, case .calculating = item.walkingTime {
let shimmerNode: ShimmerEffectNode
if let current = strongSelf.placeholderNode {
shimmerNode = current
} else {
shimmerNode = ShimmerEffectNode()
strongSelf.placeholderNode = shimmerNode
strongSelf.addSubnode(shimmerNode)
}
shimmerNode.frame = CGRect(origin: CGPoint(x: leftInset, y: subtitleFrame.maxY + 12.0), size: CGSize(width: contentSize.width - leftInset, height: 32.0))
if let (rect, size) = strongSelf.absoluteLocation {
shimmerNode.updateAbsoluteRect(rect, within: size)
if case let .ready(drivingTime) = item.drivingTime {
strongSelf.drivingButtonNode?.title = stringForEstimatedDuration(strings: item.presentationData.strings, time: drivingTime, format: { $0 })
if let previousDrivingTime = currentItem?.drivingTime, case .calculating = previousDrivingTime {
strongSelf.drivingButtonNode?.alpha = 1.0
strongSelf.drivingButtonNode?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
}
}
if case let .ready(transitTime) = item.transitTime {
strongSelf.transitButtonNode?.title = stringForEstimatedDuration(strings: item.presentationData.strings, time: transitTime, format: { $0 })
if let previousTransitTime = currentItem?.transitTime, case .calculating = previousTransitTime {
strongSelf.transitButtonNode?.alpha = 1.0
strongSelf.transitButtonNode?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
}
}
if case let .ready(walkingTime) = item.walkingTime {
strongSelf.walkingButtonNode?.title = stringForEstimatedDuration(strings: item.presentationData.strings, time: walkingTime, format: { $0 })
if let previousWalkingTime = currentItem?.walkingTime, case .calculating = previousWalkingTime {
strongSelf.walkingButtonNode?.alpha = 1.0
strongSelf.walkingButtonNode?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
}
}
}
var shapes: [ShimmerEffectNode.Shape] = []
shapes.append(.roundedRectLine(startPoint: CGPoint(x: 0.0, y: 0.0), width: directionsWidth, diameter: 32.0))
shapes.append(.roundedRectLine(startPoint: CGPoint(x: directionsWidth + directionsSpacing, y: 0.0), width: directionsWidth, diameter: 32.0))
shapes.append(.roundedRectLine(startPoint: CGPoint(x: directionsWidth + directionsSpacing + directionsWidth + directionsSpacing, y: 0.0), width: directionsWidth, diameter: 32.0))
let directionsSpacing: CGFloat = 8.0
if case .calculating = item.drivingTime, case .calculating = item.transitTime, case .calculating = item.walkingTime {
let shimmerNode: ShimmerEffectNode
if let current = strongSelf.placeholderNode {
shimmerNode = current
} else {
shimmerNode = ShimmerEffectNode()
strongSelf.placeholderNode = shimmerNode
strongSelf.addSubnode(shimmerNode)
}
shimmerNode.frame = CGRect(origin: CGPoint(x: leftInset, y: subtitleFrame.maxY + 12.0), size: CGSize(width: contentSize.width - leftInset, height: 32.0))
if let (rect, size) = strongSelf.absoluteLocation {
shimmerNode.updateAbsoluteRect(rect, within: size)
}
var shapes: [ShimmerEffectNode.Shape] = []
shapes.append(.roundedRectLine(startPoint: CGPoint(x: 0.0, y: 0.0), width: directionsWidth, diameter: 32.0))
shapes.append(.roundedRectLine(startPoint: CGPoint(x: directionsWidth + directionsSpacing, y: 0.0), width: directionsWidth, diameter: 32.0))
shapes.append(.roundedRectLine(startPoint: CGPoint(x: directionsWidth + directionsSpacing + directionsWidth + directionsSpacing, y: 0.0), width: directionsWidth, diameter: 32.0))
shimmerNode.update(backgroundColor: item.presentationData.theme.list.plainBackgroundColor, foregroundColor: item.presentationData.theme.list.mediaPlaceholderColor, shimmeringColor: item.presentationData.theme.list.itemBlocksBackgroundColor.withAlphaComponent(0.4), shapes: shapes, size: shimmerNode.frame.size)
} else if let shimmerNode = strongSelf.placeholderNode {
strongSelf.placeholderNode = nil
shimmerNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak shimmerNode] _ in
shimmerNode?.removeFromSupernode()
})
}
let drivingHeight = strongSelf.drivingButtonNode?.updateLayout(width: directionsWidth, transition: .immediate) ?? 0.0
let transitHeight = strongSelf.transitButtonNode?.updateLayout(width: directionsWidth, transition: .immediate) ?? 0.0
let walkingHeight = strongSelf.walkingButtonNode?.updateLayout(width: directionsWidth, transition: .immediate) ?? 0.0
var buttonOrigin = leftInset
strongSelf.drivingButtonNode?.frame = CGRect(origin: CGPoint(x: buttonOrigin, y: subtitleFrame.maxY + 12.0), size: CGSize(width: directionsWidth, height: drivingHeight))
if case .ready = item.drivingTime {
buttonOrigin += directionsWidth + directionsSpacing
}
strongSelf.transitButtonNode?.frame = CGRect(origin: CGPoint(x: buttonOrigin, y: subtitleFrame.maxY + 12.0), size: CGSize(width: directionsWidth, height: transitHeight))
if case .ready = item.transitTime {
buttonOrigin += directionsWidth + directionsSpacing
}
strongSelf.walkingButtonNode?.frame = CGRect(origin: CGPoint(x: buttonOrigin, y: subtitleFrame.maxY + 12.0), size: CGSize(width: directionsWidth, height: walkingHeight))
} else {
shimmerNode.update(backgroundColor: item.presentationData.theme.list.plainBackgroundColor, foregroundColor: item.presentationData.theme.list.mediaPlaceholderColor, shimmeringColor: item.presentationData.theme.list.itemBlocksBackgroundColor.withAlphaComponent(0.4), shapes: shapes, size: shimmerNode.frame.size)
} else if let shimmerNode = strongSelf.placeholderNode {
strongSelf.placeholderNode = nil
shimmerNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak shimmerNode] _ in
shimmerNode?.removeFromSupernode()
})
}
let drivingHeight = strongSelf.drivingButtonNode?.updateLayout(width: directionsWidth, transition: .immediate) ?? 0.0
let transitHeight = strongSelf.transitButtonNode?.updateLayout(width: directionsWidth, transition: .immediate) ?? 0.0
let walkingHeight = strongSelf.walkingButtonNode?.updateLayout(width: directionsWidth, transition: .immediate) ?? 0.0
var buttonOrigin = leftInset
strongSelf.drivingButtonNode?.frame = CGRect(origin: CGPoint(x: buttonOrigin, y: subtitleFrame.maxY + 12.0), size: CGSize(width: directionsWidth, height: drivingHeight))
if case .ready = item.drivingTime {
buttonOrigin += directionsWidth + directionsSpacing
}
strongSelf.transitButtonNode?.frame = CGRect(origin: CGPoint(x: buttonOrigin, y: subtitleFrame.maxY + 12.0), size: CGSize(width: directionsWidth, height: transitHeight))
if case .ready = item.transitTime {
buttonOrigin += directionsWidth + directionsSpacing
}
strongSelf.walkingButtonNode?.frame = CGRect(origin: CGPoint(x: buttonOrigin, y: subtitleFrame.maxY + 12.0), size: CGSize(width: directionsWidth, height: walkingHeight))
strongSelf.buttonNode.frame = CGRect(x: 0.0, y: 0.0, width: contentSize.width, height: 72.0)
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: contentSize.width, height: contentSize.height))
}

View File

@ -77,7 +77,7 @@ public final class LocationViewController: ViewController {
private var presentationData: PresentationData
private var presentationDataDisposable: Disposable?
private var showAll: Bool
private let disableDismissGesture: Bool
private let isStoryLocation: Bool
private let locationManager = LocationManager()
private var permissionDisposable: Disposable?
@ -88,11 +88,11 @@ public final class LocationViewController: ViewController {
public var dismissed: () -> Void = {}
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, subject: EngineMessage, disableDismissGesture: Bool = false, params: LocationViewParams) {
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, subject: EngineMessage, isStoryLocation: Bool = false, params: LocationViewParams) {
self.context = context
self.subject = subject
self.showAll = params.showAll
self.disableDismissGesture = disableDismissGesture
self.isStoryLocation = isStoryLocation
self.presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 }
@ -491,7 +491,7 @@ public final class LocationViewController: ViewController {
return
}
self.displayNode = LocationViewControllerNode(context: self.context, presentationData: self.presentationData, subject: self.subject, interaction: interaction, locationManager: self.locationManager)
self.displayNode = LocationViewControllerNode(context: self.context, presentationData: self.presentationData, subject: self.subject, interaction: interaction, locationManager: self.locationManager, isStoryLocation: self.isStoryLocation)
self.displayNodeDidLoad()
self.controllerNode.onAnnotationsReady = { [weak self] in
@ -501,7 +501,7 @@ public final class LocationViewController: ViewController {
strongSelf.controllerNode.showAll()
}
self.controllerNode.headerNode.mapNode.disableHorizontalTransitionGesture = self.disableDismissGesture
self.controllerNode.headerNode.mapNode.disableHorizontalTransitionGesture = self.isStoryLocation
}
private func updateRightBarButton() {

View File

@ -47,7 +47,7 @@ private enum LocationViewEntryId: Hashable {
}
private enum LocationViewEntry: Comparable, Identifiable {
case info(PresentationTheme, TelegramMediaMap, String?, Double?, ExpectedTravelTime, ExpectedTravelTime, ExpectedTravelTime)
case info(PresentationTheme, TelegramMediaMap, String?, Double?, ExpectedTravelTime, ExpectedTravelTime, ExpectedTravelTime, Bool)
case toggleLiveLocation(PresentationTheme, String, String, Double?, Double?)
case liveLocation(PresentationTheme, PresentationDateTimeFormat, PresentationPersonNameOrder, EngineMessage, Double?, ExpectedTravelTime, ExpectedTravelTime, ExpectedTravelTime, Int)
@ -64,8 +64,8 @@ private enum LocationViewEntry: Comparable, Identifiable {
static func ==(lhs: LocationViewEntry, rhs: LocationViewEntry) -> Bool {
switch lhs {
case let .info(lhsTheme, lhsLocation, lhsAddress, lhsDistance, lhsDrivingTime, lhsTransitTime, lhsWalkingTime):
if case let .info(rhsTheme, rhsLocation, rhsAddress, rhsDistance, rhsDrivingTime, rhsTransitTime, rhsWalkingTime) = rhs, lhsTheme === rhsTheme, lhsLocation.venue?.id == rhsLocation.venue?.id, lhsAddress == rhsAddress, lhsDistance == rhsDistance, lhsDrivingTime == rhsDrivingTime, lhsTransitTime == rhsTransitTime, lhsWalkingTime == rhsWalkingTime {
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
@ -113,7 +113,7 @@ private enum LocationViewEntry: Comparable, Identifiable {
func item(context: AccountContext, presentationData: PresentationData, interaction: LocationViewInteraction?) -> ListViewItem {
switch self {
case let .info(_, location, address, distance, drivingTime, transitTime, walkingTime):
case let .info(_, location, address, distance, drivingTime, transitTime, walkingTime, hasEta):
let addressString: String?
if let address = address {
addressString = address
@ -126,7 +126,7 @@ private enum LocationViewEntry: Comparable, Identifiable {
} else {
distanceString = nil
}
return LocationInfoListItem(presentationData: ItemListPresentationData(presentationData), engine: context.engine, location: location, address: addressString, distance: distanceString, drivingTime: drivingTime, transitTime: transitTime, walkingTime: walkingTime, action: {
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)
@ -219,6 +219,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
private var subject: EngineMessage
private let interaction: LocationViewInteraction
private let locationManager: LocationManager
private let isStoryLocation: Bool
private let listNode: ListView
let headerNode: LocationMapHeaderNode
@ -246,13 +247,14 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
}
private let travelTimesPromise = Promise<[EngineMessage.Id: (Double, ExpectedTravelTime, ExpectedTravelTime, ExpectedTravelTime)]>([:])
init(context: AccountContext, presentationData: PresentationData, subject: EngineMessage, interaction: LocationViewInteraction, locationManager: LocationManager) {
init(context: AccountContext, presentationData: PresentationData, subject: EngineMessage, interaction: LocationViewInteraction, locationManager: LocationManager, isStoryLocation: Bool) {
self.context = context
self.presentationData = presentationData
self.presentationDataPromise = Promise(presentationData)
self.subject = subject
self.interaction = interaction
self.locationManager = locationManager
self.isStoryLocation = isStoryLocation
self.state = LocationViewState()
self.statePromise = Promise(self.state)
@ -370,7 +372,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
let subjectLocation = CLLocation(latitude: location.latitude, longitude: location.longitude)
let distance = userLocation.flatMap { subjectLocation.distance(from: $0) }
entries.append(.info(presentationData.theme, location, address, distance, eta.0, eta.1, eta.2))
entries.append(.info(presentationData.theme, location, address, distance, eta.0, eta.1, eta.2, !isStoryLocation))
annotations.append(LocationPinAnnotation(context: context, theme: presentationData.theme, location: location, queryId: nil, resultId: nil, forcedSelection: true))
} else {
@ -849,7 +851,10 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
}
let overlap: CGFloat = 6.0
var topInset: CGFloat = layout.size.height - layout.intrinsicInsets.bottom - 100.0 - overlap
var topInset: CGFloat = layout.size.height - layout.intrinsicInsets.bottom - overlap
if !self.isStoryLocation {
topInset -= 100.0
}
if let location = getLocation(from: self.subject), location.liveBroadcastingTimeout != nil {
topInset += 66.0
}

View File

@ -3109,7 +3109,7 @@ final class StoryItemSetContainerSendMessage {
let subject = EngineMessage(stableId: 0, stableVersion: 0, id: EngineMessage.Id(peerId: PeerId(0), namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [.geo(TelegramMediaMap(latitude: venue.latitude, longitude: venue.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: venue.venue, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil))], peers: [:], associatedMessages: [:], associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
actions.append(ContextMenuAction(content: .textWithIcon(title: "View Location", icon: generateTintedImage(image: UIImage(bundleImageName: "Settings/TextArrowRight"), color: .white)), action: { [weak controller, weak view] in
let locationController = LocationViewController(context: component.context, updatedPresentationData: updatedPresentationData, subject: subject, disableDismissGesture: true, params: LocationViewParams(sendLiveLocation: { _ in }, stopLiveLocation: { _ in }, openUrl: { _ in }, openPeer: { _ in }))
let locationController = LocationViewController(context: component.context, updatedPresentationData: updatedPresentationData, subject: subject, isStoryLocation: true, params: LocationViewParams(sendLiveLocation: { _ in }, stopLiveLocation: { _ in }, openUrl: { _ in }, openPeer: { _ in }))
view?.updateModalTransitionFactor(1.0, transition: .animated(duration: 0.5, curve: .spring))
locationController.dismissed = { [weak view] in
view?.updateModalTransitionFactor(0.0, transition: .animated(duration: 0.5, curve: .spring))