mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge commit 'c8734c772831162743e0db48e6cb89d2bacdfc45'
This commit is contained in:
commit
87addfef2a
@ -5873,3 +5873,7 @@ Any member of this group will be able to see messages in the channel.";
|
|||||||
|
|
||||||
"Conversation.PinMessagesForMe" = "Pin for me";
|
"Conversation.PinMessagesForMe" = "Pin for me";
|
||||||
"Conversation.PinMessagesFor" = "Pin for me and %@";
|
"Conversation.PinMessagesFor" = "Pin for me and %@";
|
||||||
|
|
||||||
|
"Location.LiveLocationRequired.Title" = "Share Location";
|
||||||
|
"Location.LiveLocationRequired.Description" = "For the alert to work, please share your live location in this chat.";
|
||||||
|
"Location.LiveLocationRequired.ShareLocation" = "Share Location";
|
||||||
|
@ -397,16 +397,19 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
|
func pickerView(_ pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {
|
||||||
|
let font = Font.regular(17.0)
|
||||||
|
let string: String
|
||||||
if component == 0 {
|
if component == 0 {
|
||||||
let value = unitValues[row]
|
let value = unitValues[row]
|
||||||
return "\(value)"
|
string = "\(value)"
|
||||||
} else if component == 1 {
|
} else if component == 1 {
|
||||||
let value = String(format: "%.2d", smallUnitValues[row])
|
let value = String(format: "%.2d", smallUnitValues[row])
|
||||||
return ".\(value)"
|
string = ".\(value)"
|
||||||
} else {
|
} else {
|
||||||
return self.usesMetricSystem() ? self.presentationData.strings.Location_ProximityNotification_DistanceKM : self.presentationData.strings.Location_ProximityNotification_DistanceMI
|
string = self.usesMetricSystem() ? self.presentationData.strings.Location_ProximityNotification_DistanceKM : self.presentationData.strings.Location_ProximityNotification_DistanceMI
|
||||||
}
|
}
|
||||||
|
return NSAttributedString(string: string, font: font, textColor: self.presentationData.theme.actionSheet.primaryTextColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
func updatePresentationData(_ presentationData: PresentationData) {
|
func updatePresentationData(_ presentationData: PresentationData) {
|
||||||
@ -431,6 +434,8 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||||||
|
|
||||||
self.cancelButton.setTitle(self.presentationData.strings.Common_Cancel, with: Font.regular(17.0), with: self.presentationData.theme.actionSheet.controlAccentColor, for: .normal)
|
self.cancelButton.setTitle(self.presentationData.strings.Common_Cancel, with: Font.regular(17.0), with: self.presentationData.theme.actionSheet.controlAccentColor, for: .normal)
|
||||||
self.doneButton.updateTheme(SolidRoundedButtonTheme(theme: self.presentationData.theme))
|
self.doneButton.updateTheme(SolidRoundedButtonTheme(theme: self.presentationData.theme))
|
||||||
|
|
||||||
|
self.updateDoneButtonTitle()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func didLoad() {
|
override func didLoad() {
|
||||||
|
241
submodules/LocationUI/Sources/LocationLiveListItem.swift
Normal file
241
submodules/LocationUI/Sources/LocationLiveListItem.swift
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
import AsyncDisplayKit
|
||||||
|
import Postbox
|
||||||
|
import Display
|
||||||
|
import SwiftSignalKit
|
||||||
|
import TelegramCore
|
||||||
|
import SyncCore
|
||||||
|
import TelegramPresentationData
|
||||||
|
import ItemListUI
|
||||||
|
import LocationResources
|
||||||
|
import AppBundle
|
||||||
|
import AvatarNode
|
||||||
|
import LiveLocationTimerNode
|
||||||
|
|
||||||
|
final class LocationLiveListItem: ListViewItem {
|
||||||
|
let presentationData: ItemListPresentationData
|
||||||
|
let account: Account
|
||||||
|
let message: Message
|
||||||
|
let distance: Double?
|
||||||
|
let action: () -> Void
|
||||||
|
let longTapAction: () -> Void
|
||||||
|
|
||||||
|
public init(presentationData: ItemListPresentationData, account: Account, message: Message, distance: Double?, action: @escaping () -> Void, longTapAction: @escaping () -> Void = { }) {
|
||||||
|
self.presentationData = presentationData
|
||||||
|
self.account = account
|
||||||
|
self.message = message
|
||||||
|
self.distance = distance
|
||||||
|
self.action = action
|
||||||
|
self.longTapAction = longTapAction
|
||||||
|
}
|
||||||
|
|
||||||
|
public func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void)) -> Void) {
|
||||||
|
async {
|
||||||
|
let node = LocationLiveListItemNode()
|
||||||
|
let makeLayout = node.asyncLayout()
|
||||||
|
let (nodeLayout, nodeApply) = makeLayout(self, params, nextItem is LocationLiveListItem)
|
||||||
|
node.contentSize = nodeLayout.contentSize
|
||||||
|
node.insets = nodeLayout.insets
|
||||||
|
|
||||||
|
completion(node, nodeApply)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func updateNode(async: @escaping (@escaping () -> Void) -> Void, node: @escaping () -> ListViewItemNode, params: ListViewItemLayoutParams, previousItem: ListViewItem?, nextItem: ListViewItem?, animation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNodeLayout, @escaping (ListViewItemApply) -> Void) -> Void) {
|
||||||
|
Queue.mainQueue().async {
|
||||||
|
if let nodeValue = node() as? LocationLiveListItemNode {
|
||||||
|
let layout = nodeValue.asyncLayout()
|
||||||
|
async {
|
||||||
|
let (nodeLayout, apply) = layout(self, params, nextItem is LocationLiveListItem)
|
||||||
|
Queue.mainQueue().async {
|
||||||
|
completion(nodeLayout, { info in
|
||||||
|
apply().1(info)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public var selectable: Bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
public func selected(listView: ListView) {
|
||||||
|
listView.clearHighlightAnimated(false)
|
||||||
|
self.action()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private let avatarFont = avatarPlaceholderFont(size: floor(40.0 * 16.0 / 37.0))
|
||||||
|
final class LocationLiveListItemNode: ListViewItemNode {
|
||||||
|
private let backgroundNode: ASDisplayNode
|
||||||
|
private let separatorNode: ASDisplayNode
|
||||||
|
private let highlightedBackgroundNode: ASDisplayNode
|
||||||
|
private var titleNode: TextNode?
|
||||||
|
private var subtitleNode: TextNode?
|
||||||
|
private let avatarNode: AvatarNode
|
||||||
|
private var timerNode: ChatMessageLiveLocationTimerNode?
|
||||||
|
|
||||||
|
private var item: LocationLiveListItem?
|
||||||
|
private var layoutParams: ListViewItemLayoutParams?
|
||||||
|
|
||||||
|
required init() {
|
||||||
|
self.backgroundNode = ASDisplayNode()
|
||||||
|
self.backgroundNode.isLayerBacked = true
|
||||||
|
|
||||||
|
self.separatorNode = ASDisplayNode()
|
||||||
|
self.separatorNode.isLayerBacked = true
|
||||||
|
|
||||||
|
self.highlightedBackgroundNode = ASDisplayNode()
|
||||||
|
self.highlightedBackgroundNode.isLayerBacked = true
|
||||||
|
|
||||||
|
self.avatarNode = AvatarNode(font: avatarFont)
|
||||||
|
|
||||||
|
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
|
||||||
|
|
||||||
|
self.addSubnode(self.backgroundNode)
|
||||||
|
self.addSubnode(self.separatorNode)
|
||||||
|
self.addSubnode(self.avatarNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func layoutForParams(_ params: ListViewItemLayoutParams, item: ListViewItem, previousItem: ListViewItem?, nextItem: ListViewItem?) {
|
||||||
|
if let item = self.item {
|
||||||
|
let makeLayout = self.asyncLayout()
|
||||||
|
let (nodeLayout, nodeApply) = makeLayout(item, params, nextItem is LocationLiveListItem)
|
||||||
|
self.contentSize = nodeLayout.contentSize
|
||||||
|
self.insets = nodeLayout.insets
|
||||||
|
let _ = nodeApply()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func setHighlighted(_ highlighted: Bool, at point: CGPoint, animated: Bool) {
|
||||||
|
super.setHighlighted(highlighted, at: point, animated: animated)
|
||||||
|
|
||||||
|
if highlighted {
|
||||||
|
self.highlightedBackgroundNode.alpha = 1.0
|
||||||
|
if self.highlightedBackgroundNode.supernode == nil {
|
||||||
|
self.insertSubnode(self.highlightedBackgroundNode, aboveSubnode: self.separatorNode)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if self.highlightedBackgroundNode.supernode != nil {
|
||||||
|
if animated {
|
||||||
|
self.highlightedBackgroundNode.layer.animateAlpha(from: self.highlightedBackgroundNode.alpha, to: 0.0, duration: 0.4, completion: { [weak self] completed in
|
||||||
|
if let strongSelf = self {
|
||||||
|
if completed {
|
||||||
|
strongSelf.highlightedBackgroundNode.removeFromSupernode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
self.highlightedBackgroundNode.alpha = 0.0
|
||||||
|
} else {
|
||||||
|
self.highlightedBackgroundNode.removeFromSupernode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func asyncLayout() -> (_ item: LocationLiveListItem, _ params: ListViewItemLayoutParams, _ hasSeparator: Bool) -> (ListViewItemNodeLayout, () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void)) {
|
||||||
|
let currentItem = self.item
|
||||||
|
|
||||||
|
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
||||||
|
let makeSubtitleLayout = TextNode.asyncLayout(self.subtitleNode)
|
||||||
|
|
||||||
|
return { [weak self] item, params, hasSeparator in
|
||||||
|
let leftInset: CGFloat = 65.0 + params.leftInset
|
||||||
|
let rightInset: CGFloat = params.rightInset
|
||||||
|
let verticalInset: CGFloat = 8.0
|
||||||
|
let iconSize: CGFloat = 40.0
|
||||||
|
|
||||||
|
let titleFont = Font.medium(item.presentationData.fontSize.itemListBaseFontSize)
|
||||||
|
let subtitleFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 14.0 / 17.0))
|
||||||
|
|
||||||
|
let titleAttributedString = NSAttributedString(string: "title", font: titleFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor)
|
||||||
|
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - rightInset - 15.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
|
||||||
|
let subtitleAttributedString = NSAttributedString(string: "subtitle", font: subtitleFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||||
|
let (subtitleLayout, subtitleApply) = makeSubtitleLayout(TextNodeLayoutArguments(attributedString: subtitleAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - rightInset - 15.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
|
||||||
|
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)
|
||||||
|
let nodeLayout = ListViewItemNodeLayout(contentSize: contentSize, insets: UIEdgeInsets())
|
||||||
|
|
||||||
|
return (nodeLayout, { [weak self] in
|
||||||
|
var updatedTheme: PresentationTheme?
|
||||||
|
if currentItem?.presentationData.theme !== item.presentationData.theme {
|
||||||
|
updatedTheme = item.presentationData.theme
|
||||||
|
}
|
||||||
|
|
||||||
|
return (nil, { _ in
|
||||||
|
if let strongSelf = self {
|
||||||
|
strongSelf.item = item
|
||||||
|
strongSelf.layoutParams = params
|
||||||
|
|
||||||
|
if let _ = updatedTheme {
|
||||||
|
strongSelf.separatorNode.backgroundColor = item.presentationData.theme.list.itemPlainSeparatorColor
|
||||||
|
strongSelf.backgroundNode.backgroundColor = item.presentationData.theme.list.plainBackgroundColor
|
||||||
|
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||||
|
}
|
||||||
|
|
||||||
|
let titleNode = titleApply()
|
||||||
|
if strongSelf.titleNode == nil {
|
||||||
|
strongSelf.titleNode = titleNode
|
||||||
|
strongSelf.addSubnode(titleNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
let subtitleNode = subtitleApply()
|
||||||
|
if strongSelf.subtitleNode == nil {
|
||||||
|
strongSelf.subtitleNode = subtitleNode
|
||||||
|
strongSelf.addSubnode(subtitleNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
let titleFrame = CGRect(origin: CGPoint(x: leftInset, y: verticalInset), size: titleLayout.size)
|
||||||
|
titleNode.frame = titleFrame
|
||||||
|
|
||||||
|
let subtitleFrame = CGRect(origin: CGPoint(x: leftInset, y: verticalInset + titleLayout.size.height + titleSpacing), size: subtitleLayout.size)
|
||||||
|
subtitleNode.frame = subtitleFrame
|
||||||
|
|
||||||
|
let separatorHeight = UIScreenPixel
|
||||||
|
let topHighlightInset: CGFloat = separatorHeight
|
||||||
|
|
||||||
|
// let iconNodeFrame = CGRect(origin: CGPoint(x: params.leftInset + 15.0, y: floorToScreenPixels((contentSize.height - bottomInset - iconSize) / 2.0)), size: CGSize(width: iconSize, height: iconSize))
|
||||||
|
// strongSelf.iconNode.frame = iconNodeFrame
|
||||||
|
// strongSelf.venueIconNode.frame = iconNodeFrame
|
||||||
|
|
||||||
|
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))
|
||||||
|
strongSelf.separatorNode.isHidden = !hasSeparator
|
||||||
|
|
||||||
|
// if let (beginTimestamp, timeout) = item.beginTimeAndTimeout {
|
||||||
|
// let timerNode: ChatMessageLiveLocationTimerNode
|
||||||
|
// if let current = strongSelf.timerNode {
|
||||||
|
// timerNode = current
|
||||||
|
// } else {
|
||||||
|
// timerNode = ChatMessageLiveLocationTimerNode()
|
||||||
|
// strongSelf.addSubnode(timerNode)
|
||||||
|
// strongSelf.timerNode = timerNode
|
||||||
|
// }
|
||||||
|
// let timerSize = CGSize(width: 28.0, height: 28.0)
|
||||||
|
// timerNode.update(backgroundColor: item.presentationData.theme.list.itemAccentColor.withAlphaComponent(0.4), foregroundColor: item.presentationData.theme.list.itemAccentColor, textColor: item.presentationData.theme.list.itemAccentColor, beginTimestamp: beginTimestamp, timeout: timeout, strings: item.presentationData.strings)
|
||||||
|
// timerNode.frame = CGRect(origin: CGPoint(x: contentSize.width - 16.0 - timerSize.width, y: floorToScreenPixels((contentSize.height - timerSize.height) / 2.0) - 2.0), size: timerSize)
|
||||||
|
// } else if let timerNode = strongSelf.timerNode {
|
||||||
|
// strongSelf.timerNode = nil
|
||||||
|
// timerNode.removeFromSupernode()
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) {
|
||||||
|
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration * 0.5)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func animateRemoved(_ currentTimestamp: Double, duration: Double) {
|
||||||
|
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration * 0.5, removeOnCompletion: false)
|
||||||
|
}
|
||||||
|
}
|
@ -45,6 +45,8 @@ final class LocationMapHeaderNode: ASDisplayNode {
|
|||||||
private var proximityNotification: Bool?
|
private var proximityNotification: Bool?
|
||||||
|
|
||||||
let mapNode: LocationMapNode
|
let mapNode: LocationMapNode
|
||||||
|
var trackingMode: LocationTrackingMode = .none
|
||||||
|
|
||||||
private let optionsBackgroundNode: ASImageNode
|
private let optionsBackgroundNode: ASImageNode
|
||||||
private let optionsSeparatorNode: ASDisplayNode
|
private let optionsSeparatorNode: ASDisplayNode
|
||||||
private let optionsSecondSeparatorNode: ASDisplayNode
|
private let optionsSecondSeparatorNode: ASDisplayNode
|
||||||
@ -129,11 +131,14 @@ final class LocationMapHeaderNode: ASDisplayNode {
|
|||||||
self.placesButtonNode.addTarget(self, action: #selector(self.placesPressed), forControlEvents: .touchUpInside)
|
self.placesButtonNode.addTarget(self, action: #selector(self.placesPressed), forControlEvents: .touchUpInside)
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateState(mapMode: LocationMapMode, displayingMapModeOptions: Bool, displayingPlacesButton: Bool, proximityNotification: Bool?, animated: Bool) {
|
func updateState(mapMode: LocationMapMode, trackingMode: LocationTrackingMode, displayingMapModeOptions: Bool, displayingPlacesButton: Bool, proximityNotification: Bool?, animated: Bool) {
|
||||||
self.mapNode.mapMode = mapMode
|
self.mapNode.mapMode = mapMode
|
||||||
|
self.trackingMode = trackingMode
|
||||||
self.infoButtonNode.isSelected = displayingMapModeOptions
|
self.infoButtonNode.isSelected = displayingMapModeOptions
|
||||||
self.notificationButtonNode.isSelected = proximityNotification ?? false
|
self.notificationButtonNode.isSelected = proximityNotification ?? false
|
||||||
|
|
||||||
|
self.locationButtonNode.setImage(generateTintedImage(image: self.iconForTracking(), color: self.presentationData.theme.rootController.navigationBar.buttonColor), for: .normal)
|
||||||
|
|
||||||
let updateLayout = self.displayingPlacesButton != displayingPlacesButton || self.proximityNotification != proximityNotification
|
let updateLayout = self.displayingPlacesButton != displayingPlacesButton || self.proximityNotification != proximityNotification
|
||||||
self.displayingPlacesButton = displayingPlacesButton
|
self.displayingPlacesButton = displayingPlacesButton
|
||||||
self.proximityNotification = proximityNotification
|
self.proximityNotification = proximityNotification
|
||||||
@ -153,7 +158,7 @@ final class LocationMapHeaderNode: ASDisplayNode {
|
|||||||
self.infoButtonNode.setImage(generateTintedImage(image: UIImage(bundleImageName: "Location/InfoIcon"), color: presentationData.theme.rootController.navigationBar.buttonColor), for: .normal)
|
self.infoButtonNode.setImage(generateTintedImage(image: UIImage(bundleImageName: "Location/InfoIcon"), color: presentationData.theme.rootController.navigationBar.buttonColor), for: .normal)
|
||||||
self.infoButtonNode.setImage(generateTintedImage(image: UIImage(bundleImageName: "Location/InfoActiveIcon"), color: presentationData.theme.rootController.navigationBar.buttonColor), for: .selected)
|
self.infoButtonNode.setImage(generateTintedImage(image: UIImage(bundleImageName: "Location/InfoActiveIcon"), color: presentationData.theme.rootController.navigationBar.buttonColor), for: .selected)
|
||||||
self.infoButtonNode.setImage(generateTintedImage(image: UIImage(bundleImageName: "Location/InfoActiveIcon"), color: presentationData.theme.rootController.navigationBar.buttonColor), for: [.selected, .highlighted])
|
self.infoButtonNode.setImage(generateTintedImage(image: UIImage(bundleImageName: "Location/InfoActiveIcon"), color: presentationData.theme.rootController.navigationBar.buttonColor), for: [.selected, .highlighted])
|
||||||
self.locationButtonNode.setImage(generateTintedImage(image: UIImage(bundleImageName: "Location/TrackIcon"), color: presentationData.theme.rootController.navigationBar.buttonColor), for: .normal)
|
self.locationButtonNode.setImage(generateTintedImage(image: self.iconForTracking(), color: presentationData.theme.rootController.navigationBar.buttonColor), for: .normal)
|
||||||
self.notificationButtonNode.setImage(generateTintedImage(image: UIImage(bundleImageName: "Location/NotificationIcon"), color: presentationData.theme.rootController.navigationBar.buttonColor), for: .normal)
|
self.notificationButtonNode.setImage(generateTintedImage(image: UIImage(bundleImageName: "Location/NotificationIcon"), color: presentationData.theme.rootController.navigationBar.buttonColor), for: .normal)
|
||||||
self.notificationButtonNode.setImage(generateTintedImage(image: UIImage(bundleImageName: "Chat/Title Panels/MuteIcon"), color: presentationData.theme.rootController.navigationBar.buttonColor), for: .selected)
|
self.notificationButtonNode.setImage(generateTintedImage(image: UIImage(bundleImageName: "Chat/Title Panels/MuteIcon"), color: presentationData.theme.rootController.navigationBar.buttonColor), for: .selected)
|
||||||
self.notificationButtonNode.setImage(generateTintedImage(image: UIImage(bundleImageName: "Chat/Title Panels/MuteIcon"), color: presentationData.theme.rootController.navigationBar.buttonColor), for: [.selected, .highlighted])
|
self.notificationButtonNode.setImage(generateTintedImage(image: UIImage(bundleImageName: "Chat/Title Panels/MuteIcon"), color: presentationData.theme.rootController.navigationBar.buttonColor), for: [.selected, .highlighted])
|
||||||
@ -161,6 +166,17 @@ final class LocationMapHeaderNode: ASDisplayNode {
|
|||||||
self.shadowNode.image = generateShadowImage(theme: presentationData.theme, highlighted: false)
|
self.shadowNode.image = generateShadowImage(theme: presentationData.theme, highlighted: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func iconForTracking() -> UIImage? {
|
||||||
|
switch self.trackingMode {
|
||||||
|
case .none:
|
||||||
|
return UIImage(bundleImageName: "Location/TrackIcon")
|
||||||
|
case .follow:
|
||||||
|
return UIImage(bundleImageName: "Location/TrackActiveIcon")
|
||||||
|
case .followWithHeading:
|
||||||
|
return UIImage(bundleImageName: "Location/TrackHeadingIcon")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func updateLayout(layout: ContainerViewLayout, navigationBarHeight: CGFloat, topPadding: CGFloat, offset: CGFloat, size: CGSize, transition: ContainedViewLayoutTransition) {
|
func updateLayout(layout: ContainerViewLayout, navigationBarHeight: CGFloat, topPadding: CGFloat, offset: CGFloat, size: CGSize, transition: ContainedViewLayoutTransition) {
|
||||||
self.validLayout = (layout, navigationBarHeight, topPadding, offset, size)
|
self.validLayout = (layout, navigationBarHeight, topPadding, offset, size)
|
||||||
|
|
||||||
|
@ -26,6 +26,23 @@ public enum LocationMapMode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum LocationTrackingMode {
|
||||||
|
case none
|
||||||
|
case follow
|
||||||
|
case followWithHeading
|
||||||
|
|
||||||
|
var userTrackingMode: MKUserTrackingMode {
|
||||||
|
switch self {
|
||||||
|
case .follow:
|
||||||
|
return .follow
|
||||||
|
case .followWithHeading:
|
||||||
|
return .followWithHeading
|
||||||
|
default:
|
||||||
|
return .none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class PickerAnnotationContainerView: UIView {
|
private class PickerAnnotationContainerView: UIView {
|
||||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||||
let result = super.hitTest(point, with: event)
|
let result = super.hitTest(point, with: event)
|
||||||
@ -352,6 +369,12 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var trackingMode: LocationTrackingMode = .none {
|
||||||
|
didSet {
|
||||||
|
self.mapView?.userTrackingMode = self.trackingMode.userTrackingMode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func setMapCenter(coordinate: CLLocationCoordinate2D, span: MKCoordinateSpan = defaultMapSpan, offset: CGPoint = CGPoint(), isUserLocation: Bool = false, hidePicker: Bool = false, animated: Bool = false) {
|
func setMapCenter(coordinate: CLLocationCoordinate2D, span: MKCoordinateSpan = defaultMapSpan, offset: CGPoint = CGPoint(), isUserLocation: Bool = false, hidePicker: Bool = false, animated: Bool = false) {
|
||||||
let region = MKCoordinateRegion(center: coordinate, span: span)
|
let region = MKCoordinateRegion(center: coordinate, span: span)
|
||||||
self.ignoreRegionChanges = true
|
self.ignoreRegionChanges = true
|
||||||
|
@ -569,7 +569,7 @@ final class LocationPickerControllerNode: ViewControllerTracingNode, CLLocationM
|
|||||||
strongSelf.headerNode.mapNode.setMapCenter(coordinate: venue.coordinate, hidePicker: true, animated: true)
|
strongSelf.headerNode.mapNode.setMapCenter(coordinate: venue.coordinate, hidePicker: true, animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.headerNode.updateState(mapMode: state.mapMode, displayingMapModeOptions: state.displayingMapModeOptions, displayingPlacesButton: displayingPlacesButton, proximityNotification: nil, animated: true)
|
strongSelf.headerNode.updateState(mapMode: state.mapMode, trackingMode: .none, displayingMapModeOptions: state.displayingMapModeOptions, displayingPlacesButton: displayingPlacesButton, proximityNotification: nil, animated: true)
|
||||||
|
|
||||||
let annotations: [LocationPinAnnotation]
|
let annotations: [LocationPinAnnotation]
|
||||||
if let venues = displayedVenues {
|
if let venues = displayedVenues {
|
||||||
|
@ -38,7 +38,7 @@ enum LocationViewRightBarButton {
|
|||||||
class LocationViewInteraction {
|
class LocationViewInteraction {
|
||||||
let toggleMapModeSelection: () -> Void
|
let toggleMapModeSelection: () -> Void
|
||||||
let updateMapMode: (LocationMapMode) -> Void
|
let updateMapMode: (LocationMapMode) -> Void
|
||||||
let goToUserLocation: () -> Void
|
let toggleTrackingMode: () -> Void
|
||||||
let goToCoordinate: (CLLocationCoordinate2D) -> Void
|
let goToCoordinate: (CLLocationCoordinate2D) -> Void
|
||||||
let requestDirections: () -> Void
|
let requestDirections: () -> Void
|
||||||
let share: () -> Void
|
let share: () -> Void
|
||||||
@ -49,10 +49,10 @@ class LocationViewInteraction {
|
|||||||
let updateRightBarButton: (LocationViewRightBarButton) -> Void
|
let updateRightBarButton: (LocationViewRightBarButton) -> Void
|
||||||
let present: (ViewController) -> Void
|
let present: (ViewController) -> 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, present: @escaping (ViewController) -> Void) {
|
init(toggleMapModeSelection: @escaping () -> Void, updateMapMode: @escaping (LocationMapMode) -> Void, toggleTrackingMode: @escaping () -> Void, goToCoordinate: @escaping (CLLocationCoordinate2D) -> Void, requestDirections: @escaping () -> Void, share: @escaping () -> Void, setupProximityNotification: @escaping (Bool, CLLocationCoordinate2D?, MessageId?) -> Void, updateSendActionHighlight: @escaping (Bool) -> Void, sendLiveLocation: @escaping (CLLocationCoordinate2D, Int32?) -> Void, stopLiveLocation: @escaping () -> Void, updateRightBarButton: @escaping (LocationViewRightBarButton) -> Void, present: @escaping (ViewController) -> Void) {
|
||||||
self.toggleMapModeSelection = toggleMapModeSelection
|
self.toggleMapModeSelection = toggleMapModeSelection
|
||||||
self.updateMapMode = updateMapMode
|
self.updateMapMode = updateMapMode
|
||||||
self.goToUserLocation = goToUserLocation
|
self.toggleTrackingMode = toggleTrackingMode
|
||||||
self.goToCoordinate = goToCoordinate
|
self.goToCoordinate = goToCoordinate
|
||||||
self.requestDirections = requestDirections
|
self.requestDirections = requestDirections
|
||||||
self.share = share
|
self.share = share
|
||||||
@ -129,14 +129,21 @@ public final class LocationViewController: ViewController {
|
|||||||
state.displayingMapModeOptions = false
|
state.displayingMapModeOptions = false
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
}, goToUserLocation: { [weak self] in
|
}, toggleTrackingMode: { [weak self] in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
strongSelf.controllerNode.updateState { state in
|
strongSelf.controllerNode.updateState { state in
|
||||||
var state = state
|
var state = state
|
||||||
state.displayingMapModeOptions = false
|
state.displayingMapModeOptions = false
|
||||||
state.selectedLocation = .user
|
switch state.trackingMode {
|
||||||
|
case .none:
|
||||||
|
state.trackingMode = .follow
|
||||||
|
case .follow:
|
||||||
|
state.trackingMode = .followWithHeading
|
||||||
|
case .followWithHeading:
|
||||||
|
state.trackingMode = .none
|
||||||
|
}
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
}, goToCoordinate: { [weak self] coordinate in
|
}, goToCoordinate: { [weak self] coordinate in
|
||||||
@ -191,7 +198,10 @@ public final class LocationViewController: ViewController {
|
|||||||
if let messageId = messageId {
|
if let messageId = messageId {
|
||||||
let _ = requestEditLiveLocation(postbox: context.account.postbox, network: context.account.network, stateManager: context.account.stateManager, messageId: messageId, stop: false, coordinate: nil, heading: nil, proximityNotificationRadius: distance).start()
|
let _ = requestEditLiveLocation(postbox: context.account.postbox, network: context.account.network, stateManager: context.account.stateManager, messageId: messageId, stop: false, coordinate: nil, heading: nil, proximityNotificationRadius: distance).start()
|
||||||
} else if let coordinate = coordinate {
|
} else if let coordinate = coordinate {
|
||||||
strongSelf.interaction?.sendLiveLocation(coordinate, distance)
|
strongSelf.present(textAlertController(context: strongSelf.context, title: strongSelf.presentationData.strings.Location_LiveLocationRequired_Title, text: strongSelf.presentationData.strings.Location_LiveLocationRequired_Description, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Location_LiveLocationRequired_ShareLocation, action: {
|
||||||
|
completion()
|
||||||
|
strongSelf.interaction?.sendLiveLocation(coordinate, distance)
|
||||||
|
}), TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {})], actionLayout: .vertical), in: .window(.root))
|
||||||
}
|
}
|
||||||
completion()
|
completion()
|
||||||
}, willDismiss: { [weak self] in
|
}, willDismiss: { [weak self] in
|
||||||
|
@ -154,7 +154,7 @@ private enum LocationViewEntry: Comparable, Identifiable {
|
|||||||
} else {
|
} else {
|
||||||
distanceString = nil
|
distanceString = nil
|
||||||
}
|
}
|
||||||
return ItemListTextItem(presentationData: ItemListPresentationData(presentationData), text: .plain(""), sectionId: 0)
|
return LocationLiveListItem(presentationData: ItemListPresentationData(presentationData), account: account, message: message, distance: distance, action: {}, longTapAction: {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -180,11 +180,13 @@ struct LocationViewState {
|
|||||||
var mapMode: LocationMapMode
|
var mapMode: LocationMapMode
|
||||||
var displayingMapModeOptions: Bool
|
var displayingMapModeOptions: Bool
|
||||||
var selectedLocation: LocationViewLocation
|
var selectedLocation: LocationViewLocation
|
||||||
|
var trackingMode: LocationTrackingMode
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
self.mapMode = .map
|
self.mapMode = .map
|
||||||
self.displayingMapModeOptions = false
|
self.displayingMapModeOptions = false
|
||||||
self.selectedLocation = .initial
|
self.selectedLocation = .initial
|
||||||
|
self.trackingMode = .none
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,7 +231,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
|||||||
self.listNode.verticalScrollIndicatorFollowsOverscroll = true
|
self.listNode.verticalScrollIndicatorFollowsOverscroll = true
|
||||||
|
|
||||||
var setupProximityNotificationImpl: ((Bool) -> Void)?
|
var setupProximityNotificationImpl: ((Bool) -> Void)?
|
||||||
self.headerNode = LocationMapHeaderNode(presentationData: presentationData, toggleMapModeSelection: interaction.toggleMapModeSelection, goToUserLocation: interaction.goToUserLocation, setupProximityNotification: { reset in
|
self.headerNode = LocationMapHeaderNode(presentationData: presentationData, toggleMapModeSelection: interaction.toggleMapModeSelection, goToUserLocation: interaction.toggleTrackingMode, setupProximityNotification: { reset in
|
||||||
setupProximityNotificationImpl?(reset)
|
setupProximityNotificationImpl?(reset)
|
||||||
})
|
})
|
||||||
self.headerNode.mapNode.isRotateEnabled = false
|
self.headerNode.mapNode.isRotateEnabled = false
|
||||||
@ -399,7 +401,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
|||||||
|
|
||||||
let subjectLocation = CLLocation(latitude: location.latitude, longitude: location.longitude)
|
let subjectLocation = CLLocation(latitude: location.latitude, longitude: location.longitude)
|
||||||
let distance = userLocation.flatMap { subjectLocation.distance(from: $0) }
|
let distance = userLocation.flatMap { subjectLocation.distance(from: $0) }
|
||||||
entries.append(.liveLocation(presentationData.theme, message, distance, index))
|
// entries.append(.liveLocation(presentationData.theme, message, distance, index))
|
||||||
|
|
||||||
if message.localTags.contains(.OutgoingLiveLocation), let selfPeer = selfPeer {
|
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, heading: location.heading)
|
||||||
@ -419,7 +421,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
|||||||
let transition = preparedTransition(from: previousEntries ?? [], to: entries, account: context.account, presentationData: presentationData, interaction: strongSelf.interaction)
|
let transition = preparedTransition(from: previousEntries ?? [], to: entries, account: context.account, presentationData: presentationData, interaction: strongSelf.interaction)
|
||||||
strongSelf.enqueueTransition(transition)
|
strongSelf.enqueueTransition(transition)
|
||||||
|
|
||||||
strongSelf.headerNode.updateState(mapMode: state.mapMode, displayingMapModeOptions: state.displayingMapModeOptions, displayingPlacesButton: false, proximityNotification: proximityNotification, animated: false)
|
strongSelf.headerNode.updateState(mapMode: state.mapMode, trackingMode: state.trackingMode, displayingMapModeOptions: state.displayingMapModeOptions, displayingPlacesButton: false, proximityNotification: proximityNotification, animated: false)
|
||||||
|
|
||||||
if let proximityNotification = proximityNotification, !proximityNotification && !strongSelf.displayedProximityAlertTooltip {
|
if let proximityNotification = proximityNotification, !proximityNotification && !strongSelf.displayedProximityAlertTooltip {
|
||||||
strongSelf.displayedProximityAlertTooltip = true
|
strongSelf.displayedProximityAlertTooltip = true
|
||||||
@ -450,7 +452,8 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
|||||||
case .custom:
|
case .custom:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
strongSelf.headerNode.mapNode.trackingMode = state.trackingMode
|
||||||
|
|
||||||
let previousAnnotations = previousAnnotations.swap(annotations)
|
let previousAnnotations = previousAnnotations.swap(annotations)
|
||||||
let previousUserAnnotation = previousUserAnnotation.swap(userAnnotation)
|
let previousUserAnnotation = previousUserAnnotation.swap(userAnnotation)
|
||||||
if (userAnnotation == nil) != (previousUserAnnotation == nil) {
|
if (userAnnotation == nil) != (previousUserAnnotation == nil) {
|
||||||
@ -521,6 +524,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
|||||||
var state = state
|
var state = state
|
||||||
state.displayingMapModeOptions = false
|
state.displayingMapModeOptions = false
|
||||||
state.selectedLocation = .custom
|
state.selectedLocation = .custom
|
||||||
|
state.trackingMode = .none
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -593,6 +597,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
|||||||
self.updateState { state in
|
self.updateState { state in
|
||||||
var state = state
|
var state = state
|
||||||
state.selectedLocation = .coordinate(coordinate, true)
|
state.selectedLocation = .coordinate(coordinate, true)
|
||||||
|
state.trackingMode = .none
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -604,6 +609,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
|||||||
self.updateState { state in
|
self.updateState { state in
|
||||||
var state = state
|
var state = state
|
||||||
state.selectedLocation = .user
|
state.selectedLocation = .user
|
||||||
|
state.trackingMode = .none
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -704,10 +704,10 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[1984136919] = { return Api.wallet.LiteResponse.parse_liteResponse($0) }
|
dict[1984136919] = { return Api.wallet.LiteResponse.parse_liteResponse($0) }
|
||||||
dict[415997816] = { return Api.help.InviteText.parse_inviteText($0) }
|
dict[415997816] = { return Api.help.InviteText.parse_inviteText($0) }
|
||||||
dict[-1937807902] = { return Api.BotInlineMessage.parse_botInlineMessageText($0) }
|
dict[-1937807902] = { return Api.BotInlineMessage.parse_botInlineMessageText($0) }
|
||||||
dict[-1222451611] = { return Api.BotInlineMessage.parse_botInlineMessageMediaGeo($0) }
|
|
||||||
dict[1984755728] = { return Api.BotInlineMessage.parse_botInlineMessageMediaAuto($0) }
|
dict[1984755728] = { return Api.BotInlineMessage.parse_botInlineMessageMediaAuto($0) }
|
||||||
dict[-1970903652] = { return Api.BotInlineMessage.parse_botInlineMessageMediaVenue($0) }
|
dict[-1970903652] = { return Api.BotInlineMessage.parse_botInlineMessageMediaVenue($0) }
|
||||||
dict[416402882] = { return Api.BotInlineMessage.parse_botInlineMessageMediaContact($0) }
|
dict[416402882] = { return Api.BotInlineMessage.parse_botInlineMessageMediaContact($0) }
|
||||||
|
dict[85477117] = { return Api.BotInlineMessage.parse_botInlineMessageMediaGeo($0) }
|
||||||
dict[-1673717362] = { return Api.InputPeerNotifySettings.parse_inputPeerNotifySettings($0) }
|
dict[-1673717362] = { return Api.InputPeerNotifySettings.parse_inputPeerNotifySettings($0) }
|
||||||
dict[-1634752813] = { return Api.messages.FavedStickers.parse_favedStickersNotModified($0) }
|
dict[-1634752813] = { return Api.messages.FavedStickers.parse_favedStickersNotModified($0) }
|
||||||
dict[-209768682] = { return Api.messages.FavedStickers.parse_favedStickers($0) }
|
dict[-209768682] = { return Api.messages.FavedStickers.parse_favedStickers($0) }
|
||||||
|
@ -19971,10 +19971,10 @@ public extension Api {
|
|||||||
}
|
}
|
||||||
public enum BotInlineMessage: TypeConstructorDescription {
|
public enum BotInlineMessage: TypeConstructorDescription {
|
||||||
case botInlineMessageText(flags: Int32, message: String, entities: [Api.MessageEntity]?, replyMarkup: Api.ReplyMarkup?)
|
case botInlineMessageText(flags: Int32, message: String, entities: [Api.MessageEntity]?, replyMarkup: Api.ReplyMarkup?)
|
||||||
case botInlineMessageMediaGeo(flags: Int32, geo: Api.GeoPoint, period: Int32, replyMarkup: Api.ReplyMarkup?)
|
|
||||||
case botInlineMessageMediaAuto(flags: Int32, message: String, entities: [Api.MessageEntity]?, replyMarkup: Api.ReplyMarkup?)
|
case botInlineMessageMediaAuto(flags: Int32, message: String, entities: [Api.MessageEntity]?, replyMarkup: Api.ReplyMarkup?)
|
||||||
case botInlineMessageMediaVenue(flags: Int32, geo: Api.GeoPoint, title: String, address: String, provider: String, venueId: String, venueType: String, replyMarkup: Api.ReplyMarkup?)
|
case botInlineMessageMediaVenue(flags: Int32, geo: Api.GeoPoint, title: String, address: String, provider: String, venueId: String, venueType: String, replyMarkup: Api.ReplyMarkup?)
|
||||||
case botInlineMessageMediaContact(flags: Int32, phoneNumber: String, firstName: String, lastName: String, vcard: String, replyMarkup: Api.ReplyMarkup?)
|
case botInlineMessageMediaContact(flags: Int32, phoneNumber: String, firstName: String, lastName: String, vcard: String, replyMarkup: Api.ReplyMarkup?)
|
||||||
|
case botInlineMessageMediaGeo(flags: Int32, geo: Api.GeoPoint, heading: Int32?, period: Int32?, proximityNotificationRadius: Int32?, replyMarkup: Api.ReplyMarkup?)
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
@ -19991,15 +19991,6 @@ public extension Api {
|
|||||||
}}
|
}}
|
||||||
if Int(flags) & Int(1 << 2) != 0 {replyMarkup!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 2) != 0 {replyMarkup!.serialize(buffer, true)}
|
||||||
break
|
break
|
||||||
case .botInlineMessageMediaGeo(let flags, let geo, let period, let replyMarkup):
|
|
||||||
if boxed {
|
|
||||||
buffer.appendInt32(-1222451611)
|
|
||||||
}
|
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
|
||||||
geo.serialize(buffer, true)
|
|
||||||
serializeInt32(period, buffer: buffer, boxed: false)
|
|
||||||
if Int(flags) & Int(1 << 2) != 0 {replyMarkup!.serialize(buffer, true)}
|
|
||||||
break
|
|
||||||
case .botInlineMessageMediaAuto(let flags, let message, let entities, let replyMarkup):
|
case .botInlineMessageMediaAuto(let flags, let message, let entities, let replyMarkup):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(1984755728)
|
buffer.appendInt32(1984755728)
|
||||||
@ -20037,6 +20028,17 @@ public extension Api {
|
|||||||
serializeString(vcard, buffer: buffer, boxed: false)
|
serializeString(vcard, buffer: buffer, boxed: false)
|
||||||
if Int(flags) & Int(1 << 2) != 0 {replyMarkup!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 2) != 0 {replyMarkup!.serialize(buffer, true)}
|
||||||
break
|
break
|
||||||
|
case .botInlineMessageMediaGeo(let flags, let geo, let heading, let period, let proximityNotificationRadius, let replyMarkup):
|
||||||
|
if boxed {
|
||||||
|
buffer.appendInt32(85477117)
|
||||||
|
}
|
||||||
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
|
geo.serialize(buffer, true)
|
||||||
|
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(heading!, buffer: buffer, boxed: false)}
|
||||||
|
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(period!, buffer: buffer, boxed: false)}
|
||||||
|
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(proximityNotificationRadius!, buffer: buffer, boxed: false)}
|
||||||
|
if Int(flags) & Int(1 << 2) != 0 {replyMarkup!.serialize(buffer, true)}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20044,14 +20046,14 @@ public extension Api {
|
|||||||
switch self {
|
switch self {
|
||||||
case .botInlineMessageText(let flags, let message, let entities, let replyMarkup):
|
case .botInlineMessageText(let flags, let message, let entities, let replyMarkup):
|
||||||
return ("botInlineMessageText", [("flags", flags), ("message", message), ("entities", entities), ("replyMarkup", replyMarkup)])
|
return ("botInlineMessageText", [("flags", flags), ("message", message), ("entities", entities), ("replyMarkup", replyMarkup)])
|
||||||
case .botInlineMessageMediaGeo(let flags, let geo, let period, let replyMarkup):
|
|
||||||
return ("botInlineMessageMediaGeo", [("flags", flags), ("geo", geo), ("period", period), ("replyMarkup", replyMarkup)])
|
|
||||||
case .botInlineMessageMediaAuto(let flags, let message, let entities, let replyMarkup):
|
case .botInlineMessageMediaAuto(let flags, let message, let entities, let replyMarkup):
|
||||||
return ("botInlineMessageMediaAuto", [("flags", flags), ("message", message), ("entities", entities), ("replyMarkup", replyMarkup)])
|
return ("botInlineMessageMediaAuto", [("flags", flags), ("message", message), ("entities", entities), ("replyMarkup", replyMarkup)])
|
||||||
case .botInlineMessageMediaVenue(let flags, let geo, let title, let address, let provider, let venueId, let venueType, let replyMarkup):
|
case .botInlineMessageMediaVenue(let flags, let geo, let title, let address, let provider, let venueId, let venueType, let replyMarkup):
|
||||||
return ("botInlineMessageMediaVenue", [("flags", flags), ("geo", geo), ("title", title), ("address", address), ("provider", provider), ("venueId", venueId), ("venueType", venueType), ("replyMarkup", replyMarkup)])
|
return ("botInlineMessageMediaVenue", [("flags", flags), ("geo", geo), ("title", title), ("address", address), ("provider", provider), ("venueId", venueId), ("venueType", venueType), ("replyMarkup", replyMarkup)])
|
||||||
case .botInlineMessageMediaContact(let flags, let phoneNumber, let firstName, let lastName, let vcard, let replyMarkup):
|
case .botInlineMessageMediaContact(let flags, let phoneNumber, let firstName, let lastName, let vcard, let replyMarkup):
|
||||||
return ("botInlineMessageMediaContact", [("flags", flags), ("phoneNumber", phoneNumber), ("firstName", firstName), ("lastName", lastName), ("vcard", vcard), ("replyMarkup", replyMarkup)])
|
return ("botInlineMessageMediaContact", [("flags", flags), ("phoneNumber", phoneNumber), ("firstName", firstName), ("lastName", lastName), ("vcard", vcard), ("replyMarkup", replyMarkup)])
|
||||||
|
case .botInlineMessageMediaGeo(let flags, let geo, let heading, let period, let proximityNotificationRadius, let replyMarkup):
|
||||||
|
return ("botInlineMessageMediaGeo", [("flags", flags), ("geo", geo), ("heading", heading), ("period", period), ("proximityNotificationRadius", proximityNotificationRadius), ("replyMarkup", replyMarkup)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20079,30 +20081,6 @@ public extension Api {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static func parse_botInlineMessageMediaGeo(_ reader: BufferReader) -> BotInlineMessage? {
|
|
||||||
var _1: Int32?
|
|
||||||
_1 = reader.readInt32()
|
|
||||||
var _2: Api.GeoPoint?
|
|
||||||
if let signature = reader.readInt32() {
|
|
||||||
_2 = Api.parse(reader, signature: signature) as? Api.GeoPoint
|
|
||||||
}
|
|
||||||
var _3: Int32?
|
|
||||||
_3 = reader.readInt32()
|
|
||||||
var _4: Api.ReplyMarkup?
|
|
||||||
if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() {
|
|
||||||
_4 = Api.parse(reader, signature: signature) as? Api.ReplyMarkup
|
|
||||||
} }
|
|
||||||
let _c1 = _1 != nil
|
|
||||||
let _c2 = _2 != nil
|
|
||||||
let _c3 = _3 != nil
|
|
||||||
let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil
|
|
||||||
if _c1 && _c2 && _c3 && _c4 {
|
|
||||||
return Api.BotInlineMessage.botInlineMessageMediaGeo(flags: _1!, geo: _2!, period: _3!, replyMarkup: _4)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static func parse_botInlineMessageMediaAuto(_ reader: BufferReader) -> BotInlineMessage? {
|
public static func parse_botInlineMessageMediaAuto(_ reader: BufferReader) -> BotInlineMessage? {
|
||||||
var _1: Int32?
|
var _1: Int32?
|
||||||
_1 = reader.readInt32()
|
_1 = reader.readInt32()
|
||||||
@ -20191,6 +20169,36 @@ public extension Api {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public static func parse_botInlineMessageMediaGeo(_ reader: BufferReader) -> BotInlineMessage? {
|
||||||
|
var _1: Int32?
|
||||||
|
_1 = reader.readInt32()
|
||||||
|
var _2: Api.GeoPoint?
|
||||||
|
if let signature = reader.readInt32() {
|
||||||
|
_2 = Api.parse(reader, signature: signature) as? Api.GeoPoint
|
||||||
|
}
|
||||||
|
var _3: Int32?
|
||||||
|
if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() }
|
||||||
|
var _4: Int32?
|
||||||
|
if Int(_1!) & Int(1 << 1) != 0 {_4 = reader.readInt32() }
|
||||||
|
var _5: Int32?
|
||||||
|
if Int(_1!) & Int(1 << 3) != 0 {_5 = reader.readInt32() }
|
||||||
|
var _6: Api.ReplyMarkup?
|
||||||
|
if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() {
|
||||||
|
_6 = Api.parse(reader, signature: signature) as? Api.ReplyMarkup
|
||||||
|
} }
|
||||||
|
let _c1 = _1 != nil
|
||||||
|
let _c2 = _2 != nil
|
||||||
|
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
|
||||||
|
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
|
||||||
|
let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil
|
||||||
|
let _c6 = (Int(_1!) & Int(1 << 2) == 0) || _6 != nil
|
||||||
|
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||||
|
return Api.BotInlineMessage.botInlineMessageMediaGeo(flags: _1!, geo: _2!, heading: _3, period: _4, proximityNotificationRadius: _5, replyMarkup: _6)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public enum InputPeerNotifySettings: TypeConstructorDescription {
|
public enum InputPeerNotifySettings: TypeConstructorDescription {
|
||||||
|
@ -423,8 +423,8 @@ extension ChatContextResultMessage {
|
|||||||
parsedReplyMarkup = ReplyMarkupMessageAttribute(apiMarkup: replyMarkup)
|
parsedReplyMarkup = ReplyMarkupMessageAttribute(apiMarkup: replyMarkup)
|
||||||
}
|
}
|
||||||
self = .text(text: message, entities: parsedEntities, disableUrlPreview: (flags & (1 << 0)) != 0, replyMarkup: parsedReplyMarkup)
|
self = .text(text: message, entities: parsedEntities, disableUrlPreview: (flags & (1 << 0)) != 0, replyMarkup: parsedReplyMarkup)
|
||||||
case let .botInlineMessageMediaGeo(_, geo, period, replyMarkup):
|
case let .botInlineMessageMediaGeo(_, geo, heading, period, proximityNotificationRadius, replyMarkup):
|
||||||
let media = telegramMediaMapFromApiGeoPoint(geo, title: nil, address: nil, provider: nil, venueId: nil, venueType: nil, liveBroadcastingTimeout: period, liveProximityNotificationRadius: nil, heading: nil)
|
let media = telegramMediaMapFromApiGeoPoint(geo, title: nil, address: nil, provider: nil, venueId: nil, venueType: nil, liveBroadcastingTimeout: period, liveProximityNotificationRadius: proximityNotificationRadius, heading: heading)
|
||||||
var parsedReplyMarkup: ReplyMarkupMessageAttribute?
|
var parsedReplyMarkup: ReplyMarkupMessageAttribute?
|
||||||
if let replyMarkup = replyMarkup {
|
if let replyMarkup = replyMarkup {
|
||||||
parsedReplyMarkup = ReplyMarkupMessageAttribute(apiMarkup: replyMarkup)
|
parsedReplyMarkup = ReplyMarkupMessageAttribute(apiMarkup: replyMarkup)
|
||||||
|
File diff suppressed because it is too large
Load Diff
12
submodules/TelegramUI/Images.xcassets/Location/TrackActiveIcon.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Location/TrackActiveIcon.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "ic_gps_filled.pdf",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
submodules/TelegramUI/Images.xcassets/Location/TrackActiveIcon.imageset/ic_gps_filled.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Location/TrackActiveIcon.imageset/ic_gps_filled.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Location/TrackHeadingIcon.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Location/TrackHeadingIcon.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "ic_gps_2.pdf",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
submodules/TelegramUI/Images.xcassets/Location/TrackHeadingIcon.imageset/ic_gps_2.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Location/TrackHeadingIcon.imageset/ic_gps_2.pdf
vendored
Normal file
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user