This commit is contained in:
Ilya Laktyushin 2020-02-11 19:41:59 +04:00
parent 97fd1d10f0
commit 801b26f157
11 changed files with 253 additions and 71 deletions

Binary file not shown.

View File

@ -7,7 +7,7 @@ private let leftFadeImage = generateImage(CGSize(width: 64.0, height: 1.0), opaq
let bounds = CGRect(origin: CGPoint(), size: size)
context.clear(bounds)
let gradientColors = [UIColor.black.withAlphaComponent(0.5).cgColor, UIColor.black.withAlphaComponent(0.0).cgColor] as CFArray
let gradientColors = [UIColor.black.withAlphaComponent(0.35).cgColor, UIColor.black.withAlphaComponent(0.0).cgColor] as CFArray
var locations: [CGFloat] = [0.0, 1.0]
let colorSpace = CGColorSpaceCreateDeviceRGB()
@ -20,7 +20,7 @@ private let rightFadeImage = generateImage(CGSize(width: 64.0, height: 1.0), opa
let bounds = CGRect(origin: CGPoint(), size: size)
context.clear(bounds)
let gradientColors = [UIColor.black.withAlphaComponent(0.0).cgColor, UIColor.black.withAlphaComponent(0.5).cgColor] as CFArray
let gradientColors = [UIColor.black.withAlphaComponent(0.0).cgColor, UIColor.black.withAlphaComponent(0.35).cgColor] as CFArray
var locations: [CGFloat] = [0.0, 1.0]
let colorSpace = CGColorSpaceCreateDeviceRGB()
@ -63,12 +63,12 @@ open class ZoomableContentGalleryItemNode: GalleryItemNode, UIScrollViewDelegate
self.leftFadeNode = ASImageNode()
self.leftFadeNode.contentMode = .scaleToFill
self.leftFadeNode.image = leftFadeImage
self.leftFadeNode.isHidden = true
self.leftFadeNode.alpha = 0.0
self.rightFadeNode = ASImageNode()
self.rightFadeNode.contentMode = .scaleToFill
self.rightFadeNode.image = rightFadeImage
self.rightFadeNode.isHidden = true
self.rightFadeNode.alpha = 0.0
super.init()
@ -90,21 +90,21 @@ open class ZoomableContentGalleryItemNode: GalleryItemNode, UIScrollViewDelegate
}
tapRecognizer.highlight = { [weak self] location in
if let strongSelf = self {
let transition: ContainedViewLayoutTransition = .animated(duration: 0.07, curve: .easeInOut)
if let location = location, location.x < 44.0 {
strongSelf.leftFadeNode.isHidden = false
transition.updateAlpha(node: strongSelf.leftFadeNode, alpha: 1.0)
} else {
strongSelf.leftFadeNode.isHidden = true
transition.updateAlpha(node: strongSelf.leftFadeNode, alpha: 0.0)
}
if let location = location, location.x > strongSelf.frame.width - 44.0 {
strongSelf.rightFadeNode.isHidden = false
transition.updateAlpha(node: strongSelf.rightFadeNode, alpha: 1.0)
} else {
strongSelf.rightFadeNode.isHidden = true
transition.updateAlpha(node: strongSelf.rightFadeNode, alpha: 0.0)
}
}
}
self.scrollNode.view.addGestureRecognizer(tapRecognizer)
self.addSubnode(self.scrollNode)
self.addSubnode(self.leftFadeNode)
@ -114,9 +114,10 @@ open class ZoomableContentGalleryItemNode: GalleryItemNode, UIScrollViewDelegate
@objc open func contentTap(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) {
if recognizer.state == .ended {
if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation {
if location.x < 44.0 {
let pointInNode = self.scrollNode.view.convert(location, to: self.view)
if pointInNode.x < 44.0 {
self.goToPreviousItem()
} else if location.x > self.frame.width - 44.0 {
} else if pointInNode.x > self.frame.width - 44.0 {
self.goToNextItem()
} else {
switch gesture {
@ -159,8 +160,9 @@ open class ZoomableContentGalleryItemNode: GalleryItemNode, UIScrollViewDelegate
}
self.containerLayout = layout
self.leftFadeNode.frame = CGRect(x: 0.0, y: 0.0, width: layout.size.width * 0.2, height: layout.size.height)
self.rightFadeNode.frame = CGRect(x: layout.size.width - layout.size.width * 0.2, y: 0.0, width: layout.size.width * 0.2, height: layout.size.height)
let fadeWidth = min(72.0, layout.size.width * 0.2)
self.leftFadeNode.frame = CGRect(x: 0.0, y: 0.0, width: fadeWidth, height: layout.size.height)
self.rightFadeNode.frame = CGRect(x: layout.size.width - fadeWidth, y: 0.0, width: fadeWidth, height: layout.size.height)
if shouldResetContents {
var previousFrame: CGRect?

View File

@ -24,6 +24,8 @@ import ContextUI
import TelegramNotices
import TelegramStringFormatting
private let maxUsersDisplayedLimit: Int32 = 5
private struct PeerNearbyEntry {
let peer: (Peer, CachedPeerData?)
let expires: Int32
@ -57,14 +59,16 @@ private final class PeersNearbyControllerArguments {
let openChat: (Peer) -> Void
let openCreateGroup: (Double, Double, String?) -> Void
let contextAction: (Peer, ASDisplayNode, ContextGesture?) -> Void
let expandUsers: () -> Void
init(context: AccountContext, toggleVisibility: @escaping (Bool) -> Void, openProfile: @escaping (Peer) -> Void, openChat: @escaping (Peer) -> Void, openCreateGroup: @escaping (Double, Double, String?) -> Void, contextAction: @escaping (Peer, ASDisplayNode, ContextGesture?) -> Void) {
init(context: AccountContext, toggleVisibility: @escaping (Bool) -> Void, openProfile: @escaping (Peer) -> Void, openChat: @escaping (Peer) -> Void, openCreateGroup: @escaping (Double, Double, String?) -> Void, contextAction: @escaping (Peer, ASDisplayNode, ContextGesture?) -> Void, expandUsers: @escaping () -> Void) {
self.context = context
self.toggleVisibility = toggleVisibility
self.openProfile = openProfile
self.openChat = openChat
self.openCreateGroup = openCreateGroup
self.contextAction = contextAction
self.expandUsers = expandUsers
}
}
@ -82,6 +86,7 @@ private enum PeersNearbyEntry: ItemListNodeEntry {
case empty(PresentationTheme, String)
case visibility(PresentationTheme, String, Bool)
case user(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, PeerNearbyEntry)
case expand(PresentationTheme, String)
case groupsHeader(PresentationTheme, String, Bool)
case createGroup(PresentationTheme, String, Double?, Double?, String?)
@ -94,7 +99,7 @@ private enum PeersNearbyEntry: ItemListNodeEntry {
switch self {
case .header:
return PeersNearbySection.header.rawValue
case .usersHeader, .empty, .visibility, .user:
case .usersHeader, .empty, .visibility, .user, .expand:
return PeersNearbySection.users.rawValue
case .groupsHeader, .createGroup, .group:
return PeersNearbySection.groups.rawValue
@ -115,12 +120,14 @@ private enum PeersNearbyEntry: ItemListNodeEntry {
return 3
case let .user(index, _, _, _, _, _):
return 4 + index
case .groupsHeader:
case .expand:
return 1000
case .createGroup:
case .groupsHeader:
return 1001
case .createGroup:
return 1002
case let .group(index, _, _, _, _, _):
return 1002 + index
return 1003 + index
case .channelsHeader:
return 2000
case let .channel(index, _, _, _, _, _):
@ -161,6 +168,12 @@ private enum PeersNearbyEntry: ItemListNodeEntry {
} else {
return false
}
case let .expand(lhsTheme, lhsText):
if case let .expand(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .groupsHeader(lhsTheme, lhsText, lhsLoading):
if case let .groupsHeader(rhsTheme, rhsText, rhsLoading) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsLoading == rhsLoading {
return true
@ -224,14 +237,19 @@ private enum PeersNearbyEntry: ItemListNodeEntry {
})
case let .user(_, theme, strings, dateTimeFormat, nameDisplayOrder, peer):
var text = strings.Map_DistanceAway(stringForDistance(peer.distance)).0
if peer.peer.0.id == arguments.context.account.peerId {
let isSelfPeer = peer.peer.0.id == arguments.context.account.peerId
if isSelfPeer {
text = strings.PeopleNearby_VisibleUntil(humanReadableStringForTimestamp(strings: strings, dateTimeFormat: dateTimeFormat, timestamp: peer.expires)).0
}
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, context: arguments.context, peer: peer.peer.0, aliasHandling: .standard, nameColor: .primary, nameStyle: .distinctBold, presence: nil, text: .text(strings.Map_DistanceAway(stringForDistance(peer.distance)).0), label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: {
arguments.openProfile(peer.peer.0)
}, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }, toggleUpdated: nil, contextAction: { node, gesture in
arguments.contextAction(peer.peer.0, node, gesture)
}, hasTopGroupInset: false, tag: nil)
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, context: arguments.context, peer: peer.peer.0, aliasHandling: .standard, nameColor: .primary, nameStyle: .distinctBold, presence: nil, text: .text(text), label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, selectable: !isSelfPeer, sectionId: self.section, action: {
if !isSelfPeer {
arguments.openProfile(peer.peer.0)
}
}, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }, toggleUpdated: nil, contextAction: nil, hasTopGroupInset: false, tag: nil)
case let .expand(theme, title):
return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.downArrowImage(theme), title: title, sectionId: self.section, editing: false, action: {
arguments.expandUsers()
})
case let .groupsHeader(theme, text, loading):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, activityIndicator: loading ? .left : .none, sectionId: self.section)
case let .createGroup(theme, title, latitude, longitude, address):
@ -294,7 +312,7 @@ private struct PeersNearbyData: Equatable {
}
}
private func peersNearbyControllerEntries(data: PeersNearbyData?, presentationData: PresentationData, displayLoading: Bool) -> [PeersNearbyEntry] {
private func peersNearbyControllerEntries(data: PeersNearbyData?, presentationData: PresentationData, displayLoading: Bool, expanded: Bool) -> [PeersNearbyEntry] {
var entries: [PeersNearbyEntry] = []
entries.append(.header(presentationData.theme, presentationData.strings.PeopleNearby_DiscoverDescription))
@ -305,10 +323,22 @@ private func peersNearbyControllerEntries(data: PeersNearbyData?, presentationDa
if let data = data, !data.users.isEmpty {
var i: Int32 = 0
for user in data.users {
var users = data.users
var effectiveExpanded = expanded
if users.count > maxUsersDisplayedLimit && !expanded {
users = Array(users.prefix(Int(maxUsersDisplayedLimit)))
} else {
effectiveExpanded = true
}
for user in users {
entries.append(.user(i, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, user))
i += 1
}
if !effectiveExpanded {
entries.append(.expand(presentationData.theme, presentationData.strings.PeopleNearby_ShowMorePeople(Int32(data.users.count) - maxUsersDisplayedLimit)))
}
}
entries.append(.groupsHeader(presentationData.theme, presentationData.strings.PeopleNearby_Groups.uppercased(), displayLoading && data == nil))
@ -429,6 +459,9 @@ public func peersNearbyController(context: AccountContext) -> ViewController {
let dataPromise = Promise<PeersNearbyData?>(nil)
let addressPromise = Promise<String?>(nil)
let visibilityPromise = ValuePromise<Bool>(true)
let expandedPromise = ValuePromise<Bool>(false)
let coordinatePromise = Promise<CLLocationCoordinate2D?>(nil)
coordinatePromise.set(.single(nil) |> then(currentLocationManagerCoordinate(manager: context.sharedContext.locationManager!, timeout: 5.0)))
@ -440,12 +473,16 @@ public func peersNearbyController(context: AccountContext) -> ViewController {
let _ = (coordinatePromise.get()
|> deliverOnMainQueue).start(next: { coordinate in
if let coordinate = coordinate {
let _ = peersNearbyUpdateVisibility(network: context.account.network, stateManager: context.account.stateManager, update: .visible(latitude: coordinate.latitude, longitude: coordinate.longitude), background: false).start()
let _ = peersNearbyUpdateVisibility(account: context.account, update: .visible(latitude: coordinate.latitude, longitude: coordinate.longitude), background: false).start()
}
})
})]), nil)
visibilityPromise.set(true)
} else {
let _ = peersNearbyUpdateVisibility(network: context.account.network, stateManager: context.account.stateManager, update: .invisible, background: false).start()
let _ = peersNearbyUpdateVisibility(account: context.account, update: .invisible, background: false).start()
visibilityPromise.set(false)
}
}, openProfile: { peer in
navigateToProfileImpl?(peer)
@ -498,6 +535,8 @@ public func peersNearbyController(context: AccountContext) -> ViewController {
presentControllerImpl?(c, nil)
}), reactionItems: [], gesture: gesture)
presentInGlobalOverlayImpl?(contextController)
}, expandUsers: {
expandedPromise.set(true)
})
let dataSignal: Signal<PeersNearbyData?, NoError> = coordinatePromise.get()
@ -569,9 +608,9 @@ public func peersNearbyController(context: AccountContext) -> ViewController {
|> delay(1.0, queue: Queue.mainQueue())
)
let signal = combineLatest(context.sharedContext.presentationData, dataPromise.get(), displayLoading)
let signal = combineLatest(context.sharedContext.presentationData, dataPromise.get(), displayLoading, visibilityPromise.get(), expandedPromise.get())
|> deliverOnMainQueue
|> map { presentationData, data, displayLoading -> (ItemListControllerState, (ItemListNodeState, Any)) in
|> map { presentationData, data, displayLoading, visibility, expanded -> (ItemListControllerState, (ItemListNodeState, Any)) in
let previous = previousData.swap(data)
var crossfade = false
@ -583,7 +622,7 @@ public func peersNearbyController(context: AccountContext) -> ViewController {
}
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.PeopleNearby_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: peersNearbyControllerEntries(data: data, presentationData: presentationData, displayLoading: displayLoading), style: .blocks, emptyStateItem: nil, crossfadeState: crossfade, animateChanges: !crossfade)
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: peersNearbyControllerEntries(data: data, presentationData: presentationData, displayLoading: displayLoading, expanded: expanded), style: .blocks, emptyStateItem: nil, crossfadeState: crossfade, animateChanges: !crossfade)
return (controllerState, (listState, arguments))
}
@ -596,7 +635,7 @@ public func peersNearbyController(context: AccountContext) -> ViewController {
controller?.clearItemNodesHighlight(animated: true)
}
navigateToProfileImpl = { [weak controller] peer in
if let navigationController = controller?.navigationController as? NavigationController, let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: true) {
if let navigationController = controller?.navigationController as? NavigationController, let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false) {
(navigationController as? NavigationController)?.pushViewController(controller)
}
}

View File

@ -197,6 +197,7 @@ private enum PreferencesKeyValues: Int32 {
case walletCollection = 18
case contentSettings = 19
case chatListFilters = 20
case peersNearby = 21
}
public func applicationSpecificPreferencesKey(_ value: Int32) -> ValueBoxKey {
@ -313,6 +314,12 @@ public struct PreferencesKeys {
key.setInt32(0, value: PreferencesKeyValues.chatListFilters.rawValue)
return key
}()
public static let peersNearby: ValueBoxKey = {
let key = ValueBoxKey(length: 4)
key.setInt32(0, value: PreferencesKeyValues.peersNearby.rawValue)
return key
}()
}
private enum SharedDataKeyValues: Int32 {

View File

@ -561,6 +561,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1739392570] = { return Api.DocumentAttribute.parse_documentAttributeAudio($0) }
dict[358154344] = { return Api.DocumentAttribute.parse_documentAttributeFilename($0) }
dict[-1744710921] = { return Api.DocumentAttribute.parse_documentAttributeHasStickers($0) }
dict[-177732982] = { return Api.BankCardOpenUrl.parse_bankCardOpenUrl($0) }
dict[307276766] = { return Api.account.Authorizations.parse_authorizations($0) }
dict[935395612] = { return Api.ChatPhoto.parse_chatPhotoEmpty($0) }
dict[1197267925] = { return Api.ChatPhoto.parse_chatPhoto($0) }
@ -818,7 +819,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1707344487] = { return Api.messages.HighScores.parse_highScores($0) }
dict[-892779534] = { return Api.WebAuthorization.parse_webAuthorization($0) }
dict[-805141448] = { return Api.ImportedContact.parse_importedContact($0) }
dict[-419239361] = { return Api.payments.BankCardData.parse_bankCardData($0) }
dict[1042605427] = { return Api.payments.BankCardData.parse_bankCardData($0) }
return dict
}()
@ -1238,6 +1239,8 @@ public struct Api {
_1.serialize(buffer, boxed)
case let _1 as Api.DocumentAttribute:
_1.serialize(buffer, boxed)
case let _1 as Api.BankCardOpenUrl:
_1.serialize(buffer, boxed)
case let _1 as Api.account.Authorizations:
_1.serialize(buffer, boxed)
case let _1 as Api.ChatPhoto:

View File

@ -15952,6 +15952,44 @@ public extension Api {
return Api.DocumentAttribute.documentAttributeHasStickers
}
}
public enum BankCardOpenUrl: TypeConstructorDescription {
case bankCardOpenUrl(url: String, name: String)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .bankCardOpenUrl(let url, let name):
if boxed {
buffer.appendInt32(-177732982)
}
serializeString(url, buffer: buffer, boxed: false)
serializeString(name, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .bankCardOpenUrl(let url, let name):
return ("bankCardOpenUrl", [("url", url), ("name", name)])
}
}
public static func parse_bankCardOpenUrl(_ reader: BufferReader) -> BankCardOpenUrl? {
var _1: String?
_1 = parseString(reader)
var _2: String?
_2 = parseString(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.BankCardOpenUrl.bankCardOpenUrl(url: _1!, name: _2!)
}
else {
return nil
}
}
}
public enum ChatPhoto: TypeConstructorDescription {
case chatPhotoEmpty

View File

@ -491,44 +491,42 @@ public struct payments {
}
public enum BankCardData: TypeConstructorDescription {
case bankCardData(flags: Int32, title: String, url: String?, urlName: String?)
case bankCardData(title: String, openUrls: [Api.BankCardOpenUrl])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .bankCardData(let flags, let title, let url, let urlName):
case .bankCardData(let title, let openUrls):
if boxed {
buffer.appendInt32(-419239361)
buffer.appendInt32(1042605427)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(title, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeString(url!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 0) != 0 {serializeString(urlName!, buffer: buffer, boxed: false)}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(openUrls.count))
for item in openUrls {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .bankCardData(let flags, let title, let url, let urlName):
return ("bankCardData", [("flags", flags), ("title", title), ("url", url), ("urlName", urlName)])
case .bankCardData(let title, let openUrls):
return ("bankCardData", [("title", title), ("openUrls", openUrls)])
}
}
public static func parse_bankCardData(_ reader: BufferReader) -> BankCardData? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: String?
if Int(_1!) & Int(1 << 0) != 0 {_3 = parseString(reader) }
var _4: String?
if Int(_1!) & Int(1 << 0) != 0 {_4 = parseString(reader) }
var _1: String?
_1 = parseString(reader)
var _2: [Api.BankCardOpenUrl]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.BankCardOpenUrl.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.payments.BankCardData.bankCardData(flags: _1!, title: _2!, url: _3, urlName: _4)
if _c1 && _c2 {
return Api.payments.BankCardData.bankCardData(title: _1!, openUrls: _2!)
}
else {
return nil

View File

@ -3263,6 +3263,33 @@ public extension Api {
})
}
}
public static func inputMediaDice() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.InputMedia>) {
let buffer = Buffer()
buffer.appendInt32(-1358977017)
return (FunctionDescription(name: "inputMediaDice", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.InputMedia? in
let reader = BufferReader(buffer)
var result: Api.InputMedia?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.InputMedia
}
return result
})
}
public static func messageMediaDice(value: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.MessageMedia>) {
let buffer = Buffer()
buffer.appendInt32(1670374507)
serializeInt32(value, buffer: buffer, boxed: false)
return (FunctionDescription(name: "messageMediaDice", parameters: [("value", value)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.MessageMedia? in
let reader = BufferReader(buffer)
var result: Api.MessageMedia?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.MessageMedia
}
return result
})
}
public struct channels {
public static func readHistory(channel: Api.InputChannel, maxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
let buffer = Buffer()

View File

@ -2,33 +2,58 @@ import Foundation
import Postbox
import TelegramApi
import SyncCore
import MtProtoKit
import SwiftSignalKit
public struct BankCardUrl {
public let title: String
public let url: String
}
public struct BankCardInfo {
public let title: String
public let url: String?
public let actionTitle: String?
public let urls: [BankCardUrl]
}
public func getBankCardInfo(account: Account, cardNumber: String) -> Signal<BankCardInfo?, NoError> {
return account.network.request(Api.functions.payments.getBankCardData(number: cardNumber))
|> map { result -> BankCardInfo? in
return BankCardInfo(apiBankCardData: result)
return currentWebDocumentsHostDatacenterId(postbox: account.postbox, isTestingEnvironment: false)
|> mapToSignal { datacenterId in
let signal: Signal<Api.payments.BankCardData, MTRpcError>
if account.network.datacenterId != datacenterId {
signal = account.network.download(datacenterId: Int(datacenterId), isMedia: false, tag: nil)
|> castError(MTRpcError.self)
|> mapToSignal { worker in
return worker.request(Api.functions.payments.getBankCardData(number: cardNumber))
}
} else {
signal = account.network.request(Api.functions.payments.getBankCardData(number: cardNumber))
}
return signal
|> map { result -> BankCardInfo? in
return BankCardInfo(apiBankCardData: result)
}
|> `catch` { _ -> Signal<BankCardInfo?, NoError> in
return .single(nil)
}
}
|> `catch` { _ -> Signal<BankCardInfo?, NoError> in
return .single(nil)
}
extension BankCardUrl {
init(apiBankCardOpenUrl: Api.BankCardOpenUrl) {
switch apiBankCardOpenUrl {
case let .bankCardOpenUrl(url, name):
self.title = name
self.url = url
}
}
}
extension BankCardInfo {
init(apiBankCardData: Api.payments.BankCardData) {
switch apiBankCardData {
case let .bankCardData(flags, title, url, urlName):
case let .bankCardData(title, urls):
self.title = title
self.url = url
self.actionTitle = urlName
self.urls = urls.map { BankCardUrl(apiBankCardOpenUrl: $0) }
}
}
}

View File

@ -25,7 +25,7 @@ public enum PeerNearbyVisibilityUpdate {
case invisible
}
public func peersNearbyUpdateVisibility(network: Network, stateManager: AccountStateManager, update: PeerNearbyVisibilityUpdate, background: Bool) -> Signal<Void, NoError> {
public func peersNearbyUpdateVisibility(account: Account, update: PeerNearbyVisibilityUpdate, background: Bool) -> Signal<Void, NoError> {
var flags: Int32 = 0
var geoPoint: Api.InputGeoPoint
var selfExpires: Int32?
@ -43,18 +43,30 @@ public func peersNearbyUpdateVisibility(network: Network, stateManager: AccountS
selfExpires = 0
}
let _ = (account.postbox.transaction { transaction in
transaction.updatePreferencesEntry(key: PreferencesKeys.peersNearby, { entry in
var settings = entry as? PeersNearbyState ?? PeersNearbyState.default
if let expires = selfExpires {
settings.visibilityExpires = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) + expires
} else if case .invisible = update {
settings.visibilityExpires = nil
}
return settings
})
}).start()
if background {
flags |= (1 << 1)
}
return network.request(Api.functions.contacts.getLocated(flags: flags, geoPoint: geoPoint, selfExpires: selfExpires))
return account.network.request(Api.functions.contacts.getLocated(flags: flags, geoPoint: geoPoint, selfExpires: selfExpires))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
return .single(nil)
}
|> mapToSignal { updates -> Signal<Void, NoError> in
if let updates = updates {
stateManager.addUpdates(updates)
account.stateManager.addUpdates(updates)
}
return .complete()
}
@ -258,3 +270,33 @@ public func updateChannelGeoLocation(postbox: Postbox, network: Network, channel
}
}
}
public struct PeersNearbyState: PreferencesEntry, Equatable {
public var visibilityExpires: Int32?
public static var `default` = PeersNearbyState(visibilityExpires: nil)
public init(visibilityExpires: Int32?) {
self.visibilityExpires = visibilityExpires
}
public init(decoder: PostboxDecoder) {
self.visibilityExpires = decoder.decodeOptionalInt32ForKey("expires")
}
public func encode(_ encoder: PostboxEncoder) {
if let expires = self.visibilityExpires {
encoder.encodeInt32(expires, forKey: "expires")
} else {
encoder.encodeNil(forKey: "expires")
}
}
public func isEqual(to: PreferencesEntry) -> Bool {
if let to = to as? PeersNearbyState, self == to {
return true
} else {
return false
}
}
}

View File

@ -1357,17 +1357,18 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
guard let message = message else {
return
}
let _ = (getBankCardInfo(account: strongSelf.context.account, cardNumber: number)
|> deliverOnMainQueue).start(next: { [weak self] info in
if let strongSelf = self, let info = info {
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
var items: [ActionSheetItem] = []
items.append(ActionSheetTextItem(title: info.title))
if let url = info.url, let actionTitle = info.actionTitle {
items.append(ActionSheetButtonItem(title: actionTitle, color: .accent, action: { [weak actionSheet] in
for url in info.urls {
items.append(ActionSheetButtonItem(title: url.title, color: .accent, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
if let strongSelf = self {
strongSelf.controllerInteraction?.openUrl(url, false, false, message)
strongSelf.controllerInteraction?.openUrl(url.url, false, false, message)
}
}))
}