Merge branch 'beta'

This commit is contained in:
Ali 2019-12-13 17:36:24 +04:00
commit 97c2834506
4 changed files with 125 additions and 15 deletions

View File

@ -24,20 +24,49 @@ public struct AuthTransferTokenInfo {
public enum ExportAuthTransferTokenError { public enum ExportAuthTransferTokenError {
case generic case generic
case limitExceeded
} }
public enum ExportAuthTransferTokenResult { public enum ExportAuthTransferTokenResult {
case displayToken(AuthTransferExportedToken) case displayToken(AuthTransferExportedToken)
case changeAccountAndRetry(UnauthorizedAccount) case changeAccountAndRetry(UnauthorizedAccount)
case loggedIn case loggedIn
case passwordRequested
} }
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> {
return account.network.request(Api.functions.auth.exportLoginToken(apiId: account.networkArguments.apiId, apiHash: account.networkArguments.apiHash, exceptIds: otherAccountUserIds)) return account.network.request(Api.functions.auth.exportLoginToken(apiId: account.networkArguments.apiId, apiHash: account.networkArguments.apiHash, exceptIds: otherAccountUserIds))
|> mapError { _ -> ExportAuthTransferTokenError in |> map(Optional.init)
return .generic |> `catch` { error -> Signal<Api.auth.LoginToken?, ExportAuthTransferTokenError> in
if error.errorDescription == "SESSION_PASSWORD_NEEDED" {
return account.network.request(Api.functions.account.getPassword(), automaticFloodWait: false)
|> mapError { error -> ExportAuthTransferTokenError in
if error.errorDescription.hasPrefix("FLOOD_WAIT") {
return .limitExceeded
} else {
return .generic
}
}
|> mapToSignal { result -> Signal<Api.auth.LoginToken?, ExportAuthTransferTokenError> 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 nil
}
|> castError(ExportAuthTransferTokenError.self)
return .single(nil)
}
}
} else {
return .fail(.generic)
}
} }
|> mapToSignal { result -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in |> mapToSignal { result -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in
guard let result = result else {
return .single(.passwordRequested)
}
switch result { switch result {
case let .loginToken(expires, token): case let .loginToken(expires, token):
return .single(.displayToken(AuthTransferExportedToken(value: token.makeData(), validUntil: expires))) return .single(.displayToken(AuthTransferExportedToken(value: token.makeData(), validUntil: expires)))
@ -47,8 +76,32 @@ public func exportAuthTransferToken(accountManager: AccountManager, account: Una
|> castError(ExportAuthTransferTokenError.self) |> castError(ExportAuthTransferTokenError.self)
|> mapToSignal { updatedAccount -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in |> mapToSignal { updatedAccount -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in
return updatedAccount.network.request(Api.functions.auth.importLoginToken(token: token)) return updatedAccount.network.request(Api.functions.auth.importLoginToken(token: token))
|> mapError { _ -> ExportAuthTransferTokenError in |> map(Optional.init)
return .generic |> `catch` { error -> Signal<Api.auth.LoginToken?, ExportAuthTransferTokenError> in
if error.errorDescription == "SESSION_PASSWORD_NEEDED" {
return account.network.request(Api.functions.account.getPassword(), automaticFloodWait: false)
|> mapError { error -> ExportAuthTransferTokenError in
if error.errorDescription.hasPrefix("FLOOD_WAIT") {
return .limitExceeded
} else {
return .generic
}
}
|> mapToSignal { result -> Signal<Api.auth.LoginToken?, ExportAuthTransferTokenError> 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 nil
}
|> castError(ExportAuthTransferTokenError.self)
return .single(nil)
}
}
} else {
return .fail(.generic)
}
} }
|> mapToSignal { result -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in |> mapToSignal { result -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in
switch result { switch result {

View File

@ -315,7 +315,9 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
super.didLoad() super.didLoad()
self.titleNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.debugTap(_:)))) self.titleNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.debugTap(_:))))
//self.noticeNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.debugQrTap(_:)))) #if DEBUG
self.noticeNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.debugQrTap(_:))))
#endif
} }
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) { func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
@ -452,7 +454,7 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
self?.refreshQrToken() self?.refreshQrToken()
})) }))
strongSelf.refreshQrToken() strongSelf.refreshQrToken()
case .loggedIn: case .loggedIn, .passwordRequested:
strongSelf.exportTokenDisposable.set(nil) strongSelf.exportTokenDisposable.set(nil)
} }
})) }))

View File

@ -112,7 +112,7 @@ final class HorizontalListContextResultsChatInputContextPanelNode: ChatInputCont
self.listView.displayedItemRangeChanged = { [weak self] displayedRange, opaqueTransactionState in self.listView.displayedItemRangeChanged = { [weak self] displayedRange, opaqueTransactionState in
if let strongSelf = self, let state = opaqueTransactionState as? HorizontalListContextResultsOpaqueState { if let strongSelf = self, let state = opaqueTransactionState as? HorizontalListContextResultsOpaqueState {
if let visible = displayedRange.visibleRange { if let visible = displayedRange.visibleRange {
if state.hasMore && visible.lastIndex <= state.entryCount - 10 { if state.hasMore && visible.lastIndex >= state.entryCount - 10 {
strongSelf.loadMore() strongSelf.loadMore()
} }
} }

View File

@ -9,6 +9,7 @@ import TelegramPresentationData
import TelegramUIPreferences import TelegramUIPreferences
import MergeLists import MergeLists
import AccountContext import AccountContext
import SwiftSignalKit
private enum VerticalChatContextResultsEntryStableId: Hashable { private enum VerticalChatContextResultsEntryStableId: Hashable {
case action case action
@ -122,12 +123,16 @@ private func preparedTransition(from fromEntries: [VerticalListContextResultsCha
final class VerticalListContextResultsChatInputContextPanelNode: ChatInputContextPanelNode { final class VerticalListContextResultsChatInputContextPanelNode: ChatInputContextPanelNode {
private let listView: ListView private let listView: ListView
private var currentResults: ChatContextResultCollection? private var currentExternalResults: ChatContextResultCollection?
private var currentProcessedResults: ChatContextResultCollection?
private var currentEntries: [VerticalListContextResultsChatInputContextPanelEntry]? private var currentEntries: [VerticalListContextResultsChatInputContextPanelEntry]?
private var enqueuedTransitions: [(VerticalListContextResultsChatInputContextPanelTransition, Bool)] = [] private var enqueuedTransitions: [(VerticalListContextResultsChatInputContextPanelTransition, Bool)] = []
private var validLayout: (CGSize, CGFloat, CGFloat, CGFloat)? private var validLayout: (CGSize, CGFloat, CGFloat, CGFloat)?
private let loadMoreDisposable = MetaDisposable()
private var isLoadingMore: Bool = false
override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) { override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) {
self.listView = ListView() self.listView = ListView()
self.listView.isOpaque = false self.listView.isOpaque = false
@ -143,10 +148,33 @@ final class VerticalListContextResultsChatInputContextPanelNode: ChatInputContex
self.clipsToBounds = true self.clipsToBounds = true
self.addSubnode(self.listView) self.addSubnode(self.listView)
self.listView.visibleBottomContentOffsetChanged = { [weak self] offset in
guard let strongSelf = self, !strongSelf.isLoadingMore, case let .known(value) = offset, value < 40.0 else {
return
}
strongSelf.loadMore()
}
}
deinit {
self.loadMoreDisposable.dispose()
} }
func updateResults(_ results: ChatContextResultCollection) { func updateResults(_ results: ChatContextResultCollection) {
self.currentResults = results if self.currentExternalResults == results {
return
}
self.currentExternalResults = results
self.currentProcessedResults = results
self.isLoadingMore = false
self.loadMoreDisposable.set(nil)
self.updateInternalResults(results)
}
private func updateInternalResults(_ results: ChatContextResultCollection) {
var entries: [VerticalListContextResultsChatInputContextPanelEntry] = [] var entries: [VerticalListContextResultsChatInputContextPanelEntry] = []
var index = 0 var index = 0
var resultIds = Set<VerticalChatContextResultsEntryStableId>() var resultIds = Set<VerticalChatContextResultsEntryStableId>()
@ -203,15 +231,13 @@ final class VerticalListContextResultsChatInputContextPanelNode: ChatInputContex
var options = ListViewDeleteAndInsertOptions() var options = ListViewDeleteAndInsertOptions()
if firstTime { if firstTime {
//options.insert(.Synchronous)
//options.insert(.LowLatency)
} else { } else {
options.insert(.AnimateTopItemPosition) options.insert(.AnimateTopItemPosition)
options.insert(.AnimateCrossfade) options.insert(.AnimateCrossfade)
} }
var insets = UIEdgeInsets() var insets = UIEdgeInsets()
insets.top = topInsetForLayout(size: validLayout.0, hasSwitchPeer: self.currentResults?.switchPeer != nil) insets.top = topInsetForLayout(size: validLayout.0, hasSwitchPeer: self.currentExternalResults?.switchPeer != nil)
insets.left = validLayout.1 insets.left = validLayout.1
insets.right = validLayout.2 insets.right = validLayout.2
@ -251,7 +277,7 @@ final class VerticalListContextResultsChatInputContextPanelNode: ChatInputContex
self.validLayout = (size, leftInset, rightInset, bottomInset) self.validLayout = (size, leftInset, rightInset, bottomInset)
var insets = UIEdgeInsets() var insets = UIEdgeInsets()
insets.top = self.topInsetForLayout(size: size, hasSwitchPeer: self.currentResults?.switchPeer != nil) insets.top = self.topInsetForLayout(size: size, hasSwitchPeer: self.currentExternalResults?.switchPeer != nil)
insets.left = leftInset insets.left = leftInset
insets.right = rightInset insets.right = rightInset
@ -268,12 +294,12 @@ final class VerticalListContextResultsChatInputContextPanelNode: ChatInputContex
} }
} }
if self.theme !== interfaceState.theme, let currentResults = currentResults { if self.theme !== interfaceState.theme, let currentProcessedResults = self.currentProcessedResults {
self.theme = interfaceState.theme self.theme = interfaceState.theme
self.listView.keepBottomItemOverscrollBackground = self.theme.list.plainBackgroundColor self.listView.keepBottomItemOverscrollBackground = self.theme.list.plainBackgroundColor
let new = self.currentEntries?.map({$0.withUpdatedTheme(interfaceState.theme)}) ?? [] let new = self.currentEntries?.map({$0.withUpdatedTheme(interfaceState.theme)}) ?? []
prepareTransition(from: self.currentEntries, to: new, results: currentResults) prepareTransition(from: self.currentEntries, to: new, results: currentProcessedResults)
} }
} }
@ -299,4 +325,33 @@ final class VerticalListContextResultsChatInputContextPanelNode: ChatInputContex
let listViewFrame = self.listView.frame let listViewFrame = self.listView.frame
return self.listView.hitTest(CGPoint(x: point.x - listViewFrame.minX, y: point.y - listViewFrame.minY), with: event) return self.listView.hitTest(CGPoint(x: point.x - listViewFrame.minX, y: point.y - listViewFrame.minY), with: event)
} }
private func loadMore() {
guard !self.isLoadingMore, let currentProcessedResults = self.currentProcessedResults, let nextOffset = currentProcessedResults.nextOffset else {
return
}
self.isLoadingMore = true
self.loadMoreDisposable.set((requestChatContextResults(account: self.context.account, botId: currentProcessedResults.botId, peerId: currentProcessedResults.peerId, query: currentProcessedResults.query, location: .single(currentProcessedResults.geoPoint), offset: nextOffset)
|> deliverOnMainQueue).start(next: { [weak self] nextResults in
guard let strongSelf = self, let nextResults = nextResults else {
return
}
strongSelf.isLoadingMore = false
var results: [ChatContextResult] = []
var existingIds = Set<String>()
for result in currentProcessedResults.results {
results.append(result)
existingIds.insert(result.id)
}
for result in nextResults.results {
if !existingIds.contains(result.id) {
results.append(result)
existingIds.insert(result.id)
}
}
let mergedResults = ChatContextResultCollection(botId: currentProcessedResults.botId, peerId: currentProcessedResults.peerId, query: currentProcessedResults.query, geoPoint: currentProcessedResults.geoPoint, queryId: nextResults.queryId, nextOffset: nextResults.nextOffset, presentation: currentProcessedResults.presentation, switchPeer: currentProcessedResults.switchPeer, results: results, cacheTimeout: currentProcessedResults.cacheTimeout)
strongSelf.currentProcessedResults = mergedResults
strongSelf.updateInternalResults(mergedResults)
}))
}
} }