Merge commit 'b325b876ff541809d1bdbd079b83f413f3d1ebee'

This commit is contained in:
Ali 2020-02-11 17:00:52 +01:00
commit be0ccabe2a
12 changed files with 190 additions and 70 deletions

Binary file not shown.

View File

@ -95,7 +95,7 @@ private final class ContextControllerContentSourceImpl: ContextControllerContent
} }
} }
public class ChatListControllerImpl: TelegramBaseController, ChatListController, UIViewControllerPreviewingDelegate, TabBarContainedController { public class ChatListControllerImpl: TelegramBaseController, ChatListController, UIViewControllerPreviewingDelegate/*, TabBarContainedController*/ {
private var validLayout: ContainerViewLayout? private var validLayout: ContainerViewLayout?
public let context: AccountContext public let context: AccountContext
@ -1804,7 +1804,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
} }
} }
public func presentTabBarPreviewingController(sourceNodes: [ASDisplayNode]) { /*public func presentTabBarPreviewingController(sourceNodes: [ASDisplayNode]) {
if self.isNodeLoaded { if self.isNodeLoaded {
let _ = (self.context.account.postbox.transaction { transaction -> [ChatListFilter] in let _ = (self.context.account.postbox.transaction { transaction -> [ChatListFilter] in
let settings = transaction.getPreferencesEntry(key: PreferencesKeys.chatListFilters) as? ChatListFiltersState ?? ChatListFiltersState.default let settings = transaction.getPreferencesEntry(key: PreferencesKeys.chatListFilters) as? ChatListFiltersState ?? ChatListFiltersState.default
@ -1849,5 +1849,5 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
public func updateTabBarPreviewingControllerPresentation(_ update: TabBarContainedControllerPresentationUpdate) { public func updateTabBarPreviewingControllerPresentation(_ update: TabBarContainedControllerPresentationUpdate) {
} }*/
} }

View File

@ -1,4 +1,4 @@
import Foundation /*import Foundation
import UIKit import UIKit
import Display import Display
import SwiftSignalKit import SwiftSignalKit
@ -405,3 +405,4 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
return controller return controller
} }
*/

View File

@ -1,4 +1,4 @@
import Foundation /*import Foundation
import UIKit import UIKit
import Display import Display
import SwiftSignalKit import SwiftSignalKit
@ -206,3 +206,4 @@ func chatListFilterPresetListController(context: AccountContext, updated: @escap
return controller return controller
} }
*/

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

View File

@ -24,6 +24,8 @@ import ContextUI
import TelegramNotices import TelegramNotices
import TelegramStringFormatting import TelegramStringFormatting
private let maxUsersDisplayedLimit: Int32 = 5
private struct PeerNearbyEntry { private struct PeerNearbyEntry {
let peer: (Peer, CachedPeerData?) let peer: (Peer, CachedPeerData?)
let expires: Int32 let expires: Int32
@ -57,14 +59,16 @@ private final class PeersNearbyControllerArguments {
let openChat: (Peer) -> Void let openChat: (Peer) -> Void
let openCreateGroup: (Double, Double, String?) -> Void let openCreateGroup: (Double, Double, String?) -> Void
let contextAction: (Peer, ASDisplayNode, ContextGesture?) -> 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.context = context
self.toggleVisibility = toggleVisibility self.toggleVisibility = toggleVisibility
self.openProfile = openProfile self.openProfile = openProfile
self.openChat = openChat self.openChat = openChat
self.openCreateGroup = openCreateGroup self.openCreateGroup = openCreateGroup
self.contextAction = contextAction self.contextAction = contextAction
self.expandUsers = expandUsers
} }
} }
@ -82,6 +86,7 @@ private enum PeersNearbyEntry: ItemListNodeEntry {
case empty(PresentationTheme, String) case empty(PresentationTheme, String)
case visibility(PresentationTheme, String, Bool) case visibility(PresentationTheme, String, Bool)
case user(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, PeerNearbyEntry) case user(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, PeerNearbyEntry)
case expand(PresentationTheme, String)
case groupsHeader(PresentationTheme, String, Bool) case groupsHeader(PresentationTheme, String, Bool)
case createGroup(PresentationTheme, String, Double?, Double?, String?) case createGroup(PresentationTheme, String, Double?, Double?, String?)
@ -94,7 +99,7 @@ private enum PeersNearbyEntry: ItemListNodeEntry {
switch self { switch self {
case .header: case .header:
return PeersNearbySection.header.rawValue return PeersNearbySection.header.rawValue
case .usersHeader, .empty, .visibility, .user: case .usersHeader, .empty, .visibility, .user, .expand:
return PeersNearbySection.users.rawValue return PeersNearbySection.users.rawValue
case .groupsHeader, .createGroup, .group: case .groupsHeader, .createGroup, .group:
return PeersNearbySection.groups.rawValue return PeersNearbySection.groups.rawValue
@ -115,12 +120,14 @@ private enum PeersNearbyEntry: ItemListNodeEntry {
return 3 return 3
case let .user(index, _, _, _, _, _): case let .user(index, _, _, _, _, _):
return 4 + index return 4 + index
case .groupsHeader: case .expand:
return 1000 return 1000
case .createGroup: case .groupsHeader:
return 1001 return 1001
case .createGroup:
return 1002
case let .group(index, _, _, _, _, _): case let .group(index, _, _, _, _, _):
return 1002 + index return 1003 + index
case .channelsHeader: case .channelsHeader:
return 2000 return 2000
case let .channel(index, _, _, _, _, _): case let .channel(index, _, _, _, _, _):
@ -161,6 +168,12 @@ private enum PeersNearbyEntry: ItemListNodeEntry {
} else { } else {
return false 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): case let .groupsHeader(lhsTheme, lhsText, lhsLoading):
if case let .groupsHeader(rhsTheme, rhsText, rhsLoading) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsLoading == rhsLoading { if case let .groupsHeader(rhsTheme, rhsText, rhsLoading) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsLoading == rhsLoading {
return true return true
@ -224,14 +237,19 @@ private enum PeersNearbyEntry: ItemListNodeEntry {
}) })
case let .user(_, theme, strings, dateTimeFormat, nameDisplayOrder, peer): case let .user(_, theme, strings, dateTimeFormat, nameDisplayOrder, peer):
var text = strings.Map_DistanceAway(stringForDistance(peer.distance)).0 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 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: { 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) arguments.openProfile(peer.peer.0)
}, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }, toggleUpdated: nil, contextAction: { node, gesture in }
arguments.contextAction(peer.peer.0, node, gesture) }, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }, toggleUpdated: nil, contextAction: nil, hasTopGroupInset: false, tag: 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): case let .groupsHeader(theme, text, loading):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, activityIndicator: loading ? .left : .none, sectionId: self.section) return ItemListSectionHeaderItem(presentationData: presentationData, text: text, activityIndicator: loading ? .left : .none, sectionId: self.section)
case let .createGroup(theme, title, latitude, longitude, address): 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] = [] var entries: [PeersNearbyEntry] = []
entries.append(.header(presentationData.theme, presentationData.strings.PeopleNearby_DiscoverDescription)) 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 { if let data = data, !data.users.isEmpty {
var i: Int32 = 0 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)) entries.append(.user(i, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, user))
i += 1 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)) 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 dataPromise = Promise<PeersNearbyData?>(nil)
let addressPromise = Promise<String?>(nil) let addressPromise = Promise<String?>(nil)
let visibilityPromise = ValuePromise<Bool>(true)
let expandedPromise = ValuePromise<Bool>(false)
let coordinatePromise = Promise<CLLocationCoordinate2D?>(nil) let coordinatePromise = Promise<CLLocationCoordinate2D?>(nil)
coordinatePromise.set(.single(nil) |> then(currentLocationManagerCoordinate(manager: context.sharedContext.locationManager!, timeout: 5.0))) 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() let _ = (coordinatePromise.get()
|> deliverOnMainQueue).start(next: { coordinate in |> deliverOnMainQueue).start(next: { coordinate in
if let coordinate = coordinate { 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) })]), nil)
visibilityPromise.set(true)
} else { } 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 }, openProfile: { peer in
navigateToProfileImpl?(peer) navigateToProfileImpl?(peer)
@ -498,6 +535,8 @@ public func peersNearbyController(context: AccountContext) -> ViewController {
presentControllerImpl?(c, nil) presentControllerImpl?(c, nil)
}), reactionItems: [], gesture: gesture) }), reactionItems: [], gesture: gesture)
presentInGlobalOverlayImpl?(contextController) presentInGlobalOverlayImpl?(contextController)
}, expandUsers: {
expandedPromise.set(true)
}) })
let dataSignal: Signal<PeersNearbyData?, NoError> = coordinatePromise.get() let dataSignal: Signal<PeersNearbyData?, NoError> = coordinatePromise.get()
@ -569,9 +608,9 @@ public func peersNearbyController(context: AccountContext) -> ViewController {
|> delay(1.0, queue: Queue.mainQueue()) |> 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 |> deliverOnMainQueue
|> map { presentationData, data, displayLoading -> (ItemListControllerState, (ItemListNodeState, Any)) in |> map { presentationData, data, displayLoading, visibility, expanded -> (ItemListControllerState, (ItemListNodeState, Any)) in
let previous = previousData.swap(data) let previous = previousData.swap(data)
var crossfade = false 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 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)) return (controllerState, (listState, arguments))
} }
@ -596,7 +635,7 @@ public func peersNearbyController(context: AccountContext) -> ViewController {
controller?.clearItemNodesHighlight(animated: true) controller?.clearItemNodesHighlight(animated: true)
} }
navigateToProfileImpl = { [weak controller] peer in 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, fromChat: false) {
(navigationController as? NavigationController)?.pushViewController(controller) (navigationController as? NavigationController)?.pushViewController(controller)
} }
} }

View File

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

View File

@ -18,7 +18,7 @@ public enum ExportAuthTransferTokenResult {
case displayToken(AuthTransferExportedToken) case displayToken(AuthTransferExportedToken)
case changeAccountAndRetry(UnauthorizedAccount) case changeAccountAndRetry(UnauthorizedAccount)
case loggedIn case loggedIn
case passwordRequested case passwordRequested(UnauthorizedAccount)
} }
public func exportAuthTransferToken(accountManager: AccountManager, account: UnauthorizedAccount, otherAccountUserIds: [Int32], syncContacts: Bool) -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> { public func exportAuthTransferToken(accountManager: AccountManager, account: UnauthorizedAccount, otherAccountUserIds: [Int32], syncContacts: Bool) -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> {
@ -42,8 +42,6 @@ public func exportAuthTransferToken(accountManager: AccountManager, account: Una
return nil return nil
} }
|> castError(ExportAuthTransferTokenError.self) |> castError(ExportAuthTransferTokenError.self)
return .single(nil)
} }
} }
} else { } else {
@ -52,7 +50,7 @@ public func exportAuthTransferToken(accountManager: AccountManager, account: Una
} }
|> mapToSignal { result -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in |> mapToSignal { result -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in
guard let result = result else { guard let result = result else {
return .single(.passwordRequested) return .single(.passwordRequested(account))
} }
switch result { switch result {
case let .loginToken(expires, token): case let .loginToken(expires, token):
@ -66,7 +64,7 @@ public func exportAuthTransferToken(accountManager: AccountManager, account: Una
|> map(Optional.init) |> map(Optional.init)
|> `catch` { error -> Signal<Api.auth.LoginToken?, ExportAuthTransferTokenError> in |> `catch` { error -> Signal<Api.auth.LoginToken?, ExportAuthTransferTokenError> in
if error.errorDescription == "SESSION_PASSWORD_NEEDED" { 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 |> mapError { error -> ExportAuthTransferTokenError in
if error.errorDescription.hasPrefix("FLOOD_WAIT") { if error.errorDescription.hasPrefix("FLOOD_WAIT") {
return .limitExceeded return .limitExceeded
@ -77,13 +75,11 @@ public func exportAuthTransferToken(accountManager: AccountManager, account: Una
|> mapToSignal { result -> Signal<Api.auth.LoginToken?, ExportAuthTransferTokenError> in |> mapToSignal { result -> Signal<Api.auth.LoginToken?, ExportAuthTransferTokenError> in
switch result { switch result {
case let .password(password): case let .password(password):
return account.postbox.transaction { transaction -> Api.auth.LoginToken? in return updatedAccount.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))) transaction.setState(UnauthorizedAccountState(isTestingEnvironment: updatedAccount.testingEnvironment, masterDatacenterId: updatedAccount.masterDatacenterId, contents: .passwordEntry(hint: password.hint ?? "", number: nil, code: nil, suggestReset: false, syncContacts: syncContacts)))
return nil return nil
} }
|> castError(ExportAuthTransferTokenError.self) |> castError(ExportAuthTransferTokenError.self)
return .single(nil)
} }
} }
} else { } else {
@ -91,8 +87,11 @@ public func exportAuthTransferToken(accountManager: AccountManager, account: Una
} }
} }
|> mapToSignal { result -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in |> mapToSignal { result -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in
guard let result = result else {
return .single(.passwordRequested(updatedAccount))
}
switch result { switch result {
case let .loginTokenSuccess(authorization)?: case let .loginTokenSuccess(authorization):
switch authorization { switch authorization {
case let .authorization(_, _, user): case let .authorization(_, _, user):
return updatedAccount.postbox.transaction { transaction -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in return updatedAccount.postbox.transaction { transaction -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in

View File

@ -2,16 +2,33 @@ import Foundation
import Postbox import Postbox
import TelegramApi import TelegramApi
import SyncCore import SyncCore
import MtProtoKit
import SwiftSignalKit import SwiftSignalKit
public struct BankCardUrl {
public let title: String
public let url: String
}
public struct BankCardInfo { public struct BankCardInfo {
public let title: String public let title: String
public let url: String? public let urls: [BankCardUrl]
public let actionTitle: String?
} }
public func getBankCardInfo(account: Account, cardNumber: String) -> Signal<BankCardInfo?, NoError> { public func getBankCardInfo(account: Account, cardNumber: String) -> Signal<BankCardInfo?, NoError> {
return account.network.request(Api.functions.payments.getBankCardData(number: cardNumber)) 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 |> map { result -> BankCardInfo? in
return BankCardInfo(apiBankCardData: result) return BankCardInfo(apiBankCardData: result)
} }
@ -19,16 +36,24 @@ public func getBankCardInfo(account: Account, cardNumber: String) -> Signal<Bank
return .single(nil) return .single(nil)
} }
} }
}
extension BankCardUrl {
init(apiBankCardOpenUrl: Api.BankCardOpenUrl) {
switch apiBankCardOpenUrl {
case let .bankCardOpenUrl(url, name):
self.title = name
self.url = url
}
}
}
extension BankCardInfo { extension BankCardInfo {
init(apiBankCardData: Api.payments.BankCardData) { init(apiBankCardData: Api.payments.BankCardData) {
switch apiBankCardData { switch apiBankCardData {
case let .bankCardData(flags, title, url, urlName): case let .bankCardData(title, urls):
self.title = title self.title = title
self.url = url self.urls = urls.map { BankCardUrl(apiBankCardOpenUrl: $0) }
self.actionTitle = urlName
} }
} }
} }

View File

@ -133,7 +133,8 @@ public struct ChannelStatsContextState: Equatable {
} }
private func requestStats(network: Network, datacenterId: Int32, peer: Peer, dark: Bool = false) -> Signal<ChannelStats?, NoError> { private func requestStats(network: Network, datacenterId: Int32, peer: Peer, dark: Bool = false) -> Signal<ChannelStats?, NoError> {
guard let inputChannel = apiInputChannel(peer) else { return .never()
/*guard let inputChannel = apiInputChannel(peer) else {
return .never() return .never()
} }
@ -159,11 +160,12 @@ private func requestStats(network: Network, datacenterId: Int32, peer: Peer, dar
} }
|> `catch` { _ -> Signal<ChannelStats?, NoError> in |> `catch` { _ -> Signal<ChannelStats?, NoError> in
return .single(nil) return .single(nil)
} }*/
} }
private func requestGraph(network: Network, datacenterId: Int32, token: String) -> Signal<ChannelStatsGraph?, NoError> { private func requestGraph(network: Network, datacenterId: Int32, token: String) -> Signal<ChannelStatsGraph?, NoError> {
let signal: Signal<Api.StatsGraph, MTRpcError> return .never()
/*let signal: Signal<Api.StatsGraph, MTRpcError>
if network.datacenterId != datacenterId { if network.datacenterId != datacenterId {
signal = network.download(datacenterId: Int(datacenterId), isMedia: false, tag: nil) signal = network.download(datacenterId: Int(datacenterId), isMedia: false, tag: nil)
|> castError(MTRpcError.self) |> castError(MTRpcError.self)
@ -180,7 +182,7 @@ private func requestGraph(network: Network, datacenterId: Int32, token: String)
} }
|> `catch` { _ -> Signal<ChannelStatsGraph?, NoError> in |> `catch` { _ -> Signal<ChannelStatsGraph?, NoError> in
return .single(nil) return .single(nil)
} }*/
} }
private final class ChannelStatsContextImpl { private final class ChannelStatsContextImpl {
@ -361,7 +363,7 @@ public final class ChannelStatsContext {
} }
} }
extension ChannelStatsGraph { /*extension ChannelStatsGraph {
init(apiStatsGraph: Api.StatsGraph) { init(apiStatsGraph: Api.StatsGraph) {
switch apiStatsGraph { switch apiStatsGraph {
case let .statsGraph(json): case let .statsGraph(json):
@ -422,3 +424,4 @@ extension ChannelStats {
} }
} }
} }
*/

View File

@ -25,7 +25,7 @@ public enum PeerNearbyVisibilityUpdate {
case invisible 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 flags: Int32 = 0
var geoPoint: Api.InputGeoPoint var geoPoint: Api.InputGeoPoint
var selfExpires: Int32? var selfExpires: Int32?
@ -43,18 +43,30 @@ public func peersNearbyUpdateVisibility(network: Network, stateManager: AccountS
selfExpires = 0 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 { if background {
flags |= (1 << 1) 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) |> map(Optional.init)
|> `catch` { _ -> Signal<Api.Updates?, NoError> in |> `catch` { _ -> Signal<Api.Updates?, NoError> in
return .single(nil) return .single(nil)
} }
|> mapToSignal { updates -> Signal<Void, NoError> in |> mapToSignal { updates -> Signal<Void, NoError> in
if let updates = updates { if let updates = updates {
stateManager.addUpdates(updates) account.stateManager.addUpdates(updates)
} }
return .complete() 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

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