From eabf0985ef59bea5dde543427c80c9a223077046 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 12 Mar 2025 21:24:42 +0400 Subject: [PATCH] Various fixes --- .../Telegram-iOS/en.lproj/Localizable.strings | 1 + .../AccountContext/Sources/Premium.swift | 1 + .../Display/Source/TextAlertController.swift | 2 +- .../ChatMessagePaymentAlertController.swift | 16 ++- .../Sources/GiftOptionsScreen.swift | 134 ++++++++++++------ .../Components/Gifts/GiftViewScreen/BUILD | 1 + .../Sources/GiftTransferAlertController.swift | 15 +- .../Sources/GiftViewScreen.swift | 17 +-- .../Sources/PeerInfoGiftsPaneNode.swift | 21 ++- .../Sources/StarsPurchaseScreen.swift | 6 +- .../Sources/SharedAccountContext.swift | 130 +++++++++++------ 11 files changed, 225 insertions(+), 119 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 581f26d896..2e8b4b8d2b 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -13573,6 +13573,7 @@ Sorry for the inconvenience."; "FolderLinkPreview.ToastFolderAddedTitleV2" = "Folder {folder} Added"; "Stars.Purchase.UpgradeStarGiftInfo" = "Buy Stars to upgrade your gift into a unique collectible."; +"Stars.Purchase.TransferStarGiftInfo" = "Buy Stars to transfer ownership of your unique collectible."; "Gift.Send.Upgrade" = "Make Unique for %@"; "Gift.Send.Upgrade.Info" = "Enable this to let %1$@ turn your gift into a unique collectible. [Learn More >]()"; diff --git a/submodules/AccountContext/Sources/Premium.swift b/submodules/AccountContext/Sources/Premium.swift index 15277eccbc..743f40c3cb 100644 --- a/submodules/AccountContext/Sources/Premium.swift +++ b/submodules/AccountContext/Sources/Premium.swift @@ -136,6 +136,7 @@ public enum StarsPurchasePurpose: Equatable { case unlockMedia(requiredStars: Int64) case starGift(peerId: EnginePeer.Id, requiredStars: Int64) case upgradeStarGift(requiredStars: Int64) + case transferStarGift(requiredStars: Int64) case sendMessage(peerId: EnginePeer.Id, requiredStars: Int64) } diff --git a/submodules/Display/Source/TextAlertController.swift b/submodules/Display/Source/TextAlertController.swift index c8ddef511c..291446f04b 100644 --- a/submodules/Display/Source/TextAlertController.swift +++ b/submodules/Display/Source/TextAlertController.swift @@ -129,7 +129,7 @@ public final class TextAlertContentActionNode: HighlightableButtonNode { if let range = attributedString.string.range(of: "$") { attributedString.addAttribute(.attachment, value: UIImage(bundleImageName: "Item List/PremiumIcon")!, range: NSRange(range, in: attributedString.string)) attributedString.addAttribute(.foregroundColor, value: color, range: NSRange(range, in: attributedString.string)) - attributedString.addAttribute(.baselineOffset, value: 1.0, range: NSRange(range, in: attributedString.string)) + attributedString.addAttribute(.baselineOffset, value: 2.0, range: NSRange(range, in: attributedString.string)) } self.setAttributedTitle(attributedString, for: []) diff --git a/submodules/TelegramUI/Components/Chat/ChatMessagePaymentAlertController/Sources/ChatMessagePaymentAlertController.swift b/submodules/TelegramUI/Components/Chat/ChatMessagePaymentAlertController/Sources/ChatMessagePaymentAlertController.swift index 151913193d..75270b57dc 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessagePaymentAlertController/Sources/ChatMessagePaymentAlertController.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessagePaymentAlertController/Sources/ChatMessagePaymentAlertController.swift @@ -317,18 +317,20 @@ private final class ChatMessagePaymentAlertContentNode: AlertContentNode, ASGest } } -private class ChatMessagePaymentAlertController: AlertController { +public class ChatMessagePaymentAlertController: AlertController { private let context: AccountContext? private let presentationData: PresentationData private weak var parentNavigationController: NavigationController? - + private let showBalance: Bool + private let balance = ComponentView() - init(context: AccountContext?, presentationData: PresentationData, contentNode: AlertContentNode, navigationController: NavigationController?) { + public init(context: AccountContext?, presentationData: PresentationData, contentNode: AlertContentNode, navigationController: NavigationController?, showBalance: Bool = true) { self.context = context self.presentationData = presentationData self.parentNavigationController = navigationController - + self.showBalance = showBalance + super.init(theme: AlertControllerTheme(presentationData: presentationData), contentNode: contentNode) self.willDismiss = { [weak self] in @@ -350,16 +352,16 @@ private class ChatMessagePaymentAlertController: AlertController { } } - override func dismissAnimated() { + public override func dismissAnimated() { super.dismissAnimated() self.animateOut() } - override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { + public override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { super.containerLayoutUpdated(layout, transition: transition) - if let context = self.context, let _ = self.parentNavigationController { + if let context = self.context, let _ = self.parentNavigationController, self.showBalance { let insets = layout.insets(options: .statusBar) let balanceSize = self.balance.update( transition: .immediate, diff --git a/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift index ef5ec71c1e..b1c6b7a7ff 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift @@ -216,6 +216,8 @@ final class GiftOptionsScreenComponent: Component { private var starsStateDisposable: Disposable? private var starsState: StarsContext.State? + private let optionsPromise = Promise<[StarsTopUpOption]?>(nil) + private var component: GiftOptionsScreenComponent? private(set) weak var state: State? private var environment: EnvironmentType? @@ -508,59 +510,94 @@ final class GiftOptionsScreenComponent: Component { gift: transferGift, peer: peer, transferStars: gift.transferStars ?? 0, - commit: { [weak controller] in - let _ = (context.engine.payments.transferStarGift(prepaid: gift.transferStars == 0, reference: reference, peerId: peer.id) - |> deliverOnMainQueue).start() - - guard let controller, let navigationController = controller.navigationController as? NavigationController else { - return - } - - if peer.id.namespace == Namespaces.Peer.CloudChannel { - var controllers = navigationController.viewControllers - controllers = controllers.filter { !($0 is GiftSetupScreen) && !($0 is GiftOptionsScreenProtocol) } - var foundController = false - for controller in controllers.reversed() { - if let controller = controller as? PeerInfoScreen, controller.peerId == component.peerId { - foundController = true - break - } + navigationController: controller.navigationController as? NavigationController, + commit: { [weak self, weak controller] in + let proceed: (Bool) -> Void = { waitForTopUp in + if waitForTopUp, let starsContext = context.starsContext { + let _ = (starsContext.onUpdate + |> deliverOnMainQueue).start(next: { + let _ = (context.engine.payments.transferStarGift(prepaid: gift.transferStars == 0, reference: reference, peerId: peer.id) + |> deliverOnMainQueue).start() + }) + } else { + let _ = (context.engine.payments.transferStarGift(prepaid: gift.transferStars == 0, reference: reference, peerId: peer.id) + |> deliverOnMainQueue).start() } - if !foundController { - if let controller = context.sharedContext.makePeerInfoController( - context: context, - updatedPresentationData: nil, - peer: peer._asPeer(), - mode: .gifts, - avatarInitiallyExpanded: false, - fromChat: false, - requestsContext: nil - ) { - controllers.append(controller) - } + + guard let controller, let navigationController = controller.navigationController as? NavigationController else { + return } - navigationController.setViewControllers(controllers, animated: true) - } else { - var controllers = navigationController.viewControllers - controllers = controllers.filter { !($0 is GiftSetupScreen) && !($0 is GiftOptionsScreenProtocol) && !($0 is PeerInfoScreen) && !($0 is ContactSelectionController) } - var foundController = false - for controller in controllers.reversed() { - if let chatController = controller as? ChatController, case .peer(id: component.peerId) = chatController.chatLocation { + + if peer.id.namespace == Namespaces.Peer.CloudChannel { + var controllers = navigationController.viewControllers + controllers = controllers.filter { !($0 is GiftSetupScreen) && !($0 is GiftOptionsScreenProtocol) } + var foundController = false + for controller in controllers.reversed() { + if let controller = controller as? PeerInfoScreen, controller.peerId == component.peerId { + foundController = true + break + } + } + if !foundController { + if let controller = context.sharedContext.makePeerInfoController( + context: context, + updatedPresentationData: nil, + peer: peer._asPeer(), + mode: .gifts, + avatarInitiallyExpanded: false, + fromChat: false, + requestsContext: nil + ) { + controllers.append(controller) + } + } + navigationController.setViewControllers(controllers, animated: true) + } else { + var controllers = navigationController.viewControllers + controllers = controllers.filter { !($0 is GiftSetupScreen) && !($0 is GiftOptionsScreenProtocol) && !($0 is PeerInfoScreen) && !($0 is ContactSelectionController) } + var foundController = false + for controller in controllers.reversed() { + if let chatController = controller as? ChatController, case .peer(id: component.peerId) = chatController.chatLocation { + chatController.hintPlayNextOutgoingGift() + foundController = true + break + } + } + if !foundController { + let chatController = component.context.sharedContext.makeChatController(context: component.context, chatLocation: .peer(id: component.peerId), subject: nil, botStart: nil, mode: .standard(.default), params: nil) chatController.hintPlayNextOutgoingGift() - foundController = true - break + controllers.append(chatController) } + navigationController.setViewControllers(controllers, animated: true) } - if !foundController { - let chatController = component.context.sharedContext.makeChatController(context: component.context, chatLocation: .peer(id: component.peerId), subject: nil, botStart: nil, mode: .standard(.default), params: nil) - chatController.hintPlayNextOutgoingGift() - controllers.append(chatController) + if let completion = component.completion { + completion() } - navigationController.setViewControllers(controllers, animated: true) } - - if let completion = component.completion { - completion() + + if let self, let transferStars = gift.transferStars, transferStars > 0, let starsContext = context.starsContext, let starsState = self.starsState { + if starsState.balance < StarsAmount(value: transferStars, nanos: 0) { + let _ = (self.optionsPromise.get() + |> filter { $0 != nil } + |> take(1) + |> deliverOnMainQueue).startStandalone(next: { [weak controller] options in + let purchaseController = context.sharedContext.makeStarsPurchaseScreen( + context: context, + starsContext: starsContext, + options: options ?? [], + purpose: .transferStarGift(requiredStars: transferStars), + completion: { stars in + starsContext.add(balance: StarsAmount(value: stars, nanos: 0)) + proceed(true) + } + ) + controller?.push(purchaseController) + }) + } else { + proceed(false) + } + } else { + proceed(false) } } ) @@ -590,6 +627,11 @@ final class GiftOptionsScreenComponent: Component { self.state?.updated() } }) + + if let state = component.starsContext.currentState, state.balance < StarsAmount(value: 100, nanos: 0) { + self.optionsPromise.set(component.context.engine.payments.starsTopUpOptions() + |> map(Optional.init)) + } } self.component = component diff --git a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/BUILD b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/BUILD index ace4e1f471..66375077f3 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/BUILD +++ b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/BUILD @@ -49,6 +49,7 @@ swift_library( "//submodules/TelegramUI/Components/PeerManagement/OwnershipTransferController", "//submodules/TelegramUI/Components/PremiumLockButtonSubtitleComponent", "//submodules/TelegramUI/Components/Stars/StarsBalanceOverlayComponent", + "//submodules/TelegramUI/Components/Chat/ChatMessagePaymentAlertController", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftTransferAlertController.swift b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftTransferAlertController.swift index ffa0d3ffb8..91ccd670ac 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftTransferAlertController.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftTransferAlertController.swift @@ -12,6 +12,7 @@ import AppBundle import AvatarNode import Markdown import GiftItemComponent +import ChatMessagePaymentAlertController private final class GiftTransferAlertContentNode: AlertContentNode { private let context: AccountContext @@ -251,7 +252,14 @@ private final class GiftTransferAlertContentNode: AlertContentNode { } } -public func giftTransferAlertController(context: AccountContext, gift: StarGift.UniqueGift, peer: EnginePeer, transferStars: Int64, commit: @escaping () -> Void) -> AlertController { +public func giftTransferAlertController( + context: AccountContext, + gift: StarGift.UniqueGift, + peer: EnginePeer, + transferStars: Int64, + navigationController: NavigationController?, + commit: @escaping () -> Void +) -> AlertController { let presentationData = context.sharedContext.currentPresentationData.with { $0 } let strings = presentationData.strings @@ -267,7 +275,6 @@ public func giftTransferAlertController(context: AccountContext, gift: StarGift. } var dismissImpl: ((Bool) -> Void)? - var contentNode: GiftTransferAlertContentNode? let actions: [TextAlertAction] = [TextAlertAction(type: .defaultAction, title: buttonText, action: { dismissImpl?(true) commit() @@ -275,9 +282,9 @@ public func giftTransferAlertController(context: AccountContext, gift: StarGift. dismissImpl?(true) })] - contentNode = GiftTransferAlertContentNode(context: context, theme: AlertControllerTheme(presentationData: presentationData), ptheme: presentationData.theme, strings: strings, gift: gift, peer: peer, title: title, text: text, actions: actions) + let contentNode = GiftTransferAlertContentNode(context: context, theme: AlertControllerTheme(presentationData: presentationData), ptheme: presentationData.theme, strings: strings, gift: gift, peer: peer, title: title, text: text, actions: actions) - let controller = AlertController(theme: AlertControllerTheme(presentationData: presentationData), contentNode: contentNode!) + let controller = ChatMessagePaymentAlertController(context: context, presentationData: presentationData, contentNode: contentNode, navigationController: navigationController, showBalance: transferStars > 0) dismissImpl = { [weak controller] animated in if animated { controller?.dismissAnimated() diff --git a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift index da56c538e7..469950558b 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift @@ -147,13 +147,7 @@ private final class GiftViewSheetContent: CombinedComponent { var keepOriginalInfo = false - private var optionsDisposable: Disposable? - private(set) var options: [StarsTopUpOption] = [] { - didSet { - self.optionsPromise.set(self.options) - } - } - private let optionsPromise = ValuePromise<[StarsTopUpOption]?>(nil) + private let optionsPromise = Promise<[StarsTopUpOption]?>(nil) init( context: AccountContext, @@ -269,13 +263,8 @@ private final class GiftViewSheetContent: CombinedComponent { } if let starsContext = context.starsContext, let state = starsContext.currentState, state.balance < StarsAmount(value: 100, nanos: 0) { - self.optionsDisposable = (context.engine.payments.starsTopUpOptions() - |> deliverOnMainQueue).start(next: { [weak self] options in - guard let self else { - return - } - self.options = options - }) + self.optionsPromise.set(context.engine.payments.starsTopUpOptions() + |> map(Optional.init)) } } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift index d041bdd4f2..66026f44ab 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift @@ -1016,7 +1016,26 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr guard let self else { return } - let _ = self.context.engine.accountData.setStarGiftStatus(starGift: uniqueGift, expirationDate: nil).startStandalone() + if self.context.isPremium { + let _ = self.context.engine.accountData.setStarGiftStatus(starGift: uniqueGift, expirationDate: nil).startStandalone() + } else { + let text = strings.Gift_View_TooltipPremiumWearing + let tooltipController = UndoOverlayController( + presentationData: presentationData, + content: .premiumPaywall(title: nil, text: text, customUndoText: nil, timeout: nil, linkAction: nil), + position: .bottom, + animateInAsReplacement: false, + appearance: UndoOverlayController.Appearance(sideInset: 16.0, bottomInset: 62.0), + action: { [weak self] action in + if let self, case .info = action { + let premiumController = self.context.sharedContext.makePremiumIntroController(context: self.context, source: .messageEffects, forceDark: false, dismissed: nil) + self.parentController?.push(premiumController) + } + return false + } + ) + self.parentController?.present(tooltipController, in: .current) + } }) }))) } diff --git a/submodules/TelegramUI/Components/Stars/StarsPurchaseScreen/Sources/StarsPurchaseScreen.swift b/submodules/TelegramUI/Components/Stars/StarsPurchaseScreen/Sources/StarsPurchaseScreen.swift index cf2e01e40e..96ebd273a3 100644 --- a/submodules/TelegramUI/Components/Stars/StarsPurchaseScreen/Sources/StarsPurchaseScreen.swift +++ b/submodules/TelegramUI/Components/Stars/StarsPurchaseScreen/Sources/StarsPurchaseScreen.swift @@ -241,6 +241,8 @@ private final class StarsPurchaseScreenContentComponent: CombinedComponent { textString = strings.Stars_Purchase_StarGiftInfo(component.peers.first?.value.compactDisplayTitle ?? "").string case .upgradeStarGift: textString = strings.Stars_Purchase_UpgradeStarGiftInfo + case .transferStarGift: + textString = strings.Stars_Purchase_TransferStarGiftInfo case let .sendMessage(peerId, _): if peerId.namespace == Namespaces.Peer.CloudUser { textString = strings.Stars_Purchase_SendMessageInfo(component.peers.first?.value.compactDisplayTitle ?? "").string @@ -828,7 +830,7 @@ private final class StarsPurchaseScreenComponent: CombinedComponent { titleText = strings.Stars_Purchase_GetStars case .gift: titleText = strings.Stars_Purchase_GiftStars - case let .topUp(requiredStars, _), let .transfer(_, requiredStars), let .reactions(_, requiredStars), let .subscription(_, requiredStars, _), let .unlockMedia(requiredStars), let .starGift(_, requiredStars), let .upgradeStarGift(requiredStars), let .sendMessage(_, requiredStars): + case let .topUp(requiredStars, _), let .transfer(_, requiredStars), let .reactions(_, requiredStars), let .subscription(_, requiredStars, _), let .unlockMedia(requiredStars), let .starGift(_, requiredStars), let .upgradeStarGift(requiredStars), let .transferStarGift(requiredStars), let .sendMessage(_, requiredStars): titleText = strings.Stars_Purchase_StarsNeeded(Int32(requiredStars)) } @@ -1274,6 +1276,8 @@ private extension StarsPurchasePurpose { return requiredStars case let .upgradeStarGift(requiredStars): return requiredStars + case let .transferStarGift(requiredStars): + return requiredStars case let .sendMessage(_, requiredStars): return requiredStars default: diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index e8b79259a2..16fdd3eaf9 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -2883,62 +2883,102 @@ public final class SharedAccountContextImpl: SharedAccountContext { } } + let optionsPromise = Promise<[StarsTopUpOption]?>(nil) + if let state = context.starsContext?.currentState, state.balance < StarsAmount(value: 100, nanos: 0) { + optionsPromise.set(context.engine.payments.starsTopUpOptions() + |> map(Optional.init)) + } + presentTransferAlertImpl = { [weak controller] peer in guard let controller, case let .starGiftTransfer(_, _, gift, transferStars, _, _) = source else { return } - let alertController = giftTransferAlertController(context: context, gift: gift, peer: peer, transferStars: transferStars, commit: { [weak controller] in - completion?([peer.id]) - - guard let controller, let navigationController = controller.navigationController as? NavigationController else { - return - } - var controllers = navigationController.viewControllers - controllers = controllers.filter { !($0 is ContactSelectionController) } - - if !isChannelGift { - if peer.id.namespace == Namespaces.Peer.CloudChannel { - if let controller = context.sharedContext.makePeerInfoController( - context: context, - updatedPresentationData: nil, - peer: peer._asPeer(), - mode: .gifts, - avatarInitiallyExpanded: false, - fromChat: false, - requestsContext: nil - ) { - controllers.append(controller) + let alertController = giftTransferAlertController( + context: context, + gift: gift, + peer: peer, + transferStars: transferStars, + navigationController: controller.navigationController as? NavigationController, + commit: { [weak controller] in + let proceed: (Bool) -> Void = { waitForTopUp in + completion?([peer.id]) + + guard let controller, let navigationController = controller.navigationController as? NavigationController else { + return } - } else { - var foundController = false - for controller in controllers.reversed() { - if let chatController = controller as? ChatController, case .peer(id: peer.id) = chatController.chatLocation { - chatController.hintPlayNextOutgoingGift() - foundController = true - break + var controllers = navigationController.viewControllers + controllers = controllers.filter { !($0 is ContactSelectionController) } + + if !isChannelGift { + if peer.id.namespace == Namespaces.Peer.CloudChannel { + if let controller = context.sharedContext.makePeerInfoController( + context: context, + updatedPresentationData: nil, + peer: peer._asPeer(), + mode: .gifts, + avatarInitiallyExpanded: false, + fromChat: false, + requestsContext: nil + ) { + controllers.append(controller) + } + } else { + var foundController = false + for controller in controllers.reversed() { + if let chatController = controller as? ChatController, case .peer(id: peer.id) = chatController.chatLocation { + chatController.hintPlayNextOutgoingGift() + foundController = true + break + } + } + if !foundController { + let chatController = context.sharedContext.makeChatController(context: context, chatLocation: .peer(id: peer.id), subject: nil, botStart: nil, mode: .standard(.default), params: nil) + chatController.hintPlayNextOutgoingGift() + controllers.append(chatController) + } } } - if !foundController { - let chatController = context.sharedContext.makeChatController(context: context, chatLocation: .peer(id: peer.id), subject: nil, botStart: nil, mode: .standard(.default), params: nil) - chatController.hintPlayNextOutgoingGift() - controllers.append(chatController) + navigationController.setViewControllers(controllers, animated: true) + + Queue.mainQueue().after(0.3) { + let tooltipController = UndoOverlayController( + presentationData: presentationData, + content: .forward(savedMessages: false, text: presentationData.strings.Gift_Transfer_Success("\(gift.title) #\(presentationStringsFormattedNumber(gift.number, presentationData.dateTimeFormat.groupingSeparator))", peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string), + elevatedLayout: false, + action: { _ in return true } + ) + if let lastController = controllers.last as? ViewController { + lastController.present(tooltipController, in: .window(.root)) + } } } - } - navigationController.setViewControllers(controllers, animated: true) - - Queue.mainQueue().after(0.3) { - let tooltipController = UndoOverlayController( - presentationData: presentationData, - content: .forward(savedMessages: false, text: presentationData.strings.Gift_Transfer_Success("\(gift.title) #\(presentationStringsFormattedNumber(gift.number, presentationData.dateTimeFormat.groupingSeparator))", peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string), - elevatedLayout: false, - action: { _ in return true } - ) - if let lastController = controllers.last as? ViewController { - lastController.present(tooltipController, in: .window(.root)) + + if transferStars > 0, let starsContext = context.starsContext, let starsState = starsContext.currentState { + if starsState.balance < StarsAmount(value: transferStars, nanos: 0) { + let _ = (optionsPromise.get() + |> filter { $0 != nil } + |> take(1) + |> deliverOnMainQueue).startStandalone(next: { [weak controller] options in + let purchaseController = context.sharedContext.makeStarsPurchaseScreen( + context: context, + starsContext: starsContext, + options: options ?? [], + purpose: .transferStarGift(requiredStars: transferStars), + completion: { stars in + starsContext.add(balance: StarsAmount(value: stars, nanos: 0)) + proceed(true) + } + ) + controller?.push(purchaseController) + }) + } else { + proceed(false) + } + } else { + proceed(false) } } - }) + ) controller.present(alertController, in: .window(.root)) }