From fcdb2831da80645cf746f73c2d8eab807b05d5d8 Mon Sep 17 00:00:00 2001 From: overtake <> Date: Tue, 11 Feb 2020 18:41:00 +0400 Subject: [PATCH 1/2] no message --- .../TelegramCore/Sources/AuthTransfer.swift | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/submodules/TelegramCore/Sources/AuthTransfer.swift b/submodules/TelegramCore/Sources/AuthTransfer.swift index 793079c53e..e661aa715d 100644 --- a/submodules/TelegramCore/Sources/AuthTransfer.swift +++ b/submodules/TelegramCore/Sources/AuthTransfer.swift @@ -18,7 +18,7 @@ public enum ExportAuthTransferTokenResult { case displayToken(AuthTransferExportedToken) case changeAccountAndRetry(UnauthorizedAccount) case loggedIn - case passwordRequested + case passwordRequested(UnauthorizedAccount) } public func exportAuthTransferToken(accountManager: AccountManager, account: UnauthorizedAccount, otherAccountUserIds: [Int32], syncContacts: Bool) -> Signal { @@ -42,8 +42,6 @@ public func exportAuthTransferToken(accountManager: AccountManager, account: Una return nil } |> castError(ExportAuthTransferTokenError.self) - - return .single(nil) } } } else { @@ -52,7 +50,7 @@ public func exportAuthTransferToken(accountManager: AccountManager, account: Una } |> mapToSignal { result -> Signal in guard let result = result else { - return .single(.passwordRequested) + return .single(.passwordRequested(account)) } switch result { case let .loginToken(expires, token): @@ -66,7 +64,7 @@ public func exportAuthTransferToken(accountManager: AccountManager, account: Una |> map(Optional.init) |> `catch` { error -> Signal in if error.errorDescription == "SESSION_PASSWORD_NEEDED" { - return account.network.request(Api.functions.account.getPassword(), automaticFloodWait: false) + return updatedAccount.network.request(Api.functions.account.getPassword(), automaticFloodWait: false) |> mapError { error -> ExportAuthTransferTokenError in if error.errorDescription.hasPrefix("FLOOD_WAIT") { return .limitExceeded @@ -77,13 +75,11 @@ public func exportAuthTransferToken(accountManager: AccountManager, account: Una |> mapToSignal { result -> Signal in switch result { case let .password(password): - return account.postbox.transaction { transaction -> Api.auth.LoginToken? in - transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .passwordEntry(hint: password.hint ?? "", number: nil, code: nil, suggestReset: false, syncContacts: syncContacts))) + return updatedAccount.postbox.transaction { transaction -> Api.auth.LoginToken? in + transaction.setState(UnauthorizedAccountState(isTestingEnvironment: updatedAccount.testingEnvironment, masterDatacenterId: updatedAccount.masterDatacenterId, contents: .passwordEntry(hint: password.hint ?? "", number: nil, code: nil, suggestReset: false, syncContacts: syncContacts))) return nil } |> castError(ExportAuthTransferTokenError.self) - - return .single(nil) } } } else { @@ -91,8 +87,11 @@ public func exportAuthTransferToken(accountManager: AccountManager, account: Una } } |> mapToSignal { result -> Signal in + guard let result = result else { + return .single(.passwordRequested(updatedAccount)) + } switch result { - case let .loginTokenSuccess(authorization)?: + case let .loginTokenSuccess(authorization): switch authorization { case let .authorization(_, _, user): return updatedAccount.postbox.transaction { transaction -> Signal in From 801b26f1579ecce07cf1537828e0d9bae521660a Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 11 Feb 2020 19:41:59 +0400 Subject: [PATCH 2/2] Fixes --- Telegram-iOS/Resources/Compass.tgs | Bin 11211 -> 11147 bytes .../ZoomableContentGalleryItemNode.swift | 28 ++++--- .../Sources/PeersNearbyController.swift | 77 +++++++++++++----- submodules/SyncCore/Sources/Namespaces.swift | 7 ++ submodules/TelegramApi/Sources/Api0.swift | 5 +- submodules/TelegramApi/Sources/Api1.swift | 38 +++++++++ submodules/TelegramApi/Sources/Api2.swift | 38 ++++----- submodules/TelegramApi/Sources/Api3.swift | 27 ++++++ .../TelegramCore/Sources/BankCards.swift | 49 ++++++++--- .../TelegramCore/Sources/PeersNearby.swift | 48 ++++++++++- .../TelegramUI/ChatController.swift | 7 +- 11 files changed, 253 insertions(+), 71 deletions(-) diff --git a/Telegram-iOS/Resources/Compass.tgs b/Telegram-iOS/Resources/Compass.tgs index d9ec83eb7741d23487187cafe49dc52d7109fca7..535e4362bf03eedfbfae82180281b993846e68db 100644 GIT binary patch delta 11007 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 delta 11067 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 B#3=v( diff --git a/submodules/GalleryUI/Sources/ZoomableContentGalleryItemNode.swift b/submodules/GalleryUI/Sources/ZoomableContentGalleryItemNode.swift index a0abf7e711..a420bcbf20 100644 --- a/submodules/GalleryUI/Sources/ZoomableContentGalleryItemNode.swift +++ b/submodules/GalleryUI/Sources/ZoomableContentGalleryItemNode.swift @@ -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? diff --git a/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift b/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift index b6f056e465..2a38f9c55b 100644 --- a/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift +++ b/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift @@ -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(nil) let addressPromise = Promise(nil) + let visibilityPromise = ValuePromise(true) + let expandedPromise = ValuePromise(false) + let coordinatePromise = Promise(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 = 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) } } diff --git a/submodules/SyncCore/Sources/Namespaces.swift b/submodules/SyncCore/Sources/Namespaces.swift index 76d058ee03..1af4170023 100644 --- a/submodules/SyncCore/Sources/Namespaces.swift +++ b/submodules/SyncCore/Sources/Namespaces.swift @@ -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 { diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index d5464fef60..532cd4172a 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -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: diff --git a/submodules/TelegramApi/Sources/Api1.swift b/submodules/TelegramApi/Sources/Api1.swift index 6382732af6..280da4e641 100644 --- a/submodules/TelegramApi/Sources/Api1.swift +++ b/submodules/TelegramApi/Sources/Api1.swift @@ -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 diff --git a/submodules/TelegramApi/Sources/Api2.swift b/submodules/TelegramApi/Sources/Api2.swift index 261dc2d312..c4a1ac4fc5 100644 --- a/submodules/TelegramApi/Sources/Api2.swift +++ b/submodules/TelegramApi/Sources/Api2.swift @@ -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 diff --git a/submodules/TelegramApi/Sources/Api3.swift b/submodules/TelegramApi/Sources/Api3.swift index 106c437be6..326c59d924 100644 --- a/submodules/TelegramApi/Sources/Api3.swift +++ b/submodules/TelegramApi/Sources/Api3.swift @@ -3263,6 +3263,33 @@ public extension Api { }) } } + public static func inputMediaDice() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + 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) { + 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) { let buffer = Buffer() diff --git a/submodules/TelegramCore/Sources/BankCards.swift b/submodules/TelegramCore/Sources/BankCards.swift index f0db9d6304..b600491d83 100644 --- a/submodules/TelegramCore/Sources/BankCards.swift +++ b/submodules/TelegramCore/Sources/BankCards.swift @@ -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 { - 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 + 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 in + return .single(nil) + } } - |> `catch` { _ -> Signal 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) } } } } - - diff --git a/submodules/TelegramCore/Sources/PeersNearby.swift b/submodules/TelegramCore/Sources/PeersNearby.swift index 4ea533867d..b6eda7311b 100644 --- a/submodules/TelegramCore/Sources/PeersNearby.swift +++ b/submodules/TelegramCore/Sources/PeersNearby.swift @@ -25,7 +25,7 @@ public enum PeerNearbyVisibilityUpdate { case invisible } -public func peersNearbyUpdateVisibility(network: Network, stateManager: AccountStateManager, update: PeerNearbyVisibilityUpdate, background: Bool) -> Signal { +public func peersNearbyUpdateVisibility(account: Account, update: PeerNearbyVisibilityUpdate, background: Bool) -> Signal { 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 in return .single(nil) } |> mapToSignal { updates -> Signal 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 + } + } +} diff --git a/submodules/TelegramUI/TelegramUI/ChatController.swift b/submodules/TelegramUI/TelegramUI/ChatController.swift index 6f3df9a6e6..a5a67229ed 100644 --- a/submodules/TelegramUI/TelegramUI/ChatController.swift +++ b/submodules/TelegramUI/TelegramUI/ChatController.swift @@ -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) } })) }