mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge commit '33d946f8db623b378af48d9d56c8d9d9406bbabf' into experimental-2
This commit is contained in:
commit
a33810566d
@ -4366,9 +4366,7 @@ Sorry for the inconvenience.";
|
||||
"Channel.DiscussionGroup.UnlinkGroup" = "Unlink Group";
|
||||
"Channel.DiscussionGroup.UnlinkChannel" = "Unlink Channel";
|
||||
"Channel.DiscussionGroup.PublicChannelLink" = "Do you want to make %1$@ the discussion board for %2$@?";
|
||||
"Channel.DiscussionGroup.PrivateChannelLink" = "Do you want to make %1$@ the discussion board for %2$@?
|
||||
|
||||
Any member of this group will be able to see messages in the channel.";
|
||||
"Channel.DiscussionGroup.PrivateChannelLink" = "Do you want to make %1$@ the discussion board for %2$@?\n\nAny member of this group will be able to see messages in the channel.";
|
||||
"Channel.DiscussionGroup.MakeHistoryPublic" = "Warning: If you set this private group as the disccussion group for your channel, all channel subscribers will be able to access the group. \"Chat history for new members\" will be switched to Visible.";
|
||||
"Channel.DiscussionGroup.MakeHistoryPublicProceed" = "Proceed";
|
||||
|
||||
@ -5840,6 +5838,7 @@ 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";
|
||||
"Notification.ProximityYouReached" = "You are now within %1$@ from %2$@";
|
||||
|
||||
"Location.ProximityNotification.Title" = "Proximity Alert";
|
||||
"Location.ProximityNotification.Notify" = "Notify me within %@";
|
||||
@ -5880,6 +5879,11 @@ Any member of this group will be able to see messages in the channel.";
|
||||
"Location.LiveLocationRequired.Description" = "For the alert to work, please share your live location in this chat.";
|
||||
"Location.LiveLocationRequired.ShareLocation" = "Share Location";
|
||||
|
||||
"Location.ProximityAlertSetTitle" = "Proximity alert set";
|
||||
"Location.ProximityAlertSetText" = "We will notify you once %1$@ is within %2$@ from you.";
|
||||
"Location.ProximityAlertSetTextGroup" = "We will notify you once any other group member is within %@ from you.";
|
||||
"Location.ProximityAlertCancelled" = "Proximity alert cancelled";
|
||||
|
||||
"Stats.Message.Views" = "Views";
|
||||
"Stats.Message.PublicShares" = "Public Shares";
|
||||
"Stats.Message.PrivateShares" = "Private Shares";
|
||||
|
@ -34,8 +34,11 @@ public final class LiveLocationManagerImpl: LiveLocationManager {
|
||||
}
|
||||
|
||||
private let deviceLocationDisposable = MetaDisposable()
|
||||
private let updateCoordinateDisposable = MetaDisposable()
|
||||
private var messagesDisposable: Disposable?
|
||||
|
||||
private var deviceLocationPromise = Promise<(CLLocation, Double?)>()
|
||||
|
||||
private var broadcastToMessageIds: [MessageId: Int32] = [:]
|
||||
private var stopMessageIds = Set<MessageId>()
|
||||
|
||||
@ -106,26 +109,36 @@ public final class LiveLocationManagerImpl: LiveLocationManager {
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] value in
|
||||
if let strongSelf = self {
|
||||
if value {
|
||||
let queue = strongSelf.queue
|
||||
strongSelf.deviceLocationDisposable.set(strongSelf.locationManager.push(mode: .precise, updated: { location, heading in
|
||||
queue.async {
|
||||
var effectiveHeading = heading ?? location.course
|
||||
if location.speed > 1.0 {
|
||||
effectiveHeading = location.course
|
||||
}
|
||||
self?.updateDeviceCoordinate(location.coordinate, accuracyRadius: location.horizontalAccuracy, heading: effectiveHeading)
|
||||
}
|
||||
strongSelf.deviceLocationDisposable.set(strongSelf.locationManager.push(mode: .precise, updated: { [weak self] location, heading in
|
||||
self?.deviceLocationPromise.set(.single((location, heading)))
|
||||
}))
|
||||
} else {
|
||||
strongSelf.deviceLocationDisposable.set(nil)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let throttledDeviceLocation = self.deviceLocationPromise.get()
|
||||
|> mapToThrottled { next -> Signal<(CLLocation, Double?), NoError> in
|
||||
return .single(next) |> then(.complete() |> delay(4.0, queue: Queue.concurrentDefaultQueue()))
|
||||
}
|
||||
|
||||
self.updateCoordinateDisposable.set((throttledDeviceLocation
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] location, heading in
|
||||
if let strongSelf = self {
|
||||
var effectiveHeading = heading ?? location.course
|
||||
if location.speed > 1.0 {
|
||||
effectiveHeading = location.course
|
||||
}
|
||||
strongSelf.updateDeviceCoordinate(location.coordinate, accuracyRadius: location.horizontalAccuracy, heading: effectiveHeading)
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.requiredLocationTypeDisposable?.dispose()
|
||||
self.deviceLocationDisposable.dispose()
|
||||
self.updateCoordinateDisposable.dispose()
|
||||
self.messagesDisposable?.dispose()
|
||||
self.editMessageDisposables.dispose()
|
||||
self.invalidationTimer?.0.invalidate()
|
||||
|
@ -5,6 +5,7 @@ import Display
|
||||
import TelegramPresentationData
|
||||
|
||||
private let textFont = Font.with(size: 13.0, design: .round, traits: [.bold])
|
||||
private let smallTextFont = Font.with(size: 11.0, design: .round, traits: [.bold])
|
||||
|
||||
private class ChatMessageLiveLocationTimerNodeParams: NSObject {
|
||||
let backgroundColor: UIColor
|
||||
@ -119,10 +120,16 @@ public final class ChatMessageLiveLocationTimerNode: ASDisplayNode {
|
||||
path.lineCapStyle = .round
|
||||
path.stroke()
|
||||
|
||||
let attributes: [NSAttributedString.Key: Any] = [.font: textFont, .foregroundColor: parameters.foregroundColor]
|
||||
let attributes: [NSAttributedString.Key: Any] = [.font: parameters.string.count > 2 ? smallTextFont : textFont, .foregroundColor: parameters.foregroundColor]
|
||||
let nsString = parameters.string as NSString
|
||||
let size = nsString.size(withAttributes: attributes)
|
||||
nsString.draw(at: CGPoint(x: floor((bounds.size.width - size.width) / 2.0), y: floor((bounds.size.height - size.height) / 2.0)), withAttributes: attributes)
|
||||
|
||||
var offset: CGFloat = 0.0
|
||||
if parameters.string.count > 2 {
|
||||
offset = UIScreenPixel
|
||||
}
|
||||
|
||||
nsString.draw(at: CGPoint(x: floor((bounds.size.width - size.width) / 2.0), y: floor((bounds.size.height - size.height) / 2.0) + offset), withAttributes: attributes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ static_library(
|
||||
"//submodules/LiveLocationTimerNode:LiveLocationTimerNode",
|
||||
"//submodules/TelegramNotices:TelegramNotices",
|
||||
"//submodules/TooltipUI:TooltipUI",
|
||||
"//submodules/UndoUI:UndoUI",
|
||||
],
|
||||
frameworks = [
|
||||
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
|
||||
|
@ -39,6 +39,7 @@ swift_library(
|
||||
"//submodules/LiveLocationTimerNode:LiveLocationTimerNode",
|
||||
"//submodules/TelegramNotices:TelegramNotices",
|
||||
"//submodules/TooltipUI:TooltipUI",
|
||||
"//submodules/UndoUI:UndoUI",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -239,7 +239,10 @@ final class LocationActionListItemNode: ListViewItemNode {
|
||||
|
||||
let titleSpacing: CGFloat = 1.0
|
||||
let bottomInset: CGFloat = hasSeparator ? 0.0 : 4.0
|
||||
let contentSize = CGSize(width: params.width, height: verticalInset * 2.0 + titleLayout.size.height + titleSpacing + subtitleLayout.size.height + bottomInset)
|
||||
var contentSize = CGSize(width: params.width, height: verticalInset * 2.0 + titleLayout.size.height + titleSpacing + subtitleLayout.size.height + bottomInset)
|
||||
if hasSeparator {
|
||||
contentSize.height = max(52.0, contentSize.height)
|
||||
}
|
||||
let nodeLayout = ListViewItemNodeLayout(contentSize: contentSize, insets: UIEdgeInsets())
|
||||
|
||||
return (nodeLayout, { [weak self] in
|
||||
|
@ -52,6 +52,7 @@ class LocationPinAnnotation: NSObject, MKAnnotation {
|
||||
}
|
||||
}
|
||||
|
||||
var isSelf = false
|
||||
var selfPeer: Peer?
|
||||
var title: String? = ""
|
||||
var subtitle: String? = ""
|
||||
@ -78,11 +79,12 @@ class LocationPinAnnotation: NSObject, MKAnnotation {
|
||||
super.init()
|
||||
}
|
||||
|
||||
init(context: AccountContext, theme: PresentationTheme, message: Message, selfPeer: Peer?, heading: Int32?) {
|
||||
init(context: AccountContext, theme: PresentationTheme, message: Message, selfPeer: Peer?, isSelf: Bool, heading: Int32?) {
|
||||
self.context = context
|
||||
self.theme = theme
|
||||
self.location = nil
|
||||
self.peer = nil
|
||||
self.isSelf = isSelf
|
||||
self.message = message
|
||||
if let location = getLocation(from: message) {
|
||||
self.coordinate = location.coordinate
|
||||
@ -311,6 +313,7 @@ class LocationPinAnnotationView: MKAnnotationView {
|
||||
self.smallNode.image = generateSmallBackgroundImage(color: color)
|
||||
self.dotNode.image = generateFilledCircleImage(diameter: 6.0, color: color)
|
||||
|
||||
self.iconNode.isHidden = false
|
||||
self.dotNode.isHidden = false
|
||||
|
||||
if !self.isSelected {
|
||||
@ -354,6 +357,7 @@ class LocationPinAnnotationView: MKAnnotationView {
|
||||
}
|
||||
|
||||
override func prepareForReuse() {
|
||||
self.previousPeerId = nil
|
||||
self.smallNode.isHidden = true
|
||||
self.backgroundNode.isHidden = false
|
||||
self.appeared = false
|
||||
|
@ -28,16 +28,18 @@ final class LocationDistancePickerScreen: ViewController {
|
||||
private let context: AccountContext
|
||||
private let style: LocationDistancePickerScreenStyle
|
||||
private let distances: Signal<[Double], NoError>
|
||||
private let compactDisplayTitle: String?
|
||||
private let updated: (Int32?) -> Void
|
||||
private let completion: (Int32, @escaping () -> Void) -> Void
|
||||
private let willDismiss: () -> Void
|
||||
|
||||
private var presentationDataDisposable: Disposable?
|
||||
|
||||
init(context: AccountContext, style: LocationDistancePickerScreenStyle, distances: Signal<[Double], NoError>, updated: @escaping (Int32?) -> Void, completion: @escaping (Int32, @escaping () -> Void) -> Void, willDismiss: @escaping () -> Void) {
|
||||
init(context: AccountContext, style: LocationDistancePickerScreenStyle, compactDisplayTitle: String?, distances: Signal<[Double], NoError>, updated: @escaping (Int32?) -> Void, completion: @escaping (Int32, @escaping () -> Void) -> Void, willDismiss: @escaping () -> Void) {
|
||||
self.context = context
|
||||
self.style = style
|
||||
self.distances = distances
|
||||
self.compactDisplayTitle = compactDisplayTitle
|
||||
self.updated = updated
|
||||
self.completion = completion
|
||||
self.willDismiss = willDismiss
|
||||
@ -67,7 +69,7 @@ final class LocationDistancePickerScreen: ViewController {
|
||||
}
|
||||
|
||||
override public func loadDisplayNode() {
|
||||
self.displayNode = LocationDistancePickerScreenNode(context: self.context, style: self.style, distances: self.distances)
|
||||
self.displayNode = LocationDistancePickerScreenNode(context: self.context, style: self.style, compactDisplayTitle: self.compactDisplayTitle, distances: self.distances)
|
||||
self.controllerNode.updated = { [weak self] distance in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@ -173,6 +175,7 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
private let context: AccountContext
|
||||
private let controllerStyle: LocationDistancePickerScreenStyle
|
||||
private var presentationData: PresentationData
|
||||
private var compactDisplayTitle: String?
|
||||
private var distances: [Double] = []
|
||||
|
||||
private let dimNode: ASDisplayNode
|
||||
@ -186,10 +189,14 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
private let cancelButton: HighlightableButtonNode
|
||||
private let doneButton: SolidRoundedButtonNode
|
||||
|
||||
private let measureButtonTitleNode: ImmediateTextNode
|
||||
|
||||
private var pickerView: TimerPickerView?
|
||||
private let unitLabelNode: ImmediateTextNode
|
||||
private let smallUnitLabelNode: ImmediateTextNode
|
||||
|
||||
private var pickerTimer: SwiftSignalKit.Timer?
|
||||
|
||||
private var containerLayout: (ContainerViewLayout, CGFloat)?
|
||||
|
||||
private var distancesDisposable: Disposable?
|
||||
@ -199,11 +206,12 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
var dismiss: (() -> Void)?
|
||||
var cancel: (() -> Void)?
|
||||
|
||||
init(context: AccountContext, style: LocationDistancePickerScreenStyle, distances: Signal<[Double], NoError>) {
|
||||
init(context: AccountContext, style: LocationDistancePickerScreenStyle, compactDisplayTitle: String?, distances: Signal<[Double], NoError>) {
|
||||
self.context = context
|
||||
self.controllerStyle = style
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
self.compactDisplayTitle = compactDisplayTitle
|
||||
|
||||
self.wrappingScrollNode = ASScrollNode()
|
||||
self.wrappingScrollNode.view.alwaysBounceVertical = true
|
||||
self.wrappingScrollNode.view.delaysContentTouches = false
|
||||
@ -256,9 +264,10 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
self.doneButton.title = self.presentationData.strings.Conversation_Timer_Send
|
||||
|
||||
self.unitLabelNode = ImmediateTextNode()
|
||||
|
||||
self.smallUnitLabelNode = ImmediateTextNode()
|
||||
|
||||
self.measureButtonTitleNode = ImmediateTextNode()
|
||||
|
||||
super.init()
|
||||
|
||||
self.backgroundColor = nil
|
||||
@ -314,6 +323,8 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
|
||||
deinit {
|
||||
self.distancesDisposable?.dispose()
|
||||
|
||||
self.pickerTimer?.invalidate()
|
||||
}
|
||||
|
||||
func setupPickerView() {
|
||||
@ -338,6 +349,18 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
self.contentContainerNode.addSubnode(self.unitLabelNode)
|
||||
self.contentContainerNode.addSubnode(self.smallUnitLabelNode)
|
||||
|
||||
self.pickerTimer?.invalidate()
|
||||
|
||||
let pickerTimer = SwiftSignalKit.Timer(timeout: 0.4, repeat: true, completion: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
if strongSelf.update() {
|
||||
strongSelf.updateDoneButtonTitle()
|
||||
}
|
||||
}
|
||||
}, queue: Queue.mainQueue())
|
||||
self.pickerTimer = pickerTimer
|
||||
pickerTimer.start()
|
||||
|
||||
self.updateDoneButtonTitle()
|
||||
}
|
||||
|
||||
@ -364,19 +387,38 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
let largeValue = unitValues[selectedLargeRow]
|
||||
let smallValue = smallUnitValues[selectedSmallRow]
|
||||
|
||||
var value = largeValue * 1000 + smallValue * 10
|
||||
if !self.usesMetricSystem {
|
||||
value = Int32(Double(value) * 1.60934)
|
||||
let value = largeValue * 1000 + smallValue * 10
|
||||
var formattedValue = String(format: "%0.1f", CGFloat(value) / 1000.0)
|
||||
if smallValue == 5 {
|
||||
formattedValue = formattedValue.replacingOccurrences(of: ".1", with: ".05").replacingOccurrences(of: ",1", with: ",05")
|
||||
}
|
||||
let distance = stringForDistance(strings: self.presentationData.strings, distance: CLLocationDistance(value))
|
||||
self.doneButton.title = self.presentationData.strings.Location_ProximityNotification_Notify(distance).0
|
||||
let distance = self.usesMetricSystem ? "\(formattedValue) \(self.presentationData.strings.Location_ProximityNotification_DistanceKM)" : "\(formattedValue) \(self.presentationData.strings.Location_ProximityNotification_DistanceMI)"
|
||||
|
||||
let shortTitle = self.presentationData.strings.Location_ProximityNotification_Notify(distance).0
|
||||
var longTitle: String?
|
||||
if let displayTitle = self.compactDisplayTitle, let (layout, _) = self.containerLayout {
|
||||
let title = self.presentationData.strings.Location_ProximityNotification_NotifyLong(displayTitle, distance).0
|
||||
let width = horizontalContainerFillingSizeForLayout(layout: layout, sideInset: layout.safeInsets.left)
|
||||
|
||||
self.measureButtonTitleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(17.0), textColor: .black)
|
||||
let titleSize = self.measureButtonTitleNode.updateLayout(CGSize(width: width * 2.0, height: 50.0))
|
||||
if titleSize.width < width - 70.0 {
|
||||
longTitle = title
|
||||
}
|
||||
}
|
||||
self.doneButton.title = longTitle ?? shortTitle
|
||||
|
||||
self.textNode.attributedText = NSAttributedString(string: self.presentationData.strings.Location_ProximityNotification_AlreadyClose(distance).0, font: Font.regular(14.0), textColor: self.presentationData.theme.actionSheet.secondaryTextColor)
|
||||
if let (layout, navigationBarHeight) = self.containerLayout {
|
||||
self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate)
|
||||
}
|
||||
|
||||
if let distance = self.distances.last, Double(value) > distance {
|
||||
var convertedValue = Double(value)
|
||||
if !self.usesMetricSystem {
|
||||
convertedValue = Double(convertedValue) * 1.60934
|
||||
}
|
||||
|
||||
if let distance = self.distances.last, convertedValue > distance {
|
||||
self.doneButton.alpha = 0.0
|
||||
self.doneButton.isUserInteractionEnabled = false
|
||||
self.textNode.alpha = 1.0
|
||||
@ -388,26 +430,41 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func update() {
|
||||
var previousReportedValue: Int32?
|
||||
fileprivate func update() -> Bool {
|
||||
if let pickerView = self.pickerView {
|
||||
let largeValue = unitValues[pickerView.selectedRow(inComponent: 0)]
|
||||
let smallValue = smallUnitValues[pickerView.selectedRow(inComponent: 1)]
|
||||
let selectedLargeRow = pickerView.selectedRow(inComponent: 0)
|
||||
var selectedSmallRow = pickerView.selectedRow(inComponent: 1)
|
||||
if selectedLargeRow == 0 && selectedSmallRow == 0 {
|
||||
selectedSmallRow = 1
|
||||
}
|
||||
|
||||
let largeValue = unitValues[selectedLargeRow]
|
||||
let smallValue = smallUnitValues[selectedSmallRow]
|
||||
|
||||
var value = largeValue * 1000 + smallValue * 10
|
||||
if !self.usesMetricSystem {
|
||||
value = Int32(Double(value) * 1.60934)
|
||||
}
|
||||
self.updated?(value)
|
||||
|
||||
if let previousReportedValue = self.previousReportedValue, value == previousReportedValue {
|
||||
return false
|
||||
} else {
|
||||
self.updated?(value)
|
||||
self.previousReportedValue = value
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
|
||||
if pickerView.selectedRow(inComponent: 0) == 0 && pickerView.selectedRow(inComponent: 1) == 0 {
|
||||
pickerView.selectRow(1, inComponent: 1, animated: true)
|
||||
} else {
|
||||
self.updateDoneButtonTitle()
|
||||
self.update()
|
||||
}
|
||||
self.updateDoneButtonTitle()
|
||||
self.update()
|
||||
}
|
||||
|
||||
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
|
||||
@ -540,6 +597,7 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
}
|
||||
|
||||
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
var hadValidLayout = self.containerLayout != nil
|
||||
self.containerLayout = (layout, navigationBarHeight)
|
||||
|
||||
var insets = layout.insets(options: [.statusBar, .input])
|
||||
@ -595,5 +653,9 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
transition.updateFrame(node: self.smallUnitLabelNode, frame: CGRect(origin: CGPoint(x: floor(pickerFrame.width / 4.0 * 3.0) + 50.0, y: floor(pickerFrame.center.y - smallUnitLabelSize.height / 2.0)), size: smallUnitLabelSize))
|
||||
|
||||
transition.updateFrame(node: self.contentContainerNode, frame: contentContainerFrame)
|
||||
|
||||
if !hadValidLayout {
|
||||
self.updateDoneButtonTitle()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ final class LocationLiveListItemNode: ListViewItemNode {
|
||||
|
||||
var subtitle = timeString
|
||||
if let distance = item.distance {
|
||||
let distanceString = item.presentationData.strings.Map_DistanceAway(stringForDistance(strings: item.presentationData.strings, distance: distance)).0
|
||||
let distanceString = item.presentationData.strings.Map_DistanceAway(shortStringForDistance(strings: item.presentationData.strings, distance: Int32(distance))).0
|
||||
subtitle = "\(timeString) • \(distanceString)"
|
||||
}
|
||||
|
||||
|
@ -180,7 +180,7 @@ final class LocationMapHeaderNode: ASDisplayNode {
|
||||
func updateLayout(layout: ContainerViewLayout, navigationBarHeight: CGFloat, topPadding: CGFloat, offset: CGFloat, size: CGSize, transition: ContainedViewLayoutTransition) {
|
||||
self.validLayout = (layout, navigationBarHeight, topPadding, offset, size)
|
||||
|
||||
let mapHeight: CGFloat = floor(layout.size.height * 1.5)
|
||||
let mapHeight: CGFloat = floor(layout.size.height * 1.3)
|
||||
let mapFrame = CGRect(x: 0.0, y: floorToScreenPixels((size.height - mapHeight + navigationBarHeight) / 2.0) + offset, width: size.width, height: mapHeight)
|
||||
transition.updateFrame(node: self.mapNode, frame: mapFrame)
|
||||
self.mapNode.updateLayout(size: mapFrame.size)
|
||||
|
@ -158,6 +158,8 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
private weak var userLocationAnnotationView: MKAnnotationView?
|
||||
private var headingArrowView: UIImageView?
|
||||
|
||||
private weak var defaultUserLocationAnnotation: MKAnnotation?
|
||||
|
||||
private let pinDisposable = MetaDisposable()
|
||||
|
||||
private var mapView: LocationMapView? {
|
||||
@ -253,11 +255,16 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
self.mapView?.showsUserLocation = true
|
||||
self.mapView?.showsPointsOfInterest = false
|
||||
self.mapView?.customHitTest = { [weak self] point in
|
||||
guard let strongSelf = self, let annotationView = strongSelf.customUserLocationAnnotationView else {
|
||||
guard let strongSelf = self else {
|
||||
return false
|
||||
}
|
||||
|
||||
if let annotationRect = annotationView.superview?.convert(annotationView.frame.insetBy(dx: -16.0, dy: -16.0), to: strongSelf.mapView), annotationRect.contains(point) {
|
||||
if let annotationView = strongSelf.customUserLocationAnnotationView, let annotationRect = annotationView.superview?.convert(annotationView.frame.insetBy(dx: -16.0, dy: -16.0), to: strongSelf.mapView), annotationRect.contains(point) {
|
||||
strongSelf.userLocationAnnotationSelected?()
|
||||
return true
|
||||
}
|
||||
|
||||
if let userAnnotation = strongSelf.defaultUserLocationAnnotation, let annotationView = strongSelf.mapView?.view(for: userAnnotation), let annotationRect = annotationView.superview?.convert(annotationView.frame.insetBy(dx: -16.0, dy: -16.0), to: strongSelf.mapView), annotationRect.contains(point) {
|
||||
strongSelf.userLocationAnnotationSelected?()
|
||||
return true
|
||||
}
|
||||
@ -390,6 +397,9 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
|
||||
for view in views {
|
||||
if view.annotation is MKUserLocation {
|
||||
self.defaultUserLocationAnnotation = view.annotation
|
||||
view.canShowCallout = false
|
||||
|
||||
self.userLocationAnnotationView = view
|
||||
if let headingArrowView = self.headingArrowView {
|
||||
view.addSubview(headingArrowView)
|
||||
@ -471,6 +481,9 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
var distances: [Double] = []
|
||||
if let userLocation = userLocation {
|
||||
for annotation in annotations {
|
||||
if annotation.isSelf {
|
||||
continue
|
||||
}
|
||||
distances.append(userLocation.distance(from: CLLocation(latitude: annotation.coordinate.latitude, longitude: annotation.coordinate.longitude)))
|
||||
}
|
||||
}
|
||||
@ -483,7 +496,8 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
|
||||
var userLocation: Signal<CLLocation?, NoError> {
|
||||
return self.locationPromise.get()
|
||||
return .single(self.currentUserLocation)
|
||||
|> then (self.locationPromise.get())
|
||||
}
|
||||
|
||||
var mapCenterCoordinate: CLLocationCoordinate2D? {
|
||||
@ -693,15 +707,15 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
guard let mapView = self.mapView else {
|
||||
return
|
||||
}
|
||||
var annotations: [MKAnnotation] = []
|
||||
if let userAnnotation = self.userLocationAnnotation {
|
||||
annotations.append(userAnnotation)
|
||||
var coordinates: [CLLocationCoordinate2D] = []
|
||||
if let location = self.currentUserLocation {
|
||||
coordinates.append(location.coordinate)
|
||||
}
|
||||
annotations.append(contentsOf: self.annotations)
|
||||
coordinates.append(contentsOf: self.annotations.map { $0.coordinate })
|
||||
|
||||
var zoomRect: MKMapRect?
|
||||
for annotation in annotations {
|
||||
let pointRegionRect = MKMapRect(region: MKCoordinateRegion(center: annotation.coordinate, latitudinalMeters: 100, longitudinalMeters: 100))
|
||||
for coordinate in coordinates {
|
||||
let pointRegionRect = MKMapRect(region: MKCoordinateRegion(center: coordinate, latitudinalMeters: 100, longitudinalMeters: 100))
|
||||
if let currentZoomRect = zoomRect {
|
||||
zoomRect = currentZoomRect.union(pointRegionRect)
|
||||
} else {
|
||||
|
@ -7,6 +7,7 @@ import SyncCore
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
import TelegramPresentationData
|
||||
import TelegramStringFormatting
|
||||
import AccountContext
|
||||
import AppBundle
|
||||
import CoreLocation
|
||||
@ -14,6 +15,7 @@ import PresentationDataUtils
|
||||
import OpenInExternalAppUI
|
||||
import ShareController
|
||||
import DeviceAccess
|
||||
import UndoUI
|
||||
|
||||
public class LocationViewParams {
|
||||
let sendLiveLocation: (TelegramMediaMap) -> Void
|
||||
@ -194,12 +196,31 @@ public final class LocationViewController: ViewController {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.controllerNode.updateState { state in
|
||||
var state = state
|
||||
state.cancellingProximityRadius = false
|
||||
return state
|
||||
Queue.mainQueue().after(0.5) {
|
||||
strongSelf.controllerNode.updateState { state in
|
||||
var state = state
|
||||
state.cancellingProximityRadius = false
|
||||
return state
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
strongSelf.dismissAllTooltips()
|
||||
strongSelf.present(
|
||||
UndoOverlayController(
|
||||
presentationData: strongSelf.presentationData,
|
||||
content: .setProximityAlert(
|
||||
title: strongSelf.presentationData.strings.Location_ProximityAlertCancelled,
|
||||
text: "",
|
||||
cancelled: true
|
||||
),
|
||||
elevatedLayout: false,
|
||||
action: { action in
|
||||
return true
|
||||
}
|
||||
),
|
||||
in: .current
|
||||
)
|
||||
}
|
||||
} else {
|
||||
DeviceAccess.authorizeAccess(to: .location(.live), locationManager: strongSelf.locationManager, presentationData: strongSelf.presentationData, present: { c, a in
|
||||
@ -212,46 +233,85 @@ public final class LocationViewController: ViewController {
|
||||
}
|
||||
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
|
||||
let _ = (strongSelf.context.account.postbox.loadedPeerWithId(strongSelf.subject.id.peerId)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
if let messageId = messageId {
|
||||
strongSelf.controllerNode.updateState { state in
|
||||
var state = state
|
||||
state.updatingProximityRadius = distance
|
||||
return state
|
||||
var compactDisplayTitle: String?
|
||||
if let peer = peer as? TelegramUser {
|
||||
compactDisplayTitle = peer.compactDisplayTitle
|
||||
}
|
||||
|
||||
let controller = LocationDistancePickerScreen(context: context, style: .default, compactDisplayTitle: compactDisplayTitle, 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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
if let messageId = messageId {
|
||||
strongSelf.controllerNode.updateState { state in
|
||||
var state = state
|
||||
state.updatingProximityRadius = nil
|
||||
state.updatingProximityRadius = distance
|
||||
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)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
Queue.mainQueue().after(0.5) {
|
||||
strongSelf.controllerNode.updateState { state in
|
||||
var state = state
|
||||
state.updatingProximityRadius = nil
|
||||
return state
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
var text: String
|
||||
let distanceString = shortStringForDistance(strings: strongSelf.presentationData.strings, distance: distance)
|
||||
if let compactDisplayTitle = compactDisplayTitle {
|
||||
text = strongSelf.presentationData.strings.Location_ProximityAlertSetText(compactDisplayTitle, distanceString).0
|
||||
} else {
|
||||
text = strongSelf.presentationData.strings.Location_ProximityAlertSetTextGroup(distanceString).0
|
||||
}
|
||||
|
||||
strongSelf.dismissAllTooltips()
|
||||
strongSelf.present(
|
||||
UndoOverlayController(
|
||||
presentationData: strongSelf.presentationData,
|
||||
content: .setProximityAlert(
|
||||
title: strongSelf.presentationData.strings.Location_ProximityAlertSetTitle,
|
||||
text: text,
|
||||
cancelled: false
|
||||
),
|
||||
elevatedLayout: false,
|
||||
action: { action in
|
||||
return true
|
||||
}
|
||||
),
|
||||
in: .current
|
||||
)
|
||||
} 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))
|
||||
})
|
||||
strongSelf.present(controller, in: .window(.root))
|
||||
}
|
||||
}
|
||||
}, updateSendActionHighlight: { [weak self] highlighted in
|
||||
@ -277,6 +337,43 @@ public final class LocationViewController: ViewController {
|
||||
|> deliverOnMainQueue).start(next: { coordinate in
|
||||
params.sendLiveLocation(TelegramMediaMap(coordinate: coordinate, liveBroadcastingTimeout: 30 * 60, proximityNotificationRadius: distance))
|
||||
})
|
||||
|
||||
let _ = (strongSelf.context.account.postbox.loadedPeerWithId(strongSelf.subject.id.peerId)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
var compactDisplayTitle: String?
|
||||
if let peer = peer as? TelegramUser {
|
||||
compactDisplayTitle = peer.compactDisplayTitle
|
||||
}
|
||||
|
||||
var text: String
|
||||
let distanceString = shortStringForDistance(strings: strongSelf.presentationData.strings, distance: distance)
|
||||
if let compactDisplayTitle = compactDisplayTitle {
|
||||
text = strongSelf.presentationData.strings.Location_ProximityAlertSetText(compactDisplayTitle, distanceString).0
|
||||
} else {
|
||||
text = strongSelf.presentationData.strings.Location_ProximityAlertSetTextGroup(distanceString).0
|
||||
}
|
||||
|
||||
strongSelf.dismissAllTooltips()
|
||||
strongSelf.present(
|
||||
UndoOverlayController(
|
||||
presentationData: strongSelf.presentationData,
|
||||
content: .setProximityAlert(
|
||||
title: strongSelf.presentationData.strings.Location_ProximityAlertSetTitle,
|
||||
text: text,
|
||||
cancelled: false
|
||||
),
|
||||
elevatedLayout: false,
|
||||
action: { action in
|
||||
return true
|
||||
}
|
||||
),
|
||||
in: .current
|
||||
)
|
||||
})
|
||||
} else {
|
||||
let _ = (context.account.postbox.loadedPeerWithId(subject.id.peerId)
|
||||
|> deliverOnMainQueue).start(next: { peer in
|
||||
@ -293,6 +390,8 @@ public final class LocationViewController: ViewController {
|
||||
|> deliverOnMainQueue).start(next: { coordinate in
|
||||
params.sendLiveLocation(TelegramMediaMap(coordinate: coordinate, liveBroadcastingTimeout: period))
|
||||
})
|
||||
|
||||
strongSelf.controllerNode.showAll()
|
||||
}
|
||||
|
||||
controller.setItemGroups([
|
||||
@ -355,6 +454,15 @@ public final class LocationViewController: ViewController {
|
||||
|
||||
}
|
||||
|
||||
private func dismissAllTooltips() {
|
||||
self.forEachController({ controller in
|
||||
if let controller = controller as? UndoOverlayController {
|
||||
controller.dismissWithCommitAction()
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
override public func loadDisplayNode() {
|
||||
super.loadDisplayNode()
|
||||
guard let interaction = self.interaction else {
|
||||
|
@ -48,7 +48,7 @@ private enum LocationViewEntryId: Hashable {
|
||||
|
||||
private enum LocationViewEntry: Comparable, Identifiable {
|
||||
case info(PresentationTheme, TelegramMediaMap, String?, Double?, Double?)
|
||||
case toggleLiveLocation(PresentationTheme, String, String, CLLocationCoordinate2D?, Double?, Double?)
|
||||
case toggleLiveLocation(PresentationTheme, String, String, Double?, Double?)
|
||||
case liveLocation(PresentationTheme, PresentationDateTimeFormat, PresentationPersonNameOrder, Message, Double?, Int)
|
||||
|
||||
var stableId: LocationViewEntryId {
|
||||
@ -70,8 +70,8 @@ private enum LocationViewEntry: Comparable, Identifiable {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .toggleLiveLocation(lhsTheme, lhsTitle, lhsSubtitle, lhsCoordinate, lhsBeginTimestamp, lhsTimeout):
|
||||
if case let .toggleLiveLocation(rhsTheme, rhsTitle, rhsSubtitle, rhsCoordinate, rhsBeginTimestamp, rhsTimeout) = rhs, lhsTheme === rhsTheme, lhsTitle == rhsTitle, lhsSubtitle == rhsSubtitle, lhsCoordinate == rhsCoordinate, lhsBeginTimestamp == rhsBeginTimestamp, lhsTimeout == rhsTimeout {
|
||||
case let .toggleLiveLocation(lhsTheme, lhsTitle, lhsSubtitle, lhsBeginTimestamp, lhsTimeout):
|
||||
if case let .toggleLiveLocation(rhsTheme, rhsTitle, rhsSubtitle, rhsBeginTimestamp, rhsTimeout) = rhs, lhsTheme === rhsTheme, lhsTitle == rhsTitle, lhsSubtitle == rhsSubtitle, lhsBeginTimestamp == rhsBeginTimestamp, lhsTimeout == rhsTimeout {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -132,7 +132,7 @@ private enum LocationViewEntry: Comparable, Identifiable {
|
||||
}, getDirections: {
|
||||
interaction?.requestDirections()
|
||||
})
|
||||
case let .toggleLiveLocation(_, title, subtitle, coordinate, beginTimstamp, timeout):
|
||||
case let .toggleLiveLocation(_, title, subtitle, beginTimstamp, timeout):
|
||||
let beginTimeAndTimeout: (Double, Double)?
|
||||
if let beginTimstamp = beginTimstamp, let timeout = timeout {
|
||||
beginTimeAndTimeout = (beginTimstamp, timeout)
|
||||
@ -149,7 +149,11 @@ private enum LocationViewEntry: Comparable, Identifiable {
|
||||
interaction?.updateSendActionHighlight(highlight)
|
||||
})
|
||||
case let .liveLocation(_, dateTimeFormat, nameDisplayOrder, message, distance, _):
|
||||
return LocationLiveListItem(presentationData: ItemListPresentationData(presentationData), dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, context: context, message: message, distance: distance, action: {}, longTapAction: {})
|
||||
return LocationLiveListItem(presentationData: ItemListPresentationData(presentationData), dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, context: context, message: message, distance: distance, action: {
|
||||
if let location = getLocation(from: message) {
|
||||
interaction?.goToCoordinate(location.coordinate)
|
||||
}
|
||||
}, longTapAction: {})
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -277,10 +281,10 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
||||
return messages
|
||||
}
|
||||
|
||||
setupProximityNotificationImpl = { [weak self] reset in
|
||||
setupProximityNotificationImpl = { reset in
|
||||
let _ = (liveLocations
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] messages in
|
||||
|> deliverOnMainQueue).start(next: { messages in
|
||||
var ownMessageId: MessageId?
|
||||
for message in messages {
|
||||
if message.localTags.contains(.OutgoingLiveLocation) {
|
||||
@ -369,7 +373,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
||||
|
||||
if let channel = subject.author as? TelegramChannel, case .broadcast = channel.info, activeOwnLiveLocation == nil {
|
||||
} else {
|
||||
entries.append(.toggleLiveLocation(presentationData.theme, title, subtitle, userLocation?.coordinate, beginTime, timeout))
|
||||
entries.append(.toggleLiveLocation(presentationData.theme, title, subtitle, beginTime, timeout))
|
||||
}
|
||||
|
||||
var sortedLiveLocations: [Message] = []
|
||||
@ -409,9 +413,9 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
||||
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)
|
||||
userAnnotation = LocationPinAnnotation(context: context, theme: presentationData.theme, message: message, selfPeer: selfPeer, isSelf: true, heading: location.heading)
|
||||
} else {
|
||||
annotations.append(LocationPinAnnotation(context: context, theme: presentationData.theme, message: message, selfPeer: selfPeer, heading: location.heading))
|
||||
annotations.append(LocationPinAnnotation(context: context, theme: presentationData.theme, message: message, selfPeer: selfPeer, isSelf: message.author?.id == context.account.peerId, heading: location.heading))
|
||||
entries.append(.liveLocation(presentationData.theme, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, message, distance, index))
|
||||
}
|
||||
index += 1
|
||||
@ -420,6 +424,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
||||
|
||||
if let currentProximityNotification = proximityNotification, currentProximityNotification && state.cancellingProximityRadius {
|
||||
proximityNotification = false
|
||||
proximityNotificationRadius = nil
|
||||
} else if let radius = state.updatingProximityRadius {
|
||||
proximityNotification = true
|
||||
proximityNotificationRadius = radius
|
||||
@ -481,7 +486,9 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
||||
|
||||
if !strongSelf.reportedAnnotationsReady {
|
||||
strongSelf.reportedAnnotationsReady = true
|
||||
strongSelf.onAnnotationsReady?()
|
||||
if annotations.count > 0 {
|
||||
strongSelf.onAnnotationsReady?()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -492,7 +499,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
||||
}
|
||||
let rightBarButtonAction: LocationViewRightBarButton
|
||||
if location.liveBroadcastingTimeout != nil {
|
||||
if liveLocations.count > 1 {
|
||||
if annotations.count > 0 {
|
||||
rightBarButtonAction = .showAll
|
||||
} else {
|
||||
rightBarButtonAction = .none
|
||||
@ -551,6 +558,21 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
||||
}
|
||||
}
|
||||
|
||||
self.headerNode.mapNode.annotationSelected = { [weak self] annotation in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if let annotation = annotation {
|
||||
strongSelf.interaction.goToCoordinate(annotation.coordinate)
|
||||
}
|
||||
}
|
||||
|
||||
self.headerNode.mapNode.userLocationAnnotationSelected = { [weak self] in
|
||||
if let strongSelf = self, let location = strongSelf.headerNode.mapNode.currentUserLocation {
|
||||
strongSelf.interaction.goToCoordinate(location.coordinate)
|
||||
}
|
||||
}
|
||||
|
||||
self.locationManager.manager.startUpdatingHeading()
|
||||
self.locationManager.manager.delegate = self
|
||||
}
|
||||
|
@ -38,7 +38,8 @@ private func presentLiveLocationController(context: AccountContext, peerId: Peer
|
||||
}, openUrl: { _ in
|
||||
}, openPeer: { peer, navigation in
|
||||
}, callPeer: { _, _ in
|
||||
}, enqueueMessage: { _ in
|
||||
}, enqueueMessage: { message in
|
||||
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start()
|
||||
}, sendSticker: nil,
|
||||
setupTemporaryHiddenMedia: { _, _, _ in
|
||||
}, chatAvatarHiddenMedia: { _, _ in
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -444,7 +444,9 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
||||
attributedString = nil
|
||||
case let .geoProximityReached(fromId, toId, distance):
|
||||
let distanceString = stringForDistance(strings: strings, distance: Double(distance))
|
||||
if toId == accountPeerId {
|
||||
if fromId == accountPeerId {
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_ProximityYouReached(distanceString, message.peers[toId]?.displayTitle(strings: strings, displayOrder: nameDisplayOrder) ?? ""), body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(1, toId)]))
|
||||
} else if toId == accountPeerId {
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_ProximityReachedYou(message.peers[fromId]?.displayTitle(strings: strings, displayOrder: nameDisplayOrder) ?? "", distanceString), body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, fromId)]))
|
||||
} else {
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_ProximityReached(message.peers[fromId]?.displayTitle(strings: strings, displayOrder: nameDisplayOrder) ?? "", distanceString, message.peers[toId]?.displayTitle(strings: strings, displayOrder: nameDisplayOrder) ?? ""), body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, fromId), (2, toId)]))
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -829,7 +829,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
|
||||
wasCheck = true
|
||||
}
|
||||
|
||||
if isAudio && !isVoice {
|
||||
if isAudio && !isVoice && !isSending {
|
||||
state = .play
|
||||
} else {
|
||||
if message.groupingKey != nil, adjustedProgress.isEqual(to: 1.0), (message.flags.contains(.Unsent) || wasCheck) {
|
||||
|
@ -21,6 +21,7 @@ public enum UndoOverlayContent {
|
||||
case chatAddedToFolder(chatTitle: String, folderTitle: String)
|
||||
case chatRemovedFromFolder(chatTitle: String, folderTitle: String)
|
||||
case messagesUnpinned(title: String, text: String, undo: Bool, isHidden: Bool)
|
||||
case setProximityAlert(title: String, text: String, cancelled: Bool)
|
||||
}
|
||||
|
||||
public enum UndoOverlayAction {
|
||||
|
@ -221,7 +221,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
||||
}
|
||||
|
||||
displayUndo = undo
|
||||
self.originalRemainingSeconds = undo ? 5 : 5
|
||||
self.originalRemainingSeconds = 5
|
||||
case let .emoji(path, text):
|
||||
self.iconNode = nil
|
||||
self.iconCheckNode = nil
|
||||
@ -388,6 +388,23 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
||||
}
|
||||
})
|
||||
}
|
||||
case let .setProximityAlert(title, text, cancelled):
|
||||
self.iconNode = nil
|
||||
self.iconCheckNode = nil
|
||||
self.animationNode = AnimationNode(animation: cancelled ? "anim_proximity_cancelled" : "anim_proximity_set", colors: [:], scale: 0.45)
|
||||
self.animatedStickerNode = nil
|
||||
|
||||
let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white)
|
||||
let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white)
|
||||
let link = MarkdownAttributeSet(font: Font.regular(14.0), textColor: undoTextColor)
|
||||
let attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: body, bold: bold, link: link, linkAttribute: { _ in return nil }), textAlignment: .natural)
|
||||
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(14.0), textColor: .white)
|
||||
if !text.isEmpty {
|
||||
self.textNode.attributedText = attributedText
|
||||
}
|
||||
|
||||
displayUndo = false
|
||||
self.originalRemainingSeconds = 3
|
||||
}
|
||||
|
||||
self.remainingSeconds = self.originalRemainingSeconds
|
||||
@ -416,7 +433,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
||||
switch content {
|
||||
case .removedChat:
|
||||
self.panelWrapperNode.addSubnode(self.timerTextNode)
|
||||
case .archivedChat, .hidArchive, .revealedArchive, .succeed, .emoji, .swipeToReply, .actionSucceeded, .stickersModified, .chatAddedToFolder, .chatRemovedFromFolder, .messagesUnpinned:
|
||||
case .archivedChat, .hidArchive, .revealedArchive, .succeed, .emoji, .swipeToReply, .actionSucceeded, .stickersModified, .chatAddedToFolder, .chatRemovedFromFolder, .messagesUnpinned, .setProximityAlert:
|
||||
break
|
||||
case .dice:
|
||||
self.panelWrapperNode.clipsToBounds = true
|
||||
|
Loading…
x
Reference in New Issue
Block a user