diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift index 8a9c186184..3425c1f487 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift @@ -2421,7 +2421,15 @@ private final class ResaleGiftsContextImpl { let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users) updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers) - return (gifts.compactMap { StarGift(apiStarGift: $0) }, resultAttributes, attributeCount, count, nextOffset) + + var mappedGifts: [StarGift] = [] + for gift in gifts { + if let mappedGift = StarGift(apiStarGift: gift), case let .unique(uniqueGift) = mappedGift, let resellStars = uniqueGift.resellStars, resellStars > 0 { + mappedGifts.append(mappedGift) + } + } + + return (mappedGifts, resultAttributes, attributeCount, count, nextOffset) } } } @@ -2434,9 +2442,7 @@ private final class ResaleGiftsContextImpl { if initialNextOffset == nil || reload { self.gifts = gifts } else { - for gift in gifts { - self.gifts.append(gift) - } + self.gifts.append(contentsOf: gifts) } let updatedCount = max(Int32(self.gifts.count), count) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift index 4207c622b2..4677f08a9e 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift @@ -125,7 +125,7 @@ public extension TelegramEngine { return _internal_transferStarGift(account: self.account, prepaid: prepaid, reference: reference, peerId: peerId) } - public func buyStarGift(prepaid: Bool, slug: String, peerId: EnginePeer.Id) -> Signal { + public func buyStarGift(slug: String, peerId: EnginePeer.Id) -> Signal { return _internal_buyStarGift(account: self.account, slug: slug, peerId: peerId) } diff --git a/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift b/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift index f594bc5f95..c612e59a65 100644 --- a/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift +++ b/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift @@ -2726,7 +2726,7 @@ public class CameraScreenImpl: ViewController, CameraScreen { self.additionalPreviewView.isEnabled = false self.collageView?.isEnabled = false - #if DEBUG + #if targetEnvironment(simulator) #else Queue.mainQueue().after(0.3) { diff --git a/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftStoreScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftStoreScreen.swift index 25f029dc27..46fee26be0 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftStoreScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftStoreScreen.swift @@ -765,10 +765,19 @@ final class GiftStoreScreenComponent: Component { transition.setFrame(view: titleView, frame: CGRect(origin: CGPoint(x: floor((availableSize.width - titleSize.width) / 2.0), y: 10.0), size: titleSize)) } + let effectiveCount: Int32 + if let count = self.effectiveGifts?.count { + effectiveCount = Int32(count) + } else if let resale = component.gift.availability?.resale { + effectiveCount = Int32(resale) + } else { + effectiveCount = 0 + } + let subtitleSize = self.subtitle.update( transition: transition, component: AnyComponent(BalancedTextComponent( - text: .plain(NSAttributedString(string: "\(self.effectiveGifts?.count ?? 0) for resale", font: Font.regular(13.0), textColor: theme.rootController.navigationBar.secondaryTextColor)), + text: .plain(NSAttributedString(string: "\(effectiveCount) for resale", font: Font.regular(13.0), textColor: theme.rootController.navigationBar.secondaryTextColor)), horizontalAlignment: .center, maximumNumberOfLines: 1 )), @@ -927,7 +936,7 @@ final class GiftStoreScreenComponent: Component { self.scrollView.contentSize = contentSize self.nextScrollTransition = nil } - let scrollInsets = UIEdgeInsets(top: environment.navigationHeight, left: 0.0, bottom: 0.0, right: 0.0) + let scrollInsets = UIEdgeInsets(top: topPanelHeight, left: 0.0, bottom: 0.0, right: 0.0) if self.scrollView.scrollIndicatorInsets != scrollInsets { self.scrollView.scrollIndicatorInsets = scrollInsets } diff --git a/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/LoadingShimmerComponent.swift b/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/LoadingShimmerComponent.swift index ed76cec440..b9f6c04b2f 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/LoadingShimmerComponent.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/LoadingShimmerComponent.swift @@ -134,6 +134,7 @@ final class LoadingShimmerNode: ASDisplayNode { super.init() + self.allowsGroupOpacity = true self.isUserInteractionEnabled = false self.addSubnode(self.backgroundColorNode) diff --git a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift index 22f2fb8ac8..3125cacc51 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift @@ -57,6 +57,7 @@ private final class GiftViewSheetContent: CombinedComponent { let openMyGifts: () -> Void let transferGift: () -> Void let upgradeGift: ((Int64?, Bool) -> Signal) + let buyGift: ((String, EnginePeer.Id) -> Signal) let shareGift: () -> Void let resellGift: (Bool) -> Void let showAttributeInfo: (Any, String) -> Void @@ -79,6 +80,7 @@ private final class GiftViewSheetContent: CombinedComponent { openMyGifts: @escaping () -> Void, transferGift: @escaping () -> Void, upgradeGift: @escaping ((Int64?, Bool) -> Signal), + buyGift: @escaping ((String, EnginePeer.Id) -> Signal), shareGift: @escaping () -> Void, resellGift: @escaping (Bool) -> Void, showAttributeInfo: @escaping (Any, String) -> Void, @@ -100,6 +102,7 @@ private final class GiftViewSheetContent: CombinedComponent { self.openMyGifts = openMyGifts self.transferGift = transferGift self.upgradeGift = upgradeGift + self.buyGift = buyGift self.shareGift = shareGift self.resellGift = resellGift self.showAttributeInfo = showAttributeInfo @@ -121,7 +124,10 @@ private final class GiftViewSheetContent: CombinedComponent { final class State: ComponentState { private let context: AccountContext private(set) var subject: GiftViewScreen.Subject + private let upgradeGift: ((Int64?, Bool) -> Signal) + private let buyGift: ((String, EnginePeer.Id) -> Signal) + private let getController: () -> ViewController? private var disposable: Disposable? @@ -171,11 +177,13 @@ private final class GiftViewSheetContent: CombinedComponent { context: AccountContext, subject: GiftViewScreen.Subject, upgradeGift: @escaping ((Int64?, Bool) -> Signal), + buyGift: @escaping ((String, EnginePeer.Id) -> Signal), getController: @escaping () -> ViewController? ) { self.context = context self.subject = subject self.upgradeGift = upgradeGift + self.buyGift = buyGift self.getController = getController super.init() @@ -435,20 +443,8 @@ private final class GiftViewSheetContent: CombinedComponent { self.inProgress = true self.updated() - let signal = context.engine.payments.sendStarsPaymentForm(formId: formId, source: .starGiftResale(slug: uniqueGift.slug, toPeerId: recipientPeerId)) - |> mapError { _ -> SendBotPaymentFormError in - return .generic - } - |> mapToSignal { result in - if case let .done(_, _, gift) = result, let gift { - return .single(gift) - } else { - return .complete() - } - } - - self.buyDisposable = (signal - |> deliverOnMainQueue).start(next: { [weak self, weak starsContext] result in + self.buyDisposable = (self.buyGift(uniqueGift.slug, recipientPeerId) + |> deliverOnMainQueue).start(completed: { [weak self, weak starsContext] in guard let self, let controller = self.getController() as? GiftViewScreen else { return } @@ -677,7 +673,7 @@ private final class GiftViewSheetContent: CombinedComponent { } func makeState() -> State { - return State(context: self.context, subject: self.subject, upgradeGift: self.upgradeGift, getController: self.getController) + return State(context: self.context, subject: self.subject, upgradeGift: self.upgradeGift, buyGift: self.buyGift, getController: self.getController) } static var body: Body { @@ -690,7 +686,6 @@ private final class GiftViewSheetContent: CombinedComponent { let transferButton = Child(PlainButtonComponent.self) let wearButton = Child(PlainButtonComponent.self) -// let shareButton = Child(PlainButtonComponent.self) let resellButton = Child(PlainButtonComponent.self) let wearAvatar = Child(AvatarComponent.self) @@ -751,6 +746,7 @@ private final class GiftViewSheetContent: CombinedComponent { var uniqueGift: StarGift.UniqueGift? var isSelfGift = false var isChannelGift = false + var isMyUniqueGift = false if case let .soldOutGift(gift) = subject { animationFile = gift.file @@ -798,6 +794,10 @@ private final class GiftViewSheetContent: CombinedComponent { isSelfGift = arguments.messageId?.peerId == component.context.account.peerId + if case let .peerId(peerId) = uniqueGift?.owner, peerId == component.context.account.peerId || isChannelGift { + isMyUniqueGift = true + } + if isSelfGift { titleString = strings.Gift_View_Self_Title } else { @@ -1753,7 +1753,7 @@ private final class GiftViewSheetContent: CombinedComponent { } if let uniqueGift { - if case let .peerId(peerId) = uniqueGift.owner, peerId == component.context.account.peerId || isChannelGift { + if isMyUniqueGift, case let .peerId(peerId) = uniqueGift.owner { var canTransfer = true if let peer = state.peerMap[peerId], case let .channel(channel) = peer, !channel.flags.contains(.isCreator) { canTransfer = false @@ -2570,7 +2570,7 @@ private final class GiftViewSheetContent: CombinedComponent { availableSize: buttonSize, transition: context.transition ) - } else if !incoming, let resellStars { + } else if !incoming, let resellStars, !isMyUniqueGift { if state.cachedStarImage == nil || state.cachedStarImage?.1 !== theme { state.cachedStarImage = (generateTintedImage(image: UIImage(bundleImageName: "Item List/PremiumIcon"), color: theme.list.itemCheckColors.foregroundColor)!, theme) } @@ -2652,6 +2652,7 @@ private final class GiftViewSheetComponent: CombinedComponent { let openMyGifts: () -> Void let transferGift: () -> Void let upgradeGift: ((Int64?, Bool) -> Signal) + let buyGift: ((String, EnginePeer.Id) -> Signal) let shareGift: () -> Void let resellGift: (Bool) -> Void let viewUpgraded: (EngineMessage.Id) -> Void @@ -2672,6 +2673,7 @@ private final class GiftViewSheetComponent: CombinedComponent { openMyGifts: @escaping () -> Void, transferGift: @escaping () -> Void, upgradeGift: @escaping ((Int64?, Bool) -> Signal), + buyGift: @escaping ((String, EnginePeer.Id) -> Signal), shareGift: @escaping () -> Void, resellGift: @escaping (Bool) -> Void, viewUpgraded: @escaping (EngineMessage.Id) -> Void, @@ -2691,6 +2693,7 @@ private final class GiftViewSheetComponent: CombinedComponent { self.openMyGifts = openMyGifts self.transferGift = transferGift self.upgradeGift = upgradeGift + self.buyGift = buyGift self.shareGift = shareGift self.resellGift = resellGift self.viewUpgraded = viewUpgraded @@ -2743,6 +2746,7 @@ private final class GiftViewSheetComponent: CombinedComponent { openMyGifts: context.component.openMyGifts, transferGift: context.component.transferGift, upgradeGift: context.component.upgradeGift, + buyGift: context.component.buyGift, shareGift: context.component.shareGift, resellGift: context.component.resellGift, showAttributeInfo: context.component.showAttributeInfo, @@ -2772,6 +2776,7 @@ private final class GiftViewSheetComponent: CombinedComponent { if animated { if let controller = controller() as? GiftViewScreen { controller.dismissAllTooltips() + controller.dismissBalanceOverlay() animateOut.invoke(Action { _ in controller.dismiss(completion: nil) }) @@ -2779,6 +2784,7 @@ private final class GiftViewSheetComponent: CombinedComponent { } else { if let controller = controller() as? GiftViewScreen { controller.dismissAllTooltips() + controller.dismissBalanceOverlay() controller.dismiss(completion: nil) } } @@ -2913,6 +2919,7 @@ public class GiftViewScreen: ViewControllerComponentContainer { convertToStars: (() -> Void)? = nil, transferGift: ((Bool, EnginePeer.Id) -> Signal)? = nil, upgradeGift: ((Int64?, Bool) -> Signal)? = nil, + buyGift: ((String, EnginePeer.Id) -> Signal)? = nil, updateResellStars: ((Int64?) -> Void)? = nil, togglePinnedToTop: ((Bool) -> Bool)? = nil, shareStory: ((StarGift.UniqueGift) -> Void)? = nil @@ -2930,6 +2937,7 @@ public class GiftViewScreen: ViewControllerComponentContainer { var openMyGiftsImpl: (() -> Void)? var transferGiftImpl: (() -> Void)? var upgradeGiftImpl: ((Int64?, Bool) -> Signal)? + var buyGiftImpl: ((String, EnginePeer.Id) -> Signal)? var shareGiftImpl: (() -> Void)? var resellGiftImpl: ((Bool) -> Void)? var openMoreImpl: ((ASDisplayNode, ContextGesture?) -> Void)? @@ -2974,6 +2982,9 @@ public class GiftViewScreen: ViewControllerComponentContainer { upgradeGift: { formId, keepOriginalInfo in return upgradeGiftImpl?(formId, keepOriginalInfo) ?? .complete() }, + buyGift: { slug, peerId in + return buyGiftImpl?(slug, peerId) ?? .complete() + }, shareGift: { shareGiftImpl?() }, @@ -3278,6 +3289,11 @@ public class GiftViewScreen: ViewControllerComponentContainer { } if let upgradeGift { return upgradeGift(formId, keepOriginalInfo) + |> afterCompleted { + if formId != nil { + context.starsContext?.load(force: true) + } + } } else { return self.context.engine.payments.upgradeStarGift(formId: formId, reference: reference, keepOriginalInfo: keepOriginalInfo) |> afterCompleted { @@ -3288,6 +3304,23 @@ public class GiftViewScreen: ViewControllerComponentContainer { } } + buyGiftImpl = { [weak self] slug, peerId in + guard let self else { + return .complete() + } + if let buyGift { + return buyGift(slug, peerId) + |> afterCompleted { + context.starsContext?.load(force: true) + } + } else { + return self.context.engine.payments.buyStarGift(slug: slug, peerId: peerId) + |> afterCompleted { + context.starsContext?.load(force: true) + } + } + } + shareGiftImpl = { [weak self] in guard let self, let arguments = self.subject.arguments, case let .unique(gift) = arguments.gift else { return @@ -3628,6 +3661,10 @@ public class GiftViewScreen: ViewControllerComponentContainer { view.dismissAnimated() } + self.dismissBalanceOverlay() + } + + fileprivate func dismissBalanceOverlay() { if let view = self.balanceOverlay.view, view.superview != nil { view.layer.animateScale(from: 1.0, to: 0.8, duration: 0.4, removeOnCompletion: false) view.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false) diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift index 9d556d26db..fa895d358c 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift @@ -4867,6 +4867,12 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro } return profileGifts.upgradeStarGift(formId: formId, reference: reference, keepOriginalInfo: keepOriginalInfo) }, + buyGift: { [weak profileGifts] slug, peerId in + guard let profileGifts else { + return .never() + } + return profileGifts.buyStarGift(slug: slug, peerId: peerId) + }, shareStory: { [weak self] uniqueGift in guard let self, let controller = self.controller else { return diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift index 94d4c21e13..3ca1bfee0b 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift @@ -600,6 +600,12 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr } return self.profileGifts.upgradeStarGift(formId: formId, reference: reference, keepOriginalInfo: keepOriginalInfo) }, + buyGift: { [weak self] slug, peerId in + guard let self else { + return .never() + } + return self.profileGifts.buyStarGift(slug: slug, peerId: peerId) + }, updateResellStars: { [weak self] price in guard let self, case let .unique(uniqueGift) = product.gift else { return diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index 5d84c430d2..b2563c9c57 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -2987,11 +2987,11 @@ public final class SharedAccountContextImpl: SharedAccountContext { )) controller.navigationPresentation = .modal - let _ = combineLatest( + let _ = (combineLatest( queue: Queue.mainQueue(), controller.result, - options.get() - ).startStandalone(next: { [weak controller] result, options in + options.get()) + |> take(1)).startStandalone(next: { [weak controller] result, options in if let (peers, _, _, _, _, _) = result, let contactPeer = peers.first, case let .peer(peer, _, _) = contactPeer, let starsContext = context.starsContext { if case .starGiftTransfer = source { presentTransferAlertImpl?(EnginePeer(peer))