Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin 2021-04-09 14:00:33 +03:00
commit f362ce9fc6
8 changed files with 145 additions and 20 deletions

View File

@ -22,6 +22,7 @@ swift_library(
"//submodules/CountrySelectionUI:CountrySelectionUI",
"//submodules/AppBundle:AppBundle",
"//submodules/PresentationDataUtils:PresentationDataUtils",
"//submodules/OverlayStatusController:OverlayStatusController",
],
visibility = [
"//visibility:public",

View File

@ -138,6 +138,11 @@ final class BotCheckoutActionButton: HighlightableButtonNode {
self.progressBackgroundNode.layer.add(basicAnimation, forKey: "progressRotation")
case let .active(title):
if let applePayButton = self.applePayButton {
self.applePayButton = nil
applePayButton.removeFromSuperview()
}
if case .active = previousState {
let makeLayout = TextNode.asyncLayout(self.labelNode)
let (labelLayout, labelApply) = makeLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: title, font: titleFont, textColor: self.foregroundColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: validLayout, alignment: .natural, cutout: nil, insets: UIEdgeInsets()))

View File

@ -52,7 +52,7 @@ public final class BotCheckoutController: ViewController {
}
override public func loadDisplayNode() {
let displayNode = BotCheckoutControllerNode(controller: nil, navigationBar: self.navigationBar!, updateNavigationOffset: { [weak self] offset in
let displayNode = BotCheckoutControllerNode(controller: self, navigationBar: self.navigationBar!, updateNavigationOffset: { [weak self] offset in
if let strongSelf = self {
strongSelf.navigationOffset = offset
}

View File

@ -18,6 +18,7 @@ import TelegramStringFormatting
import PasswordSetupUI
import Stripe
import LocalAuth
import OverlayStatusController
final class BotCheckoutControllerArguments {
fileprivate let account: Account
@ -25,13 +26,15 @@ final class BotCheckoutControllerArguments {
fileprivate let openPaymentMethod: () -> Void
fileprivate let openShippingMethod: () -> Void
fileprivate let updateTip: (Int64) -> Void
fileprivate let ensureTipInputVisible: () -> Void
fileprivate init(account: Account, openInfo: @escaping (BotCheckoutInfoControllerFocus) -> Void, openPaymentMethod: @escaping () -> Void, openShippingMethod: @escaping () -> Void, updateTip: @escaping (Int64) -> Void) {
fileprivate init(account: Account, openInfo: @escaping (BotCheckoutInfoControllerFocus) -> Void, openPaymentMethod: @escaping () -> Void, openShippingMethod: @escaping () -> Void, updateTip: @escaping (Int64) -> Void, ensureTipInputVisible: @escaping () -> Void) {
self.account = account
self.openInfo = openInfo
self.openPaymentMethod = openPaymentMethod
self.openShippingMethod = openShippingMethod
self.updateTip = updateTip
self.ensureTipInputVisible = ensureTipInputVisible
}
}
@ -197,6 +200,10 @@ enum BotCheckoutEntry: ItemListNodeEntry {
case let .tip(_, _, text, currency, value, numericValue, maxValue, variants):
return BotCheckoutTipItem(theme: presentationData.theme, strings: presentationData.strings, title: text, currency: currency, value: value, numericValue: numericValue, maxValue: maxValue, availableVariants: variants, sectionId: self.section, updateValue: { value in
arguments.updateTip(value)
}, updatedFocus: { isFocused in
if isFocused {
arguments.ensureTipInputVisible()
}
})
case let .paymentMethod(_, text, value):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
@ -428,6 +435,7 @@ private func availablePaymentMethods(form: BotPaymentForm, current: BotCheckoutP
}
final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthorizationViewControllerDelegate {
private weak var controller: BotCheckoutController?
private let context: AccountContext
private let messageId: MessageId
private let present: (ViewController, Any?) -> Void
@ -452,13 +460,15 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
private let actionButtonPanelSeparator: ASDisplayNode
private let actionButton: BotCheckoutActionButton
private let inProgressDimNode: ASDisplayNode
private var statusController: ViewController?
private let payDisposable = MetaDisposable()
private let paymentAuthDisposable = MetaDisposable()
private var applePayAuthrorizationCompletion: ((PKPaymentAuthorizationStatus) -> Void)?
private var applePayController: PKPaymentAuthorizationViewController?
init(controller: ItemListController?, navigationBar: NavigationBar, updateNavigationOffset: @escaping (CGFloat) -> Void, context: AccountContext, invoice: TelegramMediaInvoice, messageId: MessageId, present: @escaping (ViewController, Any?) -> Void, dismissAnimated: @escaping () -> Void) {
init(controller: BotCheckoutController?, navigationBar: NavigationBar, updateNavigationOffset: @escaping (CGFloat) -> Void, context: AccountContext, invoice: TelegramMediaInvoice, messageId: MessageId, present: @escaping (ViewController, Any?) -> Void, dismissAnimated: @escaping () -> Void) {
self.controller = controller
self.context = context
self.messageId = messageId
self.present = present
@ -470,6 +480,7 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
var updateTipImpl: ((Int64) -> Void)?
var openPaymentMethodImpl: (() -> Void)?
var openShippingMethodImpl: (() -> Void)?
var ensureTipInputVisibleImpl: (() -> Void)?
let arguments = BotCheckoutControllerArguments(account: context.account, openInfo: { item in
openInfoImpl?(item)
@ -479,6 +490,8 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
openShippingMethodImpl?()
}, updateTip: { value in
updateTipImpl?(value)
}, ensureTipInputVisible: {
ensureTipInputVisibleImpl?()
})
let signal: Signal<(ItemListPresentationData, (ItemListNodeState, Any)), NoError> = combineLatest(context.sharedContext.presentationData, self.state.get(), paymentFormAndInfo.get(), context.account.postbox.loadedPeerWithId(messageId.peerId))
@ -503,7 +516,7 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
self.inProgressDimNode.isUserInteractionEnabled = false
self.inProgressDimNode.backgroundColor = self.presentationData.theme.list.plainBackgroundColor.withAlphaComponent(0.5)
super.init(controller: controller, navigationBar: navigationBar, updateNavigationOffset: updateNavigationOffset, state: signal)
super.init(controller: nil, navigationBar: navigationBar, updateNavigationOffset: updateNavigationOffset, state: signal)
self.arguments = arguments
@ -519,8 +532,9 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
updatedCurrentShippingOptionId = currentShippingOptionId
}
}
strongSelf.paymentFormAndInfo.set(.single((paymentFormValue, formInfo, validatedInfo, updatedCurrentShippingOptionId, strongSelf.currentPaymentMethod, strongSelf.currentTipAmount)))
strongSelf.updateActionButton()
}
}), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
@ -762,6 +776,23 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
strongSelf.updateActionButton()
}
ensureTipInputVisibleImpl = { [weak self] in
self?.afterLayout({
guard let strongSelf = self else {
return
}
var selectedItemNode: ListViewItemNode?
strongSelf.listNode.forEachItemNode { itemNode in
if let itemNode = itemNode as? BotCheckoutTipItemNode {
selectedItemNode = itemNode
}
}
if let selectedItemNode = selectedItemNode {
strongSelf.listNode.ensureItemNodeVisible(selectedItemNode, atTop: true)
}
})
}
openPaymentMethodImpl = { [weak self] in
if let strongSelf = self, let paymentForm = strongSelf.paymentFormValue {
@ -811,6 +842,9 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
self.formRequestDisposable = (formAndMaybeValidatedInfo |> deliverOnMainQueue).start(next: { [weak self] form, validatedInfo in
if let strongSelf = self {
UIView.transition(with: strongSelf.view, duration: 0.25, options: UIView.AnimationOptions.transitionCrossDissolve, animations: {
}, completion: nil)
let savedInfo: BotPaymentRequestedInfo
if let current = form.savedInfo {
savedInfo = current
@ -868,13 +902,26 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
}
self.actionButtonPanelNode.isHidden = false
}
private func updateIsInProgress(_ value: Bool) {
if value {
if self.statusController == nil {
let statusController = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil))
self.statusController = statusController
self.controller?.present(statusController, in: .window(.root))
}
} else if let statusController = self.statusController {
self.statusController = nil
statusController.dismiss()
}
}
override func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition, additionalInsets: UIEdgeInsets) {
var updatedInsets = layout.intrinsicInsets
let bottomPanelHorizontalInset: CGFloat = 16.0
let bottomPanelVerticalInset: CGFloat = 16.0
let bottomPanelHeight = updatedInsets.bottom + bottomPanelVerticalInset * 2.0 + BotCheckoutActionButton.height
let bottomPanelHeight = max(updatedInsets.bottom, layout.inputHeight ?? 0.0) + bottomPanelVerticalInset * 2.0 + BotCheckoutActionButton.height
transition.updateFrame(node: self.actionButtonPanelNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - bottomPanelHeight), size: CGSize(width: layout.size.width, height: bottomPanelHeight)))
transition.updateFrame(node: self.actionButtonPanelSeparator, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: layout.size.width, height: UIScreenPixel)))
@ -1088,11 +1135,19 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
self.inProgressDimNode.alpha = 1.0
self.actionButton.isEnabled = false
self.updateActionButton()
self.payDisposable.set((sendBotPaymentForm(account: self.context.account, messageId: self.messageId, formId: paymentForm.id, validatedInfoId: self.currentValidatedFormInfo?.id, shippingOptionId: self.currentShippingOptionId, tipAmount: self.currentTipAmount, credentials: credentials) |> deliverOnMainQueue).start(next: { [weak self] result in
self.updateIsInProgress(true)
var tipAmount = self.currentTipAmount
if tipAmount == nil, let _ = paymentForm.invoice.tip {
tipAmount = 0
}
self.payDisposable.set((sendBotPaymentForm(account: self.context.account, messageId: self.messageId, formId: paymentForm.id, validatedInfoId: self.currentValidatedFormInfo?.id, shippingOptionId: self.currentShippingOptionId, tipAmount: tipAmount, credentials: credentials) |> deliverOnMainQueue).start(next: { [weak self] result in
if let strongSelf = self {
strongSelf.inProgressDimNode.isUserInteractionEnabled = false
strongSelf.inProgressDimNode.alpha = 0.0
strongSelf.actionButton.isEnabled = true
strongSelf.updateIsInProgress(false)
if let applePayAuthrorizationCompletion = strongSelf.applePayAuthrorizationCompletion {
strongSelf.applePayAuthrorizationCompletion = nil
applePayAuthrorizationCompletion(.success)
@ -1124,6 +1179,7 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
strongSelf.inProgressDimNode.alpha = 0.0
strongSelf.actionButton.isEnabled = true
strongSelf.updateActionButton()
strongSelf.updateIsInProgress(false)
if let applePayAuthrorizationCompletion = strongSelf.applePayAuthrorizationCompletion {
strongSelf.applePayAuthrorizationCompletion = nil
applePayAuthrorizationCompletion(.failure)

View File

@ -18,12 +18,13 @@ class BotCheckoutTipItem: ListViewItem, ItemListItem {
let maxValue: Int64
let availableVariants: [(String, Int64)]
let updateValue: (Int64) -> Void
let updatedFocus: (Bool) -> Void
let sectionId: ItemListSectionId
let requestsNoInset: Bool = true
init(theme: PresentationTheme, strings: PresentationStrings, title: String, currency: String, value: String, numericValue: Int64, maxValue: Int64, availableVariants: [(String, Int64)], sectionId: ItemListSectionId, updateValue: @escaping (Int64) -> Void) {
init(theme: PresentationTheme, strings: PresentationStrings, title: String, currency: String, value: String, numericValue: Int64, maxValue: Int64, availableVariants: [(String, Int64)], sectionId: ItemListSectionId, updateValue: @escaping (Int64) -> Void, updatedFocus: @escaping (Bool) -> Void) {
self.theme = theme
self.strings = strings
self.title = title
@ -33,6 +34,7 @@ class BotCheckoutTipItem: ListViewItem, ItemListItem {
self.maxValue = maxValue
self.availableVariants = availableVariants
self.updateValue = updateValue
self.updatedFocus = updatedFocus
self.sectionId = sectionId
}
@ -264,6 +266,18 @@ class BotCheckoutTipItemNode: ListViewItemNode, UITextFieldDelegate {
strongSelf.textNode.clipsToBounds = true
strongSelf.textNode.textField.delegate = strongSelf.formatterDelegate
/*let toolbar: UIToolbar = UIToolbar()
toolbar.tintColor = item.theme.rootController.navigationBar.accentTextColor
toolbar.barTintColor = item.theme.rootController.navigationBar.backgroundColor
toolbar.barStyle = .default
toolbar.items = [
UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil),
UIBarButtonItem(title: item.strings.Common_Done, style: .done, target: strongSelf, action: #selector(strongSelf.dismissKeyboard))
]
toolbar.sizeToFit()
strongSelf.textNode.textField.inputAccessoryView = toolbar*/
}
strongSelf.textNode.textField.typingAttributes = [NSAttributedString.Key.font: titleFont]
@ -273,6 +287,7 @@ class BotCheckoutTipItemNode: ListViewItemNode, UITextFieldDelegate {
strongSelf.textNode.textField.textAlignment = .right
strongSelf.textNode.textField.keyboardAppearance = item.theme.rootController.keyboardColor.keyboardAppearance
strongSelf.textNode.textField.keyboardType = .decimalPad
strongSelf.textNode.textField.returnKeyType = .next
strongSelf.textNode.textField.tintColor = item.theme.list.itemAccentColor
var textInputFrame = CGRect(origin: CGPoint(x: params.width - leftInset - 150.0, y: -2.0), size: CGSize(width: 150.0, height: labelsContentHeight))
@ -370,6 +385,10 @@ class BotCheckoutTipItemNode: ListViewItemNode, UITextFieldDelegate {
}
}
@objc private func dismissKeyboard() {
self.textNode.textField.resignFirstResponder()
}
@objc private func textFieldTextChanged(_ textField: UITextField) {
let text = textField.text ?? ""
self.labelNode.isHidden = !text.isEmpty
@ -419,6 +438,8 @@ class BotCheckoutTipItemNode: ListViewItemNode, UITextFieldDelegate {
@objc public func textFieldDidBeginEditing(_ textField: UITextField) {
textField.selectedTextRange = textField.textRange(from: textField.endOfDocument, to: textField.endOfDocument)
self.item?.updatedFocus(true)
}
@objc public func textFieldDidChangeSelection(_ textField: UITextField) {

View File

@ -276,7 +276,9 @@ final class BotReceiptControllerNode: ItemListControllerNode {
private let receiptData = Promise<(BotPaymentInvoice, BotPaymentRequestedInfo?, BotPaymentShippingOption?, String?, TelegramMediaInvoice, Int64?)?>(nil)
private var dataRequestDisposable: Disposable?
private let actionButtonPanelNode: ASDisplayNode
private let actionButtonPanelSeparator: ASDisplayNode
private let actionButton: BotCheckoutActionButton
init(controller: ItemListController?, navigationBar: NavigationBar, updateNavigationOffset: @escaping (CGFloat) -> Void, context: AccountContext, messageId: MessageId, dismissAnimated: @escaping () -> Void) {
@ -293,6 +295,12 @@ final class BotReceiptControllerNode: ItemListControllerNode {
return (ItemListPresentationData(presentationData), (nodeState, arguments))
}
self.actionButtonPanelNode = ASDisplayNode()
self.actionButtonPanelNode.backgroundColor = self.presentationData.theme.rootController.navigationBar.backgroundColor
self.actionButtonPanelSeparator = ASDisplayNode()
self.actionButtonPanelSeparator.backgroundColor = self.presentationData.theme.rootController.navigationBar.separatorColor
self.actionButton = BotCheckoutActionButton(inactiveFillColor: self.presentationData.theme.list.plainBackgroundColor, activeFillColor: self.presentationData.theme.list.itemAccentColor, foregroundColor: self.presentationData.theme.list.plainBackgroundColor)
self.actionButton.setState(.active(self.presentationData.strings.Common_Done))
@ -301,12 +309,18 @@ final class BotReceiptControllerNode: ItemListControllerNode {
self.dataRequestDisposable = (requestBotPaymentReceipt(account: context.account, messageId: messageId) |> deliverOnMainQueue).start(next: { [weak self] receipt in
if let strongSelf = self {
UIView.transition(with: strongSelf.view, duration: 0.25, options: UIView.AnimationOptions.transitionCrossDissolve, animations: {
}, completion: nil)
strongSelf.receiptData.set(.single((receipt.invoice, receipt.info, receipt.shippingOption, receipt.credentialsTitle, receipt.invoiceMedia, receipt.tipAmount)))
}
})
self.actionButton.addTarget(self, action: #selector(self.actionButtonPressed), forControlEvents: .touchUpInside)
self.addSubnode(self.actionButton)
self.addSubnode(self.actionButtonPanelNode)
self.actionButtonPanelNode.addSubnode(self.actionButtonPanelSeparator)
self.actionButtonPanelNode.addSubnode(self.actionButton)
}
deinit {
@ -315,13 +329,21 @@ final class BotReceiptControllerNode: ItemListControllerNode {
override func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition, additionalInsets: UIEdgeInsets) {
var updatedInsets = layout.intrinsicInsets
updatedInsets.bottom += BotCheckoutActionButton.height + 16.0 * 2.0
super.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: updatedInsets, safeInsets: layout.safeInsets, additionalInsets: layout.additionalInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), navigationBarHeight: navigationBarHeight, transition: transition, additionalInsets: additionalInsets)
let actionButtonFrame = CGRect(origin: CGPoint(x: 16.0, y: layout.size.height - 16.0 - BotCheckoutActionButton.height - layout.intrinsicInsets.bottom), size: CGSize(width: layout.size.width - 16.0 * 2.0, height: BotCheckoutActionButton.height))
let bottomPanelHorizontalInset: CGFloat = 16.0
let bottomPanelVerticalInset: CGFloat = 16.0
let bottomPanelHeight = max(updatedInsets.bottom, layout.inputHeight ?? 0.0) + bottomPanelVerticalInset * 2.0 + BotCheckoutActionButton.height
transition.updateFrame(node: self.actionButtonPanelNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - bottomPanelHeight), size: CGSize(width: layout.size.width, height: bottomPanelHeight)))
transition.updateFrame(node: self.actionButtonPanelSeparator, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: layout.size.width, height: UIScreenPixel)))
let actionButtonFrame = CGRect(origin: CGPoint(x: bottomPanelHorizontalInset, y: bottomPanelVerticalInset), size: CGSize(width: layout.size.width - bottomPanelHorizontalInset * 2.0, height: BotCheckoutActionButton.height))
transition.updateFrame(node: self.actionButton, frame: actionButtonFrame)
self.actionButton.updateLayout(size: actionButtonFrame.size, transition: transition)
updatedInsets.bottom = bottomPanelHeight
super.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: updatedInsets, safeInsets: layout.safeInsets, additionalInsets: layout.additionalInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), navigationBarHeight: navigationBarHeight, transition: transition, additionalInsets: additionalInsets)
}
@objc func actionButtonPressed() {

View File

@ -4024,13 +4024,21 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
}
}
public func ensureItemNodeVisible(_ node: ListViewItemNode, animated: Bool = true, overflow: CGFloat = 0.0, allowIntersection: Bool = false, curve: ListViewAnimationCurve = .Default(duration: 0.25)) {
public func ensureItemNodeVisible(_ node: ListViewItemNode, animated: Bool = true, overflow: CGFloat = 0.0, allowIntersection: Bool = false, atTop: Bool = false, curve: ListViewAnimationCurve = .Default(duration: 0.25)) {
if let index = node.index {
if node.apparentHeight > self.visibleSize.height - self.insets.top - self.insets.bottom {
if node.frame.maxY > self.visibleSize.height - self.insets.bottom {
self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: ListViewDeleteAndInsertOptions(), scrollToItem: ListViewScrollToItem(index: index, position: ListViewScrollPosition.bottom(-overflow), animated: animated, curve: curve, directionHint: ListViewScrollToItemDirectionHint.Down), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
} else if node.frame.minY < self.insets.top && overflow > 0.0 {
self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: ListViewDeleteAndInsertOptions(), scrollToItem: ListViewScrollToItem(index: index, position: ListViewScrollPosition.top(-overflow), animated: animated, curve: curve, directionHint: ListViewScrollToItemDirectionHint.Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
if atTop {
if node.frame.maxY > self.visibleSize.height - self.insets.bottom {
self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: ListViewDeleteAndInsertOptions(), scrollToItem: ListViewScrollToItem(index: index, position: ListViewScrollPosition.top(-overflow), animated: animated, curve: curve, directionHint: ListViewScrollToItemDirectionHint.Down), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
} else if node.frame.minY < self.insets.top && overflow > 0.0 {
self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: ListViewDeleteAndInsertOptions(), scrollToItem: ListViewScrollToItem(index: index, position: ListViewScrollPosition.top(-overflow), animated: animated, curve: curve, directionHint: ListViewScrollToItemDirectionHint.Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
}
} else {
if node.frame.maxY > self.visibleSize.height - self.insets.bottom {
self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: ListViewDeleteAndInsertOptions(), scrollToItem: ListViewScrollToItem(index: index, position: ListViewScrollPosition.bottom(-overflow), animated: animated, curve: curve, directionHint: ListViewScrollToItemDirectionHint.Down), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
} else if node.frame.minY < self.insets.top && overflow > 0.0 {
self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: ListViewDeleteAndInsertOptions(), scrollToItem: ListViewScrollToItem(index: index, position: ListViewScrollPosition.top(-overflow), animated: animated, curve: curve, directionHint: ListViewScrollToItemDirectionHint.Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
}
}
} else {
if self.experimentalSnapScrollToItem {

View File

@ -79,7 +79,7 @@ public enum GetCurrentGroupCallError {
case generic
}
public func getCurrentGroupCall(account: Account, callId: Int64, accessHash: Int64) -> Signal<GroupCallSummary?, GetCurrentGroupCallError> {
public func getCurrentGroupCall(account: Account, callId: Int64, accessHash: Int64, peerId: PeerId? = nil) -> Signal<GroupCallSummary?, GetCurrentGroupCallError> {
return account.network.request(Api.functions.phone.getGroupCall(call: .inputGroupCall(id: callId, accessHash: accessHash)))
|> mapError { _ -> GetCurrentGroupCallError in
return .generic
@ -92,6 +92,7 @@ public func getCurrentGroupCall(account: Account, callId: Int64, accessHash: Int
return nil
}
var peers: [Peer] = []
var peerPresences: [PeerId: PeerPresence] = [:]
@ -108,6 +109,17 @@ public func getCurrentGroupCall(account: Account, callId: Int64, accessHash: Int
peers.append(peer)
}
}
if let peerId = peerId {
transaction.updatePeerCachedData(peerIds: [peerId], update: { _, current in
if let cachedData = current as? CachedChannelData {
return cachedData.withUpdatedActiveCall(CachedChannelData.ActiveCall.init(id: info.id, accessHash: info.accessHash, title: info.title, scheduleTimestamp: info.scheduleTimestamp, subscribedToScheduled: cachedData.activeCall?.subscribedToScheduled ?? false))
} else if let cachedData = current as? CachedGroupData {
return cachedData.withUpdatedActiveCall(CachedChannelData.ActiveCall(id: info.id, accessHash: info.accessHash, title: info.title, scheduleTimestamp: info.scheduleTimestamp, subscribedToScheduled: cachedData.activeCall?.subscribedToScheduled ?? false))
} else {
return current
}
})
}
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
return updated