mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Various improvements
This commit is contained in:
parent
57e35638d0
commit
699c703c94
@ -3330,7 +3330,9 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
replaceImpl = { [weak controller] c in
|
||||
controller?.replace(with: c)
|
||||
}
|
||||
strongSelf.push(controller)
|
||||
if let navigationController = strongSelf.context.sharedContext.mainWindow?.viewController as? NavigationController {
|
||||
navigationController.pushViewController(controller)
|
||||
}
|
||||
} else {
|
||||
strongSelf.selectTab(id: .filter(id))
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ final class AppIconsDemoComponent: Component {
|
||||
|
||||
self.component = component
|
||||
|
||||
self.containerView.frame = CGRect(origin: .zero, size: availableSize)
|
||||
self.containerView.frame = CGRect(origin: CGPoint(x: -availableSize.width / 2.0, y: 0.0), size: CGSize(width: availableSize.width * 2.0, height: availableSize.height))
|
||||
|
||||
if self.imageViews.isEmpty {
|
||||
for icon in component.appIcons {
|
||||
@ -68,6 +68,9 @@ final class AppIconsDemoComponent: Component {
|
||||
let imageView = UIImageView(frame: CGRect(origin: .zero, size: CGSize(width: 90.0, height: 90.0)))
|
||||
imageView.clipsToBounds = true
|
||||
imageView.layer.cornerRadius = 24.0
|
||||
if #available(iOS 13.0, *) {
|
||||
imageView.layer.cornerCurve = .continuous
|
||||
}
|
||||
imageView.image = image
|
||||
self.containerView.addSubview(imageView)
|
||||
|
||||
@ -90,7 +93,7 @@ final class AppIconsDemoComponent: Component {
|
||||
position = CGPoint(x: availableSize.width * 0.5, y: availableSize.height * 0.5)
|
||||
}
|
||||
|
||||
view.center = position
|
||||
view.center = position.offsetBy(dx: availableSize.width / 2.0, dy: 0.0)
|
||||
|
||||
i += 1
|
||||
}
|
||||
@ -105,10 +108,6 @@ final class AppIconsDemoComponent: Component {
|
||||
}
|
||||
|
||||
if isDisplaying && !self.isVisible {
|
||||
// var fast = false
|
||||
// if let _ = transition.userData(DemoAnimateInTransition.self) {
|
||||
// fast = true
|
||||
// }
|
||||
self.animateIn(availableSize: availableSize)
|
||||
}
|
||||
self.isVisible = isDisplaying
|
||||
@ -126,10 +125,10 @@ final class AppIconsDemoComponent: Component {
|
||||
from = CGPoint(x: -availableSize.width * 0.333, y: -availableSize.height * 0.8)
|
||||
delay = 0.1
|
||||
case 1:
|
||||
from = CGPoint(x: -availableSize.width * 0.75, y: availableSize.height * 0.75)
|
||||
from = CGPoint(x: -availableSize.width * 0.55, y: availableSize.height * 0.75)
|
||||
delay = 0.15
|
||||
case 2:
|
||||
from = CGPoint(x: availableSize.width * 0.9, y: availableSize.height * 0.0)
|
||||
from = CGPoint(x: availableSize.width * 0.9, y: availableSize.height * 0.75)
|
||||
delay = 0.0
|
||||
default:
|
||||
from = CGPoint(x: availableSize.width * 0.5, y: availableSize.height * 0.5)
|
||||
|
@ -990,7 +990,11 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
|
||||
switch perk {
|
||||
case .doubleLimits:
|
||||
let controller = PremimLimitsListScreen(context: accountContext, buttonText: isPremium ? strings.Common_OK : strings.Premium_SubscribeFor(state?.price ?? "–").string, isPremium: isPremium)
|
||||
controller.disposed = {
|
||||
updateIsFocused(false)
|
||||
}
|
||||
present(controller)
|
||||
updateIsFocused(true)
|
||||
return
|
||||
case .moreUpload:
|
||||
demoSubject = .moreUpload
|
||||
@ -1261,13 +1265,15 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
|
||||
let source: PremiumSource
|
||||
let updateInProgress: (Bool) -> Void
|
||||
let present: (ViewController) -> Void
|
||||
let push: (ViewController) -> Void
|
||||
let completion: () -> Void
|
||||
|
||||
init(context: AccountContext, source: PremiumSource, updateInProgress: @escaping (Bool) -> Void, present: @escaping (ViewController) -> Void, completion: @escaping () -> Void) {
|
||||
init(context: AccountContext, source: PremiumSource, updateInProgress: @escaping (Bool) -> Void, present: @escaping (ViewController) -> Void, push: @escaping (ViewController) -> Void, completion: @escaping () -> Void) {
|
||||
self.context = context
|
||||
self.source = source
|
||||
self.updateInProgress = updateInProgress
|
||||
self.present = present
|
||||
self.push = push
|
||||
self.completion = completion
|
||||
}
|
||||
|
||||
@ -1284,6 +1290,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
|
||||
final class State: ComponentState {
|
||||
private let context: AccountContext
|
||||
private let updateInProgress: (Bool) -> Void
|
||||
private let present: (ViewController) -> Void
|
||||
private let completion: () -> Void
|
||||
|
||||
var topContentOffset: CGFloat?
|
||||
@ -1300,9 +1307,10 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
|
||||
private var paymentDisposable = MetaDisposable()
|
||||
private var activationDisposable = MetaDisposable()
|
||||
|
||||
init(context: AccountContext, source: PremiumSource, updateInProgress: @escaping (Bool) -> Void, completion: @escaping () -> Void) {
|
||||
init(context: AccountContext, source: PremiumSource, updateInProgress: @escaping (Bool) -> Void, present: @escaping (ViewController) -> Void, completion: @escaping () -> Void) {
|
||||
self.context = context
|
||||
self.updateInProgress = updateInProgress
|
||||
self.present = present
|
||||
self.completion = completion
|
||||
|
||||
super.init()
|
||||
@ -1356,34 +1364,45 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
|
||||
self.updateInProgress(true)
|
||||
self.updated(transition: .immediate)
|
||||
|
||||
self.paymentDisposable.set((inAppPurchaseManager.buyProduct(premiumProduct, account: self.context.account)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] status in
|
||||
if let strongSelf = self, case let .purchased(transactionId) = status {
|
||||
strongSelf.activationDisposable.set((strongSelf.context.engine.payments.assignAppStoreTransaction(transactionId: transactionId)
|
||||
|> deliverOnMainQueue).start(error: { _ in
|
||||
|
||||
}, completed: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.isPremium = true
|
||||
strongSelf.updated(transition: .easeInOut(duration: 0.25))
|
||||
strongSelf.completion()
|
||||
}
|
||||
}))
|
||||
}
|
||||
}, error: { [weak self] error in
|
||||
let _ = (self.context.engine.payments.canPurchasePremium()
|
||||
|> deliverOnMainQueue).start(next: { [weak self] available in
|
||||
if let strongSelf = self {
|
||||
strongSelf.inProgress = false
|
||||
strongSelf.updateInProgress(false)
|
||||
strongSelf.updated(transition: .immediate)
|
||||
|
||||
switch error {
|
||||
case .generic:
|
||||
addAppLogEvent(postbox: strongSelf.context.account.postbox, type: "premium.promo_screen_fail")
|
||||
case .cancelled:
|
||||
break
|
||||
if available {
|
||||
strongSelf.paymentDisposable.set((inAppPurchaseManager.buyProduct(premiumProduct, account: strongSelf.context.account)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] status in
|
||||
if let strongSelf = self, case let .purchased(transactionId) = status {
|
||||
strongSelf.activationDisposable.set((strongSelf.context.engine.payments.assignAppStoreTransaction(transactionId: transactionId)
|
||||
|> deliverOnMainQueue).start(error: { _ in
|
||||
|
||||
}, completed: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.isPremium = true
|
||||
strongSelf.updated(transition: .easeInOut(duration: 0.25))
|
||||
strongSelf.completion()
|
||||
}
|
||||
}))
|
||||
}
|
||||
}, error: { [weak self] error in
|
||||
if let strongSelf = self {
|
||||
strongSelf.inProgress = false
|
||||
strongSelf.updateInProgress(false)
|
||||
strongSelf.updated(transition: .immediate)
|
||||
|
||||
switch error {
|
||||
case .generic:
|
||||
addAppLogEvent(postbox: strongSelf.context.account.postbox, type: "premium.promo_screen_fail")
|
||||
case .cancelled:
|
||||
break
|
||||
}
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
strongSelf.inProgress = false
|
||||
strongSelf.updateInProgress(false)
|
||||
strongSelf.updated(transition: .immediate)
|
||||
}
|
||||
}
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
func updateIsFocused(_ isFocused: Bool) {
|
||||
@ -1393,7 +1412,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
|
||||
}
|
||||
|
||||
func makeState() -> State {
|
||||
return State(context: self.context, source: self.source, updateInProgress: self.updateInProgress, completion: self.completion)
|
||||
return State(context: self.context, source: self.source, updateInProgress: self.updateInProgress, present: self.present, completion: self.completion)
|
||||
}
|
||||
|
||||
static var body: Body {
|
||||
@ -1694,6 +1713,7 @@ public final class PremiumIntroScreen: ViewControllerComponentContainer {
|
||||
self.context = context
|
||||
|
||||
var updateInProgressImpl: ((Bool) -> Void)?
|
||||
var pushImpl: ((ViewController) -> Void)?
|
||||
var presentImpl: ((ViewController) -> Void)?
|
||||
var completionImpl: (() -> Void)?
|
||||
super.init(context: context, component: PremiumIntroScreenComponent(
|
||||
@ -1705,6 +1725,9 @@ public final class PremiumIntroScreen: ViewControllerComponentContainer {
|
||||
present: { c in
|
||||
presentImpl?(c)
|
||||
},
|
||||
push: { c in
|
||||
pushImpl?(c)
|
||||
},
|
||||
completion: {
|
||||
completionImpl?()
|
||||
}
|
||||
@ -1729,6 +1752,10 @@ public final class PremiumIntroScreen: ViewControllerComponentContainer {
|
||||
}
|
||||
|
||||
presentImpl = { [weak self] c in
|
||||
self?.present(c, in: .window(.root))
|
||||
}
|
||||
|
||||
pushImpl = { [weak self] c in
|
||||
self?.push(c)
|
||||
}
|
||||
|
||||
|
@ -891,6 +891,8 @@ public class PremimLimitsListScreen: ViewController {
|
||||
private let buttonText: String
|
||||
private let buttonGloss: Bool
|
||||
|
||||
var disposed: () -> Void = {}
|
||||
|
||||
public convenience init(context: AccountContext, buttonText: String, isPremium: Bool) {
|
||||
var expandImpl: (() -> Void)?
|
||||
self.init(context: context, component: PremimLimitsListScreenComponent(context: context, expand: {
|
||||
@ -935,6 +937,10 @@ public class PremimLimitsListScreen: ViewController {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.disposed()
|
||||
}
|
||||
|
||||
@objc private func cancelPressed() {
|
||||
self.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import AccountContext
|
||||
import AnimatedStickerNode
|
||||
import TelegramAnimatedStickerNode
|
||||
import ShimmerEffect
|
||||
import StickerResources
|
||||
|
||||
final class StickersCarouselComponent: Component {
|
||||
public typealias EnvironmentType = DemoPageEnvironment
|
||||
@ -104,6 +105,7 @@ private class StickerNode: ASDisplayNode {
|
||||
|
||||
if file.isPremiumSticker {
|
||||
let animationNode = AnimatedStickerNode()
|
||||
animationNode.automaticallyLoadFirstFrame = true
|
||||
self.animationNode = animationNode
|
||||
|
||||
let dimensions = file.dimensions ?? PixelDimensions(width: 512, height: 512)
|
||||
@ -112,6 +114,8 @@ private class StickerNode: ASDisplayNode {
|
||||
let pathPrefix = context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(file.resource.id)
|
||||
animationNode.setup(source: AnimatedStickerResourceSource(account: self.context.account, resource: file.resource, isVideo: file.isVideoSticker), width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), playbackMode: .loop, mode: .direct(cachePathPrefix: pathPrefix))
|
||||
|
||||
self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: context.account.postbox, file: file, small: false, size: fittedDimensions))
|
||||
|
||||
self.disposable.set(freeMediaFileResourceInteractiveFetched(account: self.context.account, fileReference: .standalone(media: file), resource: file.resource).start())
|
||||
|
||||
if let effect = file.videoThumbnails.first {
|
||||
@ -134,10 +138,9 @@ private class StickerNode: ASDisplayNode {
|
||||
|
||||
self.isUserInteractionEnabled = false
|
||||
|
||||
self.addSubnode(self.imageNode)
|
||||
if let animationNode = self.animationNode {
|
||||
self.addSubnode(animationNode)
|
||||
} else {
|
||||
self.addSubnode(self.imageNode)
|
||||
}
|
||||
|
||||
if let additionalAnimationNode = self.additionalAnimationNode {
|
||||
@ -254,7 +257,7 @@ private class StickerNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
let placeholderFrame = CGRect(origin: .zero, size: size)
|
||||
let placeholderFrame = CGRect(origin: .zero, size: imageSize)
|
||||
let thumbnailDimensions = PixelDimensions(width: 512, height: 512)
|
||||
self.placeholderNode.update(backgroundColor: nil, foregroundColor: UIColor(rgb: 0xffffff, alpha: 0.2), shimmeringColor: UIColor(rgb: 0xffffff, alpha: 0.3), data: self.file.immediateThumbnailData, size: placeholderFrame.size, imageSize: thumbnailDimensions.cgSize)
|
||||
self.placeholderNode.frame = placeholderFrame
|
||||
@ -266,7 +269,7 @@ private class StickersCarouselNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
private let context: AccountContext
|
||||
private let stickers: [TelegramMediaFile]
|
||||
private var itemContainerNodes: [ASDisplayNode] = []
|
||||
private var itemNodes: [StickerNode] = []
|
||||
private var itemNodes: [Int: StickerNode] = [:]
|
||||
private let scrollNode: ASScrollNode
|
||||
private let tapNode: ASDisplayNode
|
||||
|
||||
@ -299,7 +302,13 @@ private class StickersCarouselNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
self.addSubnode(self.scrollNode)
|
||||
self.scrollNode.addSubnode(self.tapNode)
|
||||
|
||||
self.setup()
|
||||
for _ in self.stickers {
|
||||
let containerNode = ASDisplayNode()
|
||||
containerNode.isUserInteractionEnabled = false
|
||||
self.addSubnode(containerNode)
|
||||
|
||||
self.itemContainerNodes.append(containerNode)
|
||||
}
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
@ -351,7 +360,7 @@ private class StickersCarouselNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
}
|
||||
|
||||
func scrollTo(_ index: Int, playAnimation: Bool, duration: Double, clockwise: Bool? = nil) {
|
||||
guard index >= 0 && index < self.itemNodes.count else {
|
||||
guard index >= 0 && index < self.stickers.count else {
|
||||
return
|
||||
}
|
||||
self.currentIndex = index
|
||||
@ -411,19 +420,6 @@ private class StickersCarouselNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func setup() {
|
||||
for sticker in self.stickers {
|
||||
let containerNode = ASDisplayNode()
|
||||
let itemNode = StickerNode(context: self.context, file: sticker)
|
||||
containerNode.isUserInteractionEnabled = false
|
||||
containerNode.addSubnode(itemNode)
|
||||
self.addSubnode(containerNode)
|
||||
|
||||
self.itemContainerNodes.append(containerNode)
|
||||
self.itemNodes.append(itemNode)
|
||||
}
|
||||
}
|
||||
|
||||
private var ignoreContentOffsetChange = false
|
||||
private func resetScrollPosition() {
|
||||
self.scrollStartPosition = nil
|
||||
@ -434,14 +430,13 @@ private class StickersCarouselNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
|
||||
func playSelectedSticker() {
|
||||
let delta = self.positionDelta
|
||||
let index = max(0, Int(round(self.currentPosition / delta)) % self.itemNodes.count)
|
||||
let index = max(0, Int(round(self.currentPosition / delta)) % self.stickers.count)
|
||||
|
||||
guard !self.playingIndices.contains(index) else {
|
||||
return
|
||||
}
|
||||
|
||||
for i in 0 ..< self.itemNodes.count {
|
||||
let itemNode = self.itemNodes[i]
|
||||
for (i, itemNode) in self.itemNodes {
|
||||
let containerNode = self.itemContainerNodes[i]
|
||||
let isCentral = i == index
|
||||
itemNode.setCentral(isCentral)
|
||||
@ -461,7 +456,7 @@ private class StickersCarouselNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
self.scrollStartPosition = (scrollView.contentOffset.y, self.currentPosition)
|
||||
}
|
||||
|
||||
for itemNode in self.itemNodes {
|
||||
for (_, itemNode) in self.itemNodes {
|
||||
itemNode.setCentral(false)
|
||||
}
|
||||
}
|
||||
@ -493,7 +488,7 @@ private class StickersCarouselNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
self.currentPosition = updatedPosition
|
||||
|
||||
let indexDelta = self.positionDelta
|
||||
let index = max(0, Int(round(self.currentPosition / indexDelta)) % self.itemNodes.count)
|
||||
let index = max(0, Int(round(self.currentPosition / indexDelta)) % self.stickers.count)
|
||||
if index != self.currentIndex {
|
||||
self.currentIndex = index
|
||||
if self.scrollNode.view.isTracking || self.scrollNode.view.isDecelerating {
|
||||
@ -528,7 +523,7 @@ private class StickersCarouselNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
self.resetScrollPosition()
|
||||
|
||||
let delta = self.positionDelta
|
||||
let index = max(0, Int(round(self.currentPosition / delta)) % self.itemNodes.count)
|
||||
let index = max(0, Int(round(self.currentPosition / delta)) % self.stickers.count)
|
||||
self.scrollTo(index, playAnimation: true, duration: 0.2)
|
||||
}
|
||||
}
|
||||
@ -555,8 +550,7 @@ private class StickersCarouselNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
let bounds = CGRect(origin: .zero, size: size)
|
||||
let areaSize = CGSize(width: floor(size.width * 4.0), height: size.height * 2.2)
|
||||
|
||||
for i in 0 ..< self.itemNodes.count {
|
||||
let itemNode = self.itemNodes[i]
|
||||
for i in 0 ..< self.stickers.count {
|
||||
let containerNode = self.itemContainerNodes[i]
|
||||
|
||||
var angle = CGFloat.pi * 0.5 + CGFloat(i) * delta * CGFloat.pi * 2.0 - self.currentPosition * CGFloat.pi * 2.0 - CGFloat.pi * 0.5
|
||||
@ -588,13 +582,28 @@ private class StickersCarouselNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
containerNode.position = CGPoint(x: itemFrame.midX, y: itemFrame.midY)
|
||||
transition.updateTransformScale(node: containerNode, scale: 1.0 - distance * 0.75)
|
||||
transition.updateAlpha(node: containerNode, alpha: 1.0 - distance * 0.6)
|
||||
itemNode.updateAbsoluteRect(itemFrame, within: size)
|
||||
|
||||
let isVisible = self.visibility && itemFrame.intersects(bounds)
|
||||
itemNode.setVisible(isVisible)
|
||||
|
||||
itemNode.frame = CGRect(origin: CGPoint(), size: itemFrame.size)
|
||||
itemNode.updateLayout(size: itemFrame.size, transition: transition)
|
||||
if isVisible {
|
||||
let itemNode: StickerNode
|
||||
if let current = self.itemNodes[i] {
|
||||
itemNode = current
|
||||
} else {
|
||||
itemNode = StickerNode(context: self.context, file: self.stickers[i])
|
||||
containerNode.addSubnode(itemNode)
|
||||
self.itemNodes[i] = itemNode
|
||||
}
|
||||
itemNode.updateAbsoluteRect(itemFrame, within: size)
|
||||
itemNode.setVisible(isVisible)
|
||||
|
||||
itemNode.frame = CGRect(origin: CGPoint(), size: itemFrame.size)
|
||||
itemNode.updateLayout(size: itemFrame.size, transition: transition)
|
||||
} else {
|
||||
if let itemNode = self.itemNodes[i] {
|
||||
itemNode.removeFromSupernode()
|
||||
self.itemNodes[i] = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6256,6 +6256,21 @@ public extension Api.functions.payments {
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.payments {
|
||||
static func canPurchasePremium() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-1435856696)
|
||||
|
||||
return (FunctionDescription(name: "payments.canPurchasePremium", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Bool?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.Bool
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.payments {
|
||||
static func clearSavedInfo(flags: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
let buffer = Buffer()
|
||||
@ -6366,6 +6381,36 @@ public extension Api.functions.payments {
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.payments {
|
||||
static func restoreAppStoreReceipt(receipt: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-2132923705)
|
||||
serializeBytes(receipt, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "payments.restoreAppStoreReceipt", parameters: [("receipt", String(describing: receipt))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Updates?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.Updates
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.payments {
|
||||
static func restorePlayMarketReceipt(receipt: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-781917334)
|
||||
serializeBytes(receipt, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "payments.restorePlayMarketReceipt", parameters: [("receipt", String(describing: receipt))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Updates?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.Updates
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.payments {
|
||||
static func sendPaymentForm(flags: Int32, formId: Int64, invoice: Api.InputInvoice, requestedInfoId: String?, shippingOptionId: String?, credentials: Api.InputPaymentCredentials, tipAmount: Int64?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.PaymentResult>) {
|
||||
let buffer = Buffer()
|
||||
|
@ -30,3 +30,18 @@ func _internal_assignAppStoreTransaction(account: Account, transactionId: String
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func _internal_canPurchasePremium(account: Account) -> Signal<Bool, NoError> {
|
||||
return account.network.request(Api.functions.payments.canPurchasePremium())
|
||||
|> map { result -> Bool in
|
||||
switch result {
|
||||
case .boolTrue:
|
||||
return true
|
||||
case .boolFalse:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|> `catch` { _ -> Signal<Bool, NoError> in
|
||||
return.single(false)
|
||||
}
|
||||
}
|
||||
|
@ -40,5 +40,9 @@ public extension TelegramEngine {
|
||||
public func assignAppStoreTransaction(transactionId: String) -> Signal<Never, AssignAppStoreTransactionError> {
|
||||
return _internal_assignAppStoreTransaction(account: self.account, transactionId: transactionId)
|
||||
}
|
||||
|
||||
public func canPurchasePremium() -> Signal<Bool, NoError> {
|
||||
return _internal_canPurchasePremium(account: self.account)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6266,7 +6266,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
replaceImpl = { [weak controller] c in
|
||||
controller?.replace(with: c)
|
||||
}
|
||||
self.controller?.push(controller)
|
||||
if let navigationController = context.sharedContext.mainWindow?.viewController as? NavigationController {
|
||||
navigationController.pushViewController(controller)
|
||||
}
|
||||
} else {
|
||||
self.context.sharedContext.beginNewAuth(testingEnvironment: self.context.account.testingEnvironment)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user