Various fixes

This commit is contained in:
Ilya Laktyushin 2020-10-19 07:55:13 +04:00
parent 43517068e8
commit 05f3e47623
15 changed files with 315 additions and 109 deletions

View File

@ -10,6 +10,7 @@ import AvatarNode
import LocationResources
import AppBundle
import AccountContext
import CoreLocation
private let avatarFont = avatarPlaceholderFont(size: 24.0)
private let avatarBackgroundImage = UIImage(bundleImageName: "Chat/Message/LocationPin")?.precomposed()
@ -50,9 +51,34 @@ private func chatBubbleMapPinImage(_ theme: PresentationTheme, color: UIColor) -
})
}
private let arrowImageSize = CGSize(width: 70.0, height: 70.0)
private func generateHeadingArrowImage() -> UIImage? {
return generateImage(arrowImageSize, contextGenerator: { size, context in
let bounds = CGRect(origin: CGPoint(), size: size)
context.clear(bounds)
context.saveGState()
let center = CGPoint(x: arrowImageSize.width / 2.0, y: arrowImageSize.height / 2.0)
context.move(to: center)
context.addArc(center: center, radius: arrowImageSize.width / 2.0, startAngle: CGFloat.pi / 2.0 + CGFloat.pi / 8.0, endAngle: CGFloat.pi / 2.0 - CGFloat.pi / 8.0, clockwise: true)
context.clip()
var locations: [CGFloat] = [0.0, 0.4, 1.0]
let colors: [CGColor] = [UIColor(rgb: 0x007aff, alpha: 0.5).cgColor, UIColor(rgb: 0x007aff, alpha: 0.3).cgColor, UIColor(rgb: 0x007aff, alpha: 0.0).cgColor]
let colorSpace = CGColorSpaceCreateDeviceRGB()
let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)!
context.drawRadialGradient(gradient, startCenter: center, startRadius: 5.0, endCenter: center, endRadius: arrowImageSize.width / 2.0, options: .drawsAfterEndLocation)
context.restoreGState()
context.setBlendMode(.clear)
context.fillEllipse(in: CGRect(x: (arrowImageSize.width - 10.0) / 2.0, y: (arrowImageSize.height - 10.0) / 2.0, width: 10.0, height: 10.0))
})
}
public final class ChatMessageLiveLocationPositionNode: ASDisplayNode {
public enum Mode {
case liveLocation(Peer, Bool)
case liveLocation(peer: Peer, active: Bool, latitude: Double, longitude: Double, heading: Double?)
case location(TelegramMediaMap?)
}
@ -60,9 +86,12 @@ public final class ChatMessageLiveLocationPositionNode: ASDisplayNode {
private let iconNode: TransformImageNode
private let avatarNode: AvatarNode
private let pulseNode: ASImageNode
private let arrowNode: ASImageNode
private var pulseImage: UIImage?
private var arrowImage: UIImage?
private var venueType: String?
private var coordinate: (Double, Double)?
override public init() {
let isLayerBacked = !smartInvertColorsEnabled()
@ -84,11 +113,19 @@ public final class ChatMessageLiveLocationPositionNode: ASDisplayNode {
self.pulseNode.displayWithoutProcessing = true
self.pulseNode.isHidden = true
self.arrowNode = ASImageNode()
self.arrowNode.frame = CGRect(origin: CGPoint(), size: arrowImageSize)
self.arrowNode.isLayerBacked = true
self.arrowNode.displaysAsynchronously = false
self.arrowNode.displayWithoutProcessing = true
self.arrowNode.isHidden = true
super.init()
self.isLayerBacked = isLayerBacked
self.addSubnode(self.pulseNode)
self.addSubnode(self.arrowNode)
self.addSubnode(self.backgroundNode)
self.addSubnode(self.iconNode)
self.addSubnode(self.avatarNode)
@ -98,17 +135,24 @@ public final class ChatMessageLiveLocationPositionNode: ASDisplayNode {
let iconLayout = self.iconNode.asyncLayout()
let currentPulseImage = self.pulseImage
let currentArrowImage = self.arrowImage
let currentVenueType = self.venueType
let currentCoordinate = self.coordinate
return { [weak self] context, theme, mode in
var updatedVenueType: String?
let backgroundImage: UIImage?
var hasPulse = false
var heading: Double?
var coordinate: (Double, Double)?
switch mode {
case let .liveLocation(_, active):
case let .liveLocation(_, active, latitude, longitude, headingValue):
backgroundImage = avatarBackgroundImage
hasPulse = active
coordinate = (latitude, longitude)
heading = headingValue
case let .location(location):
let venueType = location?.venue?.type ?? ""
let color = venueType.isEmpty ? theme.list.itemAccentColor : venueIconColor(type: venueType)
@ -118,27 +162,57 @@ 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 {
let lat1 = degToRad(currentCoordinate.0)
let lon1 = degToRad(currentCoordinate.1)
let lat2 = degToRad(coordinate.0)
let lon2 = degToRad(coordinate.1)
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 = atan2(y, x)
}
}
let pulseImage: UIImage?
let arrowImage: UIImage?
if hasPulse {
pulseImage = currentPulseImage ?? generateFilledCircleImage(diameter: 120.0, color: UIColor(rgb: 0x007aff, alpha: 0.27))
} else {
pulseImage = nil
}
if let _ = heading {
arrowImage = currentArrowImage ?? generateHeadingArrowImage()
} else {
arrowImage = nil
}
return (CGSize(width: 62.0, height: 74.0), {
if let strongSelf = self {
strongSelf.coordinate = coordinate
if strongSelf.backgroundNode.image !== backgroundImage {
strongSelf.backgroundNode.image = backgroundImage
}
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 62.0, height: 74.0))
strongSelf.avatarNode.frame = CGRect(origin: CGPoint(x: 10.0, y: 9.0), size: CGSize(width: 42.0, height: 42.0))
switch mode {
case let .liveLocation(peer, active):
case let .liveLocation(peer, active, _, _, _):
strongSelf.avatarNode.setPeer(context: context, theme: theme, peer: peer)
strongSelf.avatarNode.isHidden = false
strongSelf.iconNode.isHidden = true
strongSelf.avatarNode.alpha = active ? 1.0 : 0.6
case let .location(location):
case .location:
strongSelf.iconNode.isHidden = false
strongSelf.avatarNode.isHidden = true
}
@ -147,7 +221,6 @@ public final class ChatMessageLiveLocationPositionNode: ASDisplayNode {
strongSelf.venueType = updatedVenueType
strongSelf.iconNode.setSignal(venueIcon(postbox: context.account.postbox, type: updatedVenueType, background: false))
}
let arguments = VenueIconArguments(defaultForegroundColor: theme.chat.inputPanel.actionControlForegroundColor)
let iconSize = CGSize(width: 44.0, height: 44.0)
@ -170,6 +243,13 @@ public final class ChatMessageLiveLocationPositionNode: ASDisplayNode {
strongSelf.pulseNode.isHidden = true
removePulseAnimations(layer: strongSelf.pulseNode.layer)
}
strongSelf.arrowImage = arrowImage
strongSelf.arrowNode.image = arrowImage
strongSelf.arrowNode.isHidden = heading == nil || !hasPulse
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)
}
})
}

View File

@ -3,9 +3,7 @@ import UIKit
import Display
import AsyncDisplayKit
import LegacyComponents
private final class LocationBroadcastPanelWavesNodeParams: NSObject {
private final class LiveLocationWavesNodeParams: NSObject {
let color: UIColor
let progress: CGFloat
@ -21,8 +19,8 @@ private func degToRad(_ degrees: CGFloat) -> CGFloat {
return degrees * CGFloat.pi / 180.0
}
final class LocationBroadcastPanelWavesNode: ASDisplayNode {
var color: UIColor {
public final class LiveLocationWavesNode: ASDisplayNode {
public var color: UIColor {
didSet {
self.setNeedsDisplay()
}
@ -34,7 +32,9 @@ final class LocationBroadcastPanelWavesNode: ASDisplayNode {
}
}
init(color: UIColor) {
var animator: ConstantDisplayLinkAnimator?
public init(color: UIColor) {
self.color = color
super.init()
@ -43,42 +43,72 @@ final class LocationBroadcastPanelWavesNode: ASDisplayNode {
self.isOpaque = false
}
override func willEnterHierarchy() {
deinit {
self.animator?.invalidate()
}
private var previousAnimationStart: Double?
private func updateAnimations(inHierarchy: Bool) {
let timestamp = CACurrentMediaTime()
let animating: Bool
if inHierarchy {
animating = true
let animator: ConstantDisplayLinkAnimator
if let current = self.animator {
animator = current
} else {
animator = ConstantDisplayLinkAnimator(update: { [weak self] in
self?.updateAnimations(inHierarchy: true)
})
self.animator = animator
}
animator.isPaused = false
} else {
animating = false
self.animator?.isPaused = true
self.previousAnimationStart = nil
}
if animating {
let animationDuration: Double = 2.5
if var startTimestamp = self.previousAnimationStart {
if timestamp > startTimestamp + animationDuration {
while timestamp > startTimestamp + animationDuration {
startTimestamp += animationDuration
}
startTimestamp -= animationDuration
}
let t = min(1.0, max(0.0, (timestamp - startTimestamp) / animationDuration))
self.effectiveProgress = CGFloat(t)
} else {
self.previousAnimationStart = timestamp
}
}
}
public override func willEnterHierarchy() {
super.willEnterHierarchy()
self.pop_removeAnimation(forKey: "indefiniteProgress")
let animation = POPBasicAnimation()
animation.property = (POPAnimatableProperty.property(withName: "progress", initializer: { property in
property?.readBlock = { node, values in
values?.pointee = (node as! LocationBroadcastPanelWavesNode).effectiveProgress
}
property?.writeBlock = { node, values in
(node as! LocationBroadcastPanelWavesNode).effectiveProgress = values!.pointee
}
property?.threshold = 0.01
}) as! POPAnimatableProperty)
animation.fromValue = CGFloat(0.0) as NSNumber
animation.toValue = CGFloat(1.0) as NSNumber
animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
animation.duration = 2.5
animation.repeatForever = true
self.pop_add(animation, forKey: "indefiniteProgress")
self.updateAnimations(inHierarchy: true)
}
override func didExitHierarchy() {
public override func didExitHierarchy() {
super.didExitHierarchy()
self.pop_removeAnimation(forKey: "indefiniteProgress")
self.updateAnimations(inHierarchy: false)
}
override func drawParameters(forAsyncLayer layer: _ASDisplayLayer) -> NSObjectProtocol? {
public override func drawParameters(forAsyncLayer layer: _ASDisplayLayer) -> NSObjectProtocol? {
let t = CACurrentMediaTime()
let value: CGFloat = CGFloat(t.truncatingRemainder(dividingBy: 2.0)) / 2.0
return LocationBroadcastPanelWavesNodeParams(color: self.color, progress: value)
return LiveLocationWavesNodeParams(color: self.color, progress: value)
}
@objc override class func draw(_ bounds: CGRect, withParameters parameters: Any?, isCancelled: () -> Bool, isRasterizing: Bool) {
@objc public override class func draw(_ bounds: CGRect, withParameters parameters: Any?, isCancelled: () -> Bool, isRasterizing: Bool) {
let context = UIGraphicsGetCurrentContext()!
if !isRasterizing {
@ -87,7 +117,7 @@ final class LocationBroadcastPanelWavesNode: ASDisplayNode {
context.fill(bounds)
}
if let parameters = parameters as? LocationBroadcastPanelWavesNodeParams {
if let parameters = parameters as? LiveLocationWavesNodeParams {
let center = CGPoint(x: bounds.width / 2.0, y: bounds.height / 2.0)
let length: CGFloat = 9.0

View File

@ -74,7 +74,7 @@ private func generateLiveLocationIcon(theme: PresentationTheme, stop: Bool) -> U
context.scaleBy(x: 1.0, y: -1.0)
context.translateBy(x: -size.width / 2.0, y: -size.height / 2.0)
if let image = generateTintedImage(image: UIImage(bundleImageName: "Location/SendLocationIcon"), color: .white) {
if let image = generateTintedImage(image: UIImage(bundleImageName: "Location/SendLocationIcon"), color: theme.chat.inputPanel.actionControlForegroundColor) {
context.draw(image.cgImage!, in: CGRect(origin: CGPoint(x: floor((size.width - image.size.width) / 2.0), y: floor((size.height - image.size.height) / 2.0)), size: image.size))
}
})!
@ -148,6 +148,7 @@ final class LocationActionListItemNode: ListViewItemNode {
private let iconNode: ASImageNode
private let venueIconNode: TransformImageNode
private var timerNode: ChatMessageLiveLocationTimerNode?
private var wavesNode: LiveLocationWavesNode?
private var item: LocationActionListItem?
private var layoutParams: ListViewItemLayoutParams?
@ -278,6 +279,16 @@ final class LocationActionListItemNode: ListViewItemNode {
strongSelf.venueIconNode.isHidden = false
strongSelf.venueIconNode.setSignal(venueIcon(postbox: item.account.postbox, type: venue.venue?.type ?? "", background: true))
}
if updatedIcon == .stopLiveLocation {
let wavesNode = LiveLocationWavesNode(color: item.presentationData.theme.chat.inputPanel.actionControlForegroundColor)
strongSelf.addSubnode(wavesNode)
strongSelf.wavesNode = wavesNode
} else if let wavesNode = strongSelf.wavesNode {
strongSelf.wavesNode = nil
wavesNode.removeFromSupernode()
}
strongSelf.wavesNode?.color = item.presentationData.theme.chat.inputPanel.actionControlForegroundColor
}
let iconApply = iconLayout(TransformImageArguments(corners: ImageCorners(), imageSize: CGSize(width: iconSize, height: iconSize), boundingSize: CGSize(width: iconSize, height: iconSize), intrinsicInsets: UIEdgeInsets()))
@ -308,6 +319,8 @@ final class LocationActionListItemNode: ListViewItemNode {
strongSelf.iconNode.frame = iconNodeFrame
strongSelf.venueIconNode.frame = iconNodeFrame
strongSelf.wavesNode?.frame = CGRect(origin: CGPoint(x: params.leftInset + 11.0, y: floorToScreenPixels((contentSize.height - bottomInset - iconSize) / 2.0) - 4.0), size: CGSize(width: 48.0, height: 48.0))
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: contentSize.width, height: contentSize.height))
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -nodeLayout.insets.top - topHighlightInset), size: CGSize(width: contentSize.width, height: contentSize.height + topHighlightInset))
strongSelf.separatorNode.frame = CGRect(origin: CGPoint(x: leftInset, y: nodeLayout.contentSize.height - separatorHeight), size: CGSize(width: nodeLayout.size.width, height: separatorHeight))

View File

@ -31,12 +31,26 @@ private func generateSmallBackgroundImage(color: UIColor) -> UIImage? {
class LocationPinAnnotation: NSObject, MKAnnotation {
let context: AccountContext
let theme: PresentationTheme
var coordinate: CLLocationCoordinate2D
var coordinate: CLLocationCoordinate2D {
willSet {
self.willChangeValue(forKey: "coordinate")
}
didSet {
self.didChangeValue(forKey: "coordinate")
}
}
let location: TelegramMediaMap?
let peer: Peer?
let message: Message?
let forcedSelection: Bool
var heading: Int32?
var heading: Int32? {
willSet {
self.willChangeValue(forKey: "heading")
}
didSet {
self.didChangeValue(forKey: "heading")
}
}
var selfPeer: Peer?
var title: String? = ""

View File

@ -74,18 +74,20 @@ func generateHeadingArrowImage() -> UIImage? {
let bounds = CGRect(origin: CGPoint(), size: size)
context.clear(bounds)
context.saveGState()
let center = CGPoint(x: arrowImageSize.width / 2.0, y: arrowImageSize.height / 2.0)
context.move(to: center)
context.addArc(center: center, radius: arrowImageSize.width / 2.0, startAngle: CGFloat.pi / 2.0 + CGFloat.pi / 8.0, endAngle: CGFloat.pi / 2.0 - CGFloat.pi / 8.0, clockwise: true)
context.clip()
var locations: [CGFloat] = [0.0, 0.4, 1.0]
let colors: [CGColor] = [UIColor(rgb: 0x007ee5, alpha: 0.5).cgColor, UIColor(rgb: 0x007ee5, alpha: 0.3).cgColor, UIColor(rgb: 0x007ee5, alpha: 0.0).cgColor]
let colors: [CGColor] = [UIColor(rgb: 0x007aff, alpha: 0.5).cgColor, UIColor(rgb: 0x007aff, alpha: 0.3).cgColor, UIColor(rgb: 0x007aff, alpha: 0.0).cgColor]
let colorSpace = CGColorSpaceCreateDeviceRGB()
let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)!
context.drawRadialGradient(gradient, startCenter: center, startRadius: 11.0, endCenter: center, endRadius: arrowImageSize.width / 2.0, options: .drawsAfterEndLocation)
context.restoreGState()
context.setBlendMode(.clear)
context.fillEllipse(in: CGRect(x: (arrowImageSize.width - 22.0) / 2.0, y: (arrowImageSize.height - 22.0) / 2.0, width: 22.0, height: 22.0))
})
@ -218,10 +220,10 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
} else {
indicatorOverlay = InvertedProximityCircle(center: location.coordinate, radius: activeProximityRadius)
self.mapView?.addOverlay(indicatorOverlay)
self.indicatorOverlay = indicatorOverlay
indicatorOverlay.alpha = 1.0
self.updateAnimations()
}
self.indicatorOverlay = indicatorOverlay
}
} else {
if let indicatorOverlay = self.indicatorOverlay {
@ -261,7 +263,6 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
animator = ConstantDisplayLinkAnimator(update: { [weak self] in
self?.updateAnimations()
})
animator.frameInterval = 2
self.animator = animator
}
animator.isPaused = false
@ -269,7 +270,7 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
self.animator?.isPaused = true
}
self.currentInvertedCircleRenderer?.setNeedsDisplay()
self.currentInvertedCircleRenderer?.setNeedsDisplay(MKMapRect.world)
}
private var circleOverlay: MKCircle?
@ -652,15 +653,33 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
}
if let updatedAnnotation = dict[annotation.id] {
annotation.coordinate = updatedAnnotation.coordinate
UIView.animate(withDuration: 0.2) {
annotation.coordinate = updatedAnnotation.coordinate
}
dict[annotation.id] = nil
} else {
annotationsToRemove.insert(annotation)
}
}
mapView.removeAnnotations(Array(annotationsToRemove))
mapView.addAnnotations(Array(dict.values))
let selectedAnnotation = mapView.selectedAnnotations.first
var updated = false
if !annotationsToRemove.isEmpty {
mapView.removeAnnotations(Array(annotationsToRemove))
updated = true
}
if !dict.isEmpty {
mapView.addAnnotations(Array(dict.values))
updated = true
}
if let selectedAnnotation = selectedAnnotation as? LocationPinAnnotation, updated {
for annotation in self.annotations {
if annotation.id == selectedAnnotation.id {
mapView.selectAnnotation(annotation, animated: false)
break
}
}
}
}
}

View File

@ -42,13 +42,13 @@ class LocationViewInteraction {
let goToCoordinate: (CLLocationCoordinate2D) -> Void
let requestDirections: () -> Void
let share: () -> Void
let setupProximityNotification: (Bool, MessageId?) -> Void
let setupProximityNotification: (Bool, CLLocationCoordinate2D?, MessageId?) -> Void
let updateSendActionHighlight: (Bool) -> Void
let sendLiveLocation: (CLLocationCoordinate2D, Int32?) -> Void
let stopLiveLocation: () -> Void
let updateRightBarButton: (LocationViewRightBarButton) -> Void
init(toggleMapModeSelection: @escaping () -> Void, updateMapMode: @escaping (LocationMapMode) -> Void, goToUserLocation: @escaping () -> Void, goToCoordinate: @escaping (CLLocationCoordinate2D) -> Void, requestDirections: @escaping () -> Void, share: @escaping () -> Void, setupProximityNotification: @escaping (Bool, MessageId?) -> Void, updateSendActionHighlight: @escaping (Bool) -> Void, sendLiveLocation: @escaping (CLLocationCoordinate2D, Int32?) -> Void, stopLiveLocation: @escaping () -> Void, updateRightBarButton: @escaping (LocationViewRightBarButton) -> Void) {
init(toggleMapModeSelection: @escaping () -> Void, updateMapMode: @escaping (LocationMapMode) -> Void, goToUserLocation: @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) {
self.toggleMapModeSelection = toggleMapModeSelection
self.updateMapMode = updateMapMode
self.goToUserLocation = goToUserLocation
@ -166,7 +166,7 @@ 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, messageId in
}, setupProximityNotification: { [weak self] reset, coordinate, messageId in
guard let strongSelf = self else {
return
}
@ -204,8 +204,10 @@ public final class LocationViewController: ViewController {
CURRENT_DISTANCE = Double(distance)
}
} else {
} 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: { [weak self] in
self?.interaction?.sendLiveLocation(coordinate, distance)
}), TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {})]), in: .window(.root))
}
}, willDismiss: { [weak self] in
if let strongSelf = self {
@ -243,21 +245,18 @@ public final class LocationViewController: ViewController {
controller?.dismissAnimated()
if let strongSelf = self {
params.sendLiveLocation(TelegramMediaMap(coordinate: coordinate, liveBroadcastingTimeout: 15 * 60))
strongSelf.dismiss()
}
}),
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Map_LiveLocationFor1Hour, color: .accent, action: { [weak self, weak controller] in
controller?.dismissAnimated()
if let strongSelf = self {
params.sendLiveLocation(TelegramMediaMap(coordinate: coordinate, liveBroadcastingTimeout: 60 * 60 - 1))
strongSelf.dismiss()
}
}),
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Map_LiveLocationFor8Hours, color: .accent, action: { [weak self, weak controller] in
controller?.dismissAnimated()
if let strongSelf = self {
params.sendLiveLocation(TelegramMediaMap(coordinate: coordinate, liveBroadcastingTimeout: 8 * 60 * 60))
strongSelf.dismiss()
}
})
]),
@ -304,7 +303,7 @@ public final class LocationViewController: ViewController {
return
}
self.displayNode = LocationViewControllerNode(context: self.context, presentationData: self.presentationData, subject: self.subject, interaction: interaction)
self.displayNode = LocationViewControllerNode(context: self.context, presentationData: self.presentationData, subject: self.subject, interaction: interaction, locationManager: self.locationManager)
self.displayNodeDidLoad()
self.controllerNode.updateState { state -> LocationViewState in

View File

@ -15,6 +15,7 @@ import AccountContext
import AppBundle
import CoreLocation
import Geocoding
import DeviceAccess
func getLocation(from message: Message) -> TelegramMediaMap? {
return message.media.first(where: { $0 is TelegramMediaMap } ) as? TelegramMediaMap
@ -191,12 +192,13 @@ struct LocationViewState {
}
}
final class LocationViewControllerNode: ViewControllerTracingNode {
final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationManagerDelegate {
private let context: AccountContext
private var presentationData: PresentationData
private let presentationDataPromise: Promise<PresentationData>
private var subject: Message
private let interaction: LocationViewInteraction
private let locationManager: LocationManager
private let listNode: ListView
let headerNode: LocationMapHeaderNode
@ -212,12 +214,13 @@ final class LocationViewControllerNode: ViewControllerTracingNode {
private var validLayout: (layout: ContainerViewLayout, navigationHeight: CGFloat)?
private var listOffset: CGFloat?
init(context: AccountContext, presentationData: PresentationData, subject: Message, interaction: LocationViewInteraction) {
init(context: AccountContext, presentationData: PresentationData, subject: Message, interaction: LocationViewInteraction, locationManager: LocationManager) {
self.context = context
self.presentationData = presentationData
self.presentationDataPromise = Promise(presentationData)
self.subject = subject
self.interaction = interaction
self.locationManager = locationManager
self.state = LocationViewState()
self.statePromise = Promise(self.state)
@ -276,7 +279,10 @@ final class LocationViewControllerNode: ViewControllerTracingNode {
setupProximityNotificationImpl = { reset in
let _ = (liveLocations
|> take(1)
|> deliverOnMainQueue).start(next: { messages in
|> 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 +290,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode {
break
}
}
interaction.setupProximityNotification(reset, ownMessageId)
interaction.setupProximityNotification(reset, strongSelf.headerNode.mapNode.currentUserLocation?.coordinate, ownMessageId)
})
}
@ -351,15 +357,29 @@ final class LocationViewControllerNode: ViewControllerTracingNode {
timeout = Double(liveBroadcastingTimeout)
} else {
title = presentationData.strings.Map_ShareLiveLocation
subtitle = presentationData.strings.Map_ShareLiveLocation
subtitle = presentationData.strings.Map_ShareLiveLocationHelp
beginTime = nil
timeout = nil
}
entries.append(.toggleLiveLocation(presentationData.theme, title, subtitle, userLocation?.coordinate, beginTime, timeout))
if effectiveLiveLocations.isEmpty {
effectiveLiveLocations = [subject]
var sortedLiveLocations: [Message] = []
var effectiveSubject: Message?
for message in effectiveLiveLocations {
if message.id.peerId == subject.id.peerId {
effectiveSubject = message
} else {
sortedLiveLocations.append(message)
}
}
if let effectiveSubject = effectiveSubject {
sortedLiveLocations.insert(effectiveSubject, at: 0)
} else {
sortedLiveLocations.insert(subject, at: 0)
}
effectiveLiveLocations = sortedLiveLocations
}
for message in effectiveLiveLocations {
@ -480,11 +500,20 @@ final class LocationViewControllerNode: ViewControllerTracingNode {
return state
}
}
self.locationManager.manager.startUpdatingHeading()
self.locationManager.manager.delegate = self
}
deinit {
self.disposable?.dispose()
self.geocodingDisposable.dispose()
self.locationManager.manager.stopUpdatingHeading()
}
func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
self.headerNode.mapNode.userHeading = CGFloat(newHeading.magneticHeading)
}
func updatePresentationData(_ presentationData: PresentationData) {

View File

@ -16,7 +16,6 @@ static_library(
"//submodules/TelegramStringFormatting:TelegramStringFormatting",
"//submodules/LiveLocationTimerNode:LiveLocationTimerNode",
"//submodules/AccountContext:AccountContext",
"//submodules/LegacyComponents:LegacyComponents",
"//submodules/OverlayStatusController:OverlayStatusController",
"//submodules/PresentationDataUtils:PresentationDataUtils",
"//submodules/Markdown:Markdown",

View File

@ -17,7 +17,6 @@ swift_library(
"//submodules/TelegramStringFormatting:TelegramStringFormatting",
"//submodules/LiveLocationTimerNode:LiveLocationTimerNode",
"//submodules/AccountContext:AccountContext",
"//submodules/LegacyComponents:LegacyComponents",
"//submodules/OverlayStatusController:OverlayStatusController",
"//submodules/PresentationDataUtils:PresentationDataUtils",
"//submodules/Markdown:Markdown",

View File

@ -10,6 +10,7 @@ import TelegramUIPreferences
import TextFormat
import Markdown
import LocalizedPeerData
import LiveLocationTimerNode
private let titleFont = Font.regular(12.0)
private let subtitleFont = Font.regular(10.0)
@ -31,7 +32,7 @@ final class LocationBroadcastNavigationAccessoryPanel: ASDisplayNode {
private let contentNode: ASDisplayNode
private let iconNode: ASImageNode
private let wavesNode: LocationBroadcastPanelWavesNode
private let wavesNode: LiveLocationWavesNode
private let titleNode: TextNode
private let subtitleNode: TextNode
private let closeButton: HighlightableButtonNode
@ -58,7 +59,7 @@ final class LocationBroadcastNavigationAccessoryPanel: ASDisplayNode {
self.iconNode.displaysAsynchronously = false
self.iconNode.image = PresentationResourcesRootController.navigationLiveLocationIcon(self.theme)
self.wavesNode = LocationBroadcastPanelWavesNode(color: self.theme.rootController.navigationBar.accentTextColor)
self.wavesNode = LiveLocationWavesNode(color: self.theme.rootController.navigationBar.accentTextColor)
self.titleNode = TextNode()
self.titleNode.isUserInteractionEnabled = false

View File

@ -261,7 +261,7 @@ func textMediaAndExpirationTimerFromApiMedia(_ media: Api.MessageMedia?, _ peerI
let mediaMap = telegramMediaMapFromApiGeoPoint(geo, title: title, address: address, provider: provider, venueId: venueId, venueType: venueType, liveBroadcastingTimeout: nil, heading: nil)
return (mediaMap, nil)
case let .messageMediaGeoLive(geo, heading, period):
let mediaMap = telegramMediaMapFromApiGeoPoint(geo, title: nil, address: nil, provider: nil, venueId: nil, venueType: nil, liveBroadcastingTimeout: period, heading: heading)
let mediaMap = telegramMediaMapFromApiGeoPoint(geo, title: nil, address: nil, provider: nil, venueId: nil, venueType: nil, liveBroadcastingTimeout: period, heading: heading > 0 ? heading : nil)
return (mediaMap, nil)
case let .messageMediaDocument(_, document, ttlSeconds):
if let document = document {

View File

@ -10,7 +10,7 @@ func telegramMediaMapFromApiGeoPoint(_ geo: Api.GeoPoint, title: String?, addres
venue = MapVenue(title: title, address: address, provider: provider, id: venueId, type: venueType)
}
switch geo {
case let .geoPoint(_, long, lat, accessHash, accuracyRadius):
case let .geoPoint(_, long, lat, _, accuracyRadius):
return TelegramMediaMap(latitude: lat, longitude: long, heading: heading.flatMap { Double($0) }, accuracyRadius: accuracyRadius.flatMap { Double($0) }, geoPlace: nil, venue: venue, liveBroadcastingTimeout: liveBroadcastingTimeout)
case .geoPointEmpty:
return TelegramMediaMap(latitude: 0.0, longitude: 0.0, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: venue, liveBroadcastingTimeout: liveBroadcastingTimeout)

View File

@ -184,9 +184,12 @@ public final class PrincipalThemeEssentialGraphics {
public let incomingBubbleGradientImage: UIImage?
public let outgoingBubbleGradientImage: UIImage?
public let hasWallpaper: Bool
init(mediaBox: MediaBox, presentationTheme: PresentationTheme, wallpaper initialWallpaper: TelegramWallpaper, preview: Bool = false, knockoutMode: Bool, bubbleCorners: PresentationChatBubbleCorners) {
let theme = presentationTheme.chat
var wallpaper = initialWallpaper
self.hasWallpaper = !wallpaper.isEmpty
let incoming: PresentationThemeBubbleColorComponents = wallpaper.isEmpty ? theme.message.incoming.bubble.withoutWallpaper : theme.message.incoming.bubble.withWallpaper
let outgoing: PresentationThemeBubbleColorComponents = wallpaper.isEmpty ? theme.message.outgoing.bubble.withoutWallpaper : theme.message.outgoing.bubble.withWallpaper

View File

@ -250,7 +250,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
}
if let currentParams = self.currentParams {
var backgroundFrame = CGRect(x: currentParams.contentOrigin.x - offset, y: currentParams.contentOrigin.y, width: currentParams.size.width + offset, height: currentParams.size.height)
let backgroundFrame = CGRect(x: currentParams.contentOrigin.x - offset, y: 0.0, width: currentParams.size.width + offset, height: currentParams.size.height)
self.backgroundNode?.updateLayout(size: backgroundFrame.size, transition: .immediate)
self.backgroundNode?.frame = backgroundFrame
}
@ -262,6 +262,9 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
}
}
func isExtractedToContextPreviewUpdated(_ isExtractedToContextPreview: Bool) {
}
func update(size: CGSize, contentOrigin: CGPoint, index: Int, presentationData: ChatPresentationData, graphics: PrincipalThemeEssentialGraphics, backgroundType: ChatMessageBackgroundType, messageSelection: Bool?) {
self.currentParams = (size, contentOrigin, presentationData, graphics, backgroundType, messageSelection)
let bounds = CGRect(origin: CGPoint(), size: size)
@ -277,17 +280,20 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
if let _ = self.selectionBackgroundNode {
} else {
let selectionBackgroundNode = ASDisplayNode()
self.sourceNode.contentNode.insertSubnode(selectionBackgroundNode, at: 0)
self.containerNode.insertSubnode(selectionBackgroundNode, at: 0)
self.selectionBackgroundNode = selectionBackgroundNode
}
var selectionBackgroundFrame = bounds.offsetBy(dx: contentOrigin.x, dy: contentOrigin.y)
var selectionBackgroundFrame = bounds.offsetBy(dx: contentOrigin.x, dy: 0.0)
if index == 0 && contentOrigin.y > 0.0 {
selectionBackgroundFrame.origin.y -= contentOrigin.y
selectionBackgroundFrame.size.height += contentOrigin.y
}
self.selectionBackgroundNode?.backgroundColor = messageTheme.accentTextColor.withAlphaComponent(0.08)
let bubbleColor = graphics.hasWallpaper ? messageTheme.bubble.withWallpaper.fill : messageTheme.bubble.withoutWallpaper.fill
let selectionColor = bubbleColor.withAlphaComponent(1.0).mixedWith(messageTheme.accentTextColor.withAlphaComponent(1.0), alpha: 0.08)
self.selectionBackgroundNode?.backgroundColor = selectionColor
self.selectionBackgroundNode?.frame = selectionBackgroundFrame
} else if let selectionBackgroundNode = self.selectionBackgroundNode {
self.selectionBackgroundNode = nil
@ -1102,7 +1108,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
let maximumContentWidth = floor(tmpWidth - layoutConstants.bubble.edgeInset - layoutConstants.bubble.edgeInset - layoutConstants.bubble.contentInsets.left - layoutConstants.bubble.contentInsets.right - avatarInset)
var contentPropertiesAndPrepareLayouts: [(Message, Bool, ChatMessageEntryAttributes, BubbleItemAttributes, (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool) -> Void))))] = []
var addedContentNodes: [(Message, ChatMessageBubbleContentNode)]?
var addedContentNodes: [(Message, Bool, ChatMessageBubbleContentNode)]?
let (contentNodeMessagesAndClasses, needSeparateContainers) = contentNodeMessagesAndClassesForItem(item)
for (contentNodeMessage, contentNodeClass, attributes, bubbleAttributes) in contentNodeMessagesAndClasses {
@ -1120,7 +1126,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
if addedContentNodes == nil {
addedContentNodes = []
}
addedContentNodes!.append((contentNodeMessage, contentNode))
addedContentNodes!.append((contentNodeMessage, bubbleAttributes.isAttachment, contentNode))
}
}
@ -1279,7 +1285,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
let (properties, unboundSize, maxNodeWidth, nodeLayout) = prepareLayout(contentItem, layoutConstants, prepareContentPosition, itemSelection, CGSize(width: maximumContentWidth, height: CGFloat.greatestFiniteMagnitude))
maximumNodeWidth = min(maximumNodeWidth, maxNodeWidth)
contentPropertiesAndLayouts.append((unboundSize, properties, prepareContentPosition, bubbleAttributes, nodeLayout, needSeparateContainers ? message.stableId : nil, itemSelection))
contentPropertiesAndLayouts.append((unboundSize, properties, prepareContentPosition, bubbleAttributes, nodeLayout, needSeparateContainers && !bubbleAttributes.isAttachment ? message.stableId : nil, itemSelection))
switch properties.hidesBackground {
case .never:
@ -1616,7 +1622,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
}
for i in 0 ..< contentPropertiesAndLayouts.count {
let (_, contentNodeProperties, preparePosition, _, contentNodeLayout, contentGroupId, itemSelection) = contentPropertiesAndLayouts[i]
let (_, contentNodeProperties, preparePosition, attributes, contentNodeLayout, contentGroupId, itemSelection) = contentPropertiesAndLayouts[i]
if let mosaicRange = mosaicRange, mosaicRange.contains(i), let (framesAndPositions, size) = calculatedGroupFramesAndSize {
let mosaicIndex = i - mosaicRange.lowerBound
@ -1769,7 +1775,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
}
var contentSize = CGSize(width: maxContentWidth, height: 0.0)
var contentNodeFramesPropertiesAndApply: [(CGRect, ChatMessageBubbleContentProperties, (ListViewItemUpdateAnimation, Bool) -> Void)] = []
var contentNodeFramesPropertiesAndApply: [(CGRect, ChatMessageBubbleContentProperties, Bool, (ListViewItemUpdateAnimation, Bool) -> Void)] = []
var contentContainerNodeFrames: [(UInt32, CGRect, Bool?)] = []
var currentContainerGroupId: UInt32?
var currentItemSelection: Bool?
@ -1797,7 +1803,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
let (_, apply) = finalize(maxContentWidth)
let contentNodeFrame = framesAndPositions[mosaicIndex].0.offsetBy(dx: 0.0, dy: contentNodesHeight)
contentNodeFramesPropertiesAndApply.append((contentNodeFrame, properties, apply))
contentNodeFramesPropertiesAndApply.append((contentNodeFrame, properties, false, apply))
if mosaicIndex == mosaicRange.upperBound - 1 {
contentNodesHeight += size.height
@ -1807,8 +1813,10 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
}
} else {
if i == 0 && !headerSize.height.isZero {
contentNodesHeight += properties.headerSpacing
totalContentNodesHeight += contentNodesHeight
if contentGroupId == nil {
contentNodesHeight += properties.headerSpacing
}
totalContentNodesHeight += properties.headerSpacing
}
if currentContainerGroupId != contentGroupId {
@ -1816,17 +1824,22 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
var overlapOffset: CGFloat = 0.0
if !contentContainerNodeFrames.isEmpty {
overlapOffset = smallContainerGroupOverlap
}
contentContainerNodeFrames.append((containerGroupId, CGRect(x: 0.0, y: headerSize.height + totalContentNodesHeight - contentNodesHeight - overlapOffset, width: maxContentWidth, height: contentNodesHeight), currentItemSelection))
if !overlapOffset.isZero {
totalContentNodesHeight -= smallContainerGroupOverlap
}
contentContainerNodeFrames.append((containerGroupId, CGRect(x: 0.0, y: totalContentNodesHeight - contentNodesHeight - overlapOffset, width: maxContentWidth, height: contentNodesHeight), currentItemSelection))
if contentGroupId == nil {
totalContentNodesHeight += 3.0
}
}
contentNodesHeight = 0.0
contentNodesHeight = contentGroupId == nil ? totalContentNodesHeight : 0.0
currentContainerGroupId = contentGroupId
currentItemSelection = itemSelection
}
let (size, apply) = finalize(maxContentWidth)
contentNodeFramesPropertiesAndApply.append((CGRect(origin: CGPoint(x: 0.0, y: contentNodesHeight), size: size), properties, apply))
contentNodeFramesPropertiesAndApply.append((CGRect(origin: CGPoint(x: 0.0, y: contentNodesHeight), size: size), properties, contentGroupId == nil, apply))
contentNodesHeight += size.height
totalContentNodesHeight += size.height
@ -1838,7 +1851,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
if !contentContainerNodeFrames.isEmpty {
overlapOffset = smallContainerGroupOverlap
}
contentContainerNodeFrames.append((containerGroupId, CGRect(x: 0.0, y: totalContentNodesHeight - contentNodesHeight - overlapOffset, width: maxContentWidth, height: contentNodesHeight), currentItemSelection))
contentContainerNodeFrames.append((containerGroupId, CGRect(x: 0.0, y: headerSize.height + totalContentNodesHeight - contentNodesHeight - overlapOffset, width: maxContentWidth, height: contentNodesHeight), currentItemSelection))
if !overlapOffset.isZero {
totalContentNodesHeight -= smallContainerGroupOverlap
}
@ -2007,9 +2020,9 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
replyInfoSizeApply: (CGSize, () -> ChatMessageReplyInfoNode?),
replyInfoOriginY: CGFloat,
removedContentNodeIndices: [Int]?,
addedContentNodes: [(Message, ChatMessageBubbleContentNode)]?,
addedContentNodes: [(Message, Bool, ChatMessageBubbleContentNode)]?,
contentNodeMessagesAndClasses: [(Message, AnyClass, ChatMessageEntryAttributes, BubbleItemAttributes)],
contentNodeFramesPropertiesAndApply: [(CGRect, ChatMessageBubbleContentProperties, (ListViewItemUpdateAnimation, Bool) -> Void)],
contentNodeFramesPropertiesAndApply: [(CGRect, ChatMessageBubbleContentProperties, Bool, (ListViewItemUpdateAnimation, Bool) -> Void)],
contentContainerNodeFrames: [(UInt32, CGRect, Bool?)],
mosaicStatusOrigin: CGPoint?,
mosaicStatusSizeAndApply: (CGSize, (Bool) -> ChatMessageDateAndStatusNode)?,
@ -2263,10 +2276,12 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
}
}
}
contextSourceNode.isExtractedToContextPreviewUpdated = { [weak strongSelf, weak contextSourceNode] isExtractedToContextPreview in
contextSourceNode.isExtractedToContextPreviewUpdated = { [weak strongSelf, weak container, weak contextSourceNode] isExtractedToContextPreview in
guard let strongSelf = strongSelf, let strongContextSourceNode = contextSourceNode else {
return
}
container?.isExtractedToContextPreviewUpdated(isExtractedToContextPreview)
// if !isExtractedToContextPreview, let (rect, size) = strongSelf.absoluteRect {
// strongSelf.updateAbsoluteRect(rect, within: size)
@ -2305,22 +2320,18 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
let containerFrame = CGRect(origin: relativeFrame.origin, size: CGSize(width: params.width, height: relativeFrame.size.height))
contentContainer?.sourceNode.frame = CGRect(origin: CGPoint(), size: containerFrame.size)
contentContainer?.sourceNode.contentNode.frame = CGRect(origin: CGPoint(), size: containerFrame.size)
// contentContainer?.sourceNode.backgroundColor = UIColor.blue.withAlphaComponent(0.5)
contentContainer?.containerNode.frame = containerFrame
// contentContainer?.containerNode.backgroundColor = UIColor.red.withAlphaComponent(0.5)
contentContainer?.sourceNode.contentRect = CGRect(origin: CGPoint(x: backgroundFrame.minX + incomingOffset, y: 0.0), size: relativeFrame.size)
contentContainer?.containerNode.targetNodeForActivationProgressContentRect = relativeFrame.offsetBy(dx: backgroundFrame.minX + incomingOffset, dy: 0.0)
contentContainer?.containerNode.targetNodeForActivationProgressContentRect = CGRect(origin: CGPoint(x: backgroundFrame.minX + incomingOffset, y: 0.0), size: relativeFrame.size)
if previousContextFrame?.size != contentContainer?.containerNode.bounds.size || previousContextContentFrame != contentContainer?.sourceNode.contentRect {
contentContainer?.sourceNode.layoutUpdated?(relativeFrame.size)
}
contentContainer?.update(size: relativeFrame.size, contentOrigin: contentOrigin, index: index, presentationData: item.presentationData, graphics: graphics, backgroundType: backgroundType, messageSelection: itemSelection)
print("container \(relativeFrame)")
index += 1
}
@ -2359,12 +2370,15 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
}
if let addedContentNodes = addedContentNodes {
for (contentNodeMessage, contentNode) in addedContentNodes {
for (contentNodeMessage, isAttachent, contentNode) in addedContentNodes {
updatedContentNodes.append(contentNode)
let contextSourceNode: ContextExtractedContentContainingNode = strongSelf.contentContainers.first(where: { $0.contentMessageStableId == contentNodeMessage.stableId })?.sourceNode ?? strongSelf.mainContextSourceNode
print(contextSourceNode.debugDescription)
let contextSourceNode: ContextExtractedContentContainingNode
if isAttachent {
contextSourceNode = strongSelf.mainContextSourceNode
} else {
contextSourceNode = strongSelf.contentContainers.first(where: { $0.contentMessageStableId == contentNodeMessage.stableId })?.sourceNode ?? strongSelf.mainContextSourceNode
}
contextSourceNode.contentNode.addSubnode(contentNode)
contentNode.visibility = strongSelf.visibility
@ -2378,7 +2392,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
var sortedContentNodes: [ChatMessageBubbleContentNode] = []
outer: for (message, nodeClass, _, _) in contentNodeMessagesAndClasses {
if let addedContentNodes = addedContentNodes {
for (contentNodeMessage, contentNode) in addedContentNodes {
for (contentNodeMessage, _, contentNode) in addedContentNodes {
if type(of: contentNode) == nodeClass && contentNodeMessage.stableId == message.stableId {
sortedContentNodes.append(contentNode)
continue outer
@ -2399,7 +2413,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
}
var contentNodeIndex = 0
for (relativeFrame, _, apply) in contentNodeFramesPropertiesAndApply {
for (relativeFrame, _, useContentOrigin, apply) in contentNodeFramesPropertiesAndApply {
apply(animation, synchronousLoads)
if contentNodeIndex >= strongSelf.contentNodes.count {
@ -2407,17 +2421,15 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
}
let contentNode = strongSelf.contentNodes[contentNodeIndex]
let contentNodeFrame = relativeFrame.offsetBy(dx: contentOrigin.x, dy: contentOrigin.y)
let contentNodeFrame = relativeFrame.offsetBy(dx: contentOrigin.x, dy: useContentOrigin ? contentOrigin.y : 0.0)
let previousContentNodeFrame = contentNode.frame
contentNode.frame = contentNodeFrame
print("frame \(contentNodeFrame.debugDescription)")
if case let .System(duration) = animation {
var animateFrame = false
var animateAlpha = false
if let addedContentNodes = addedContentNodes {
if !addedContentNodes.contains(where: { $0.1 === contentNode }) {
if !addedContentNodes.contains(where: { $0.2 === contentNode }) {
animateFrame = true
} else {
animateAlpha = true
@ -2647,8 +2659,12 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
if let replyInfoNode = self.replyInfoNode {
node.addSubnode(replyInfoNode)
}
for contentNode in self.contentNodes {
node.addSubnode(contentNode)
if !self.contentContainers.isEmpty {
node.addSubnode(self.contentContainersWrapperNode)
} else {
for contentNode in self.contentNodes {
node.addSubnode(contentNode)
}
}
self.mainContextSourceNode.contentNode.addSubnode(node)
self.transitionClippingNode = node
@ -2663,8 +2679,12 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
if let replyInfoNode = self.replyInfoNode {
self.mainContextSourceNode.contentNode.addSubnode(replyInfoNode)
}
for contentNode in self.contentNodes {
self.mainContextSourceNode.contentNode.addSubnode(contentNode)
if !self.contentContainers.isEmpty {
self.mainContextSourceNode.contentNode.addSubnode(self.contentContainersWrapperNode)
} else {
for contentNode in self.contentNodes {
self.mainContextSourceNode.contentNode.addSubnode(contentNode)
}
}
transitionClippingNode.removeFromSupernode()
self.transitionClippingNode = nil

View File

@ -145,7 +145,7 @@ class ChatMessageMapBubbleContentNode: ChatMessageBubbleContentNode {
var mode: ChatMessageLiveLocationPositionNode.Mode = .location(selectedMedia)
if let selectedMedia = selectedMedia, let peer = item.message.author {
if selectedMedia.liveBroadcastingTimeout != nil {
mode = .liveLocation(peer, activeLiveBroadcastingTimeout != nil)
mode = .liveLocation(peer: peer, active: activeLiveBroadcastingTimeout != nil, latitude: selectedMedia.latitude, longitude: selectedMedia.longitude, heading: selectedMedia.heading)
}
}
let (pinSize, pinApply) = makePinLayout(item.context, item.presentationData.theme.theme, mode)