diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift index 2eb5ec91de..6b44951fc8 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift @@ -2438,6 +2438,7 @@ private final class ResaleGiftsContextImpl { private var gifts: [StarGift] = [] private var attributes: [StarGift.UniqueGift.Attribute] = [] private var attributeCount: [ResaleGiftsContext.Attribute: Int32] = [:] + private var attributesHash: Int64? private var count: Int32? private var dataState: ResaleGiftsContext.State.DataState = .ready(canLoadMore: true, nextOffset: nil) @@ -2477,6 +2478,7 @@ private final class ResaleGiftsContextImpl { let postbox = self.account.postbox let sorting = self.sorting let filterAttributes = self.filterAttributes + let currentAttributesHash = self.attributesHash let dataState = self.dataState @@ -2511,46 +2513,45 @@ private final class ResaleGiftsContextImpl { } } - var attributesHash: Int64? - if "".isEmpty { - flags |= (1 << 0) - attributesHash = 0 - } + let attributesHash = currentAttributesHash ?? 0 + flags |= (1 << 0) let signal = network.request(Api.functions.payments.getResaleStarGifts(flags: flags, attributesHash: attributesHash, giftId: giftId, attributes: apiAttributes, offset: initialNextOffset ?? "", limit: 36)) |> map(Optional.init) |> `catch` { _ -> Signal in return .single(nil) } - |> mapToSignal { result -> Signal<([StarGift], [StarGift.UniqueGift.Attribute], [ResaleGiftsContext.Attribute: Int32], Int32, String?), NoError> in + |> mapToSignal { result -> Signal<([StarGift], [StarGift.UniqueGift.Attribute]?, [ResaleGiftsContext.Attribute: Int32]?, Int64?, Int32, String?), NoError> in guard let result else { - return .single(([], [], [:], 0, nil)) + return .single(([], nil, nil, nil, 0, nil)) } - return postbox.transaction { transaction -> ([StarGift], [StarGift.UniqueGift.Attribute], [ResaleGiftsContext.Attribute: Int32], Int32, String?) in + return postbox.transaction { transaction -> ([StarGift], [StarGift.UniqueGift.Attribute]?, [ResaleGiftsContext.Attribute: Int32]?, Int64?, Int32, String?) in switch result { case let .resaleStarGifts(_, count, gifts, nextOffset, attributes, attributesHash, chats, counters, users): let _ = attributesHash - var resultAttributes: [StarGift.UniqueGift.Attribute] = [] + var resultAttributes: [StarGift.UniqueGift.Attribute]? if let attributes { resultAttributes = attributes.compactMap { StarGift.UniqueGift.Attribute(apiAttribute: $0) } } - var attributeCount: [ResaleGiftsContext.Attribute: Int32] = [:] + var attributeCount: [ResaleGiftsContext.Attribute: Int32]? if let counters { + var attributeCountValue: [ResaleGiftsContext.Attribute: Int32] = [:] for counter in counters { switch counter { case let .starGiftAttributeCounter(attribute, count): switch attribute { case let .starGiftAttributeIdModel(documentId): - attributeCount[.model(documentId)] = count + attributeCountValue[.model(documentId)] = count case let .starGiftAttributeIdPattern(documentId): - attributeCount[.pattern(documentId)] = count + attributeCountValue[.pattern(documentId)] = count case let .starGiftAttributeIdBackdrop(backdropId): - attributeCount[.backdrop(backdropId)] = count + attributeCountValue[.backdrop(backdropId)] = count } } } + attributeCount = attributeCountValue } let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users) @@ -2563,13 +2564,13 @@ private final class ResaleGiftsContextImpl { } } - return (mappedGifts, resultAttributes, attributeCount, count, nextOffset) + return (mappedGifts, resultAttributes, attributeCount, attributesHash, count, nextOffset) } } } self.disposable.set((signal - |> deliverOn(self.queue)).start(next: { [weak self] (gifts, attributes, attributeCount, count, nextOffset) in + |> deliverOn(self.queue)).start(next: { [weak self] (gifts, attributes, attributeCount, attributesHash, count, nextOffset) in guard let self else { return } @@ -2581,10 +2582,13 @@ private final class ResaleGiftsContextImpl { let updatedCount = max(Int32(self.gifts.count), count) self.count = updatedCount - self.attributes = attributes - if !attributeCount.isEmpty { + + if let attributes, let attributeCount, let attributesHash { + self.attributes = attributes self.attributeCount = attributeCount + self.attributesHash = attributesHash } + self.dataState = .ready(canLoadMore: count != 0 && updatedCount > self.gifts.count && nextOffset != nil, nextOffset: nextOffset) self.pushState() diff --git a/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift index 52bd22d3ee..e28b5d6219 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift @@ -458,9 +458,13 @@ final class GiftOptionsScreenComponent: Component { mainController.push(giftController) } } else { - var forceUnique = false - if let disallowedGifts = self.state?.disallowedGifts, disallowedGifts.contains(.limited) && !disallowedGifts.contains(.unique) { - forceUnique = true + var forceUnique: Bool? + if let disallowedGifts = self.state?.disallowedGifts { + if disallowedGifts.contains(.limited) && !disallowedGifts.contains(.unique) { + forceUnique = true + } else if !disallowedGifts.contains(.limited) && disallowedGifts.contains(.unique) { + forceUnique = false + } } let giftController = GiftSetupScreen( diff --git a/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/GiftSetupScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/GiftSetupScreen.swift index 3c325c54bb..2c574d0a09 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/GiftSetupScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/GiftSetupScreen.swift @@ -788,57 +788,60 @@ final class GiftSetupScreenComponent: Component { contentHeight += sectionSpacing } - if case let .starGift(starGift, _) = component.subject, let availability = starGift.availability, availability.resale > 0 { - let resaleSectionSize = self.resaleSection.update( - transition: transition, - component: AnyComponent(ListSectionComponent( - theme: environment.theme, - header: nil, - footer: nil, - items: [ - AnyComponentWithIdentity(id: 0, component: AnyComponent(ListActionItemComponent( - theme: environment.theme, - title: AnyComponent(VStack([ - AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent( - MultilineTextComponent( - text: .plain(NSAttributedString(string: environment.strings.Gift_Send_AvailableForResale, font: Font.regular(presentationData.listsFontSize.baseDisplaySize), textColor: environment.theme.list.itemPrimaryTextColor)) + if case let .starGift(starGift, forceUnique) = component.subject, let availability = starGift.availability, availability.resale > 0 { + if let forceUnique, !forceUnique { + } else { + let resaleSectionSize = self.resaleSection.update( + transition: transition, + component: AnyComponent(ListSectionComponent( + theme: environment.theme, + header: nil, + footer: nil, + items: [ + AnyComponentWithIdentity(id: 0, component: AnyComponent(ListActionItemComponent( + theme: environment.theme, + title: AnyComponent(VStack([ + AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent( + MultilineTextComponent( + text: .plain(NSAttributedString(string: environment.strings.Gift_Send_AvailableForResale, font: Font.regular(presentationData.listsFontSize.baseDisplaySize), textColor: environment.theme.list.itemPrimaryTextColor)) + ) + )), + ], alignment: .left, spacing: 2.0)), + accessory: .custom(ListActionItemComponent.CustomAccessory(component: AnyComponentWithIdentity(id: 0, component: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString( + string: presentationStringsFormattedNumber(Int32(availability.resale), environment.dateTimeFormat.groupingSeparator), + font: Font.regular(presentationData.listsFontSize.baseDisplaySize), + textColor: environment.theme.list.itemSecondaryTextColor + )), + maximumNumberOfLines: 0 + ))), insets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 16.0))), + action: { [weak self] _ in + guard let self, let component = self.component, let controller = environment.controller() else { + return + } + let storeController = component.context.sharedContext.makeGiftStoreController( + context: component.context, + peerId: component.peerId, + gift: starGift ) - )), - ], alignment: .left, spacing: 2.0)), - accessory: .custom(ListActionItemComponent.CustomAccessory(component: AnyComponentWithIdentity(id: 0, component: AnyComponent(MultilineTextComponent( - text: .plain(NSAttributedString( - string: presentationStringsFormattedNumber(Int32(availability.resale), environment.dateTimeFormat.groupingSeparator), - font: Font.regular(presentationData.listsFontSize.baseDisplaySize), - textColor: environment.theme.list.itemSecondaryTextColor - )), - maximumNumberOfLines: 0 - ))), insets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 16.0))), - action: { [weak self] _ in - guard let self, let component = self.component, let controller = environment.controller() else { - return + controller.push(storeController) } - let storeController = component.context.sharedContext.makeGiftStoreController( - context: component.context, - peerId: component.peerId, - gift: starGift - ) - controller.push(storeController) - } - ))) - ] - )), - environment: {}, - containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 10000.0) - ) - let resaleSectionFrame = CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: resaleSectionSize) - if let resaleSectionView = self.resaleSection.view { - if resaleSectionView.superview == nil { - self.scrollView.addSubview(resaleSectionView) + ))) + ] + )), + environment: {}, + containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 10000.0) + ) + let resaleSectionFrame = CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: resaleSectionSize) + if let resaleSectionView = self.resaleSection.view { + if resaleSectionView.superview == nil { + self.scrollView.addSubview(resaleSectionView) + } + transition.setFrame(view: resaleSectionView, frame: resaleSectionFrame) } - transition.setFrame(view: resaleSectionView, frame: resaleSectionFrame) + contentHeight += resaleSectionSize.height + contentHeight += sectionSpacing } - contentHeight += resaleSectionSize.height - contentHeight += sectionSpacing } let giftConfiguration = GiftConfiguration.with(appConfiguration: component.context.currentAppConfiguration.with { $0 }) @@ -1128,7 +1131,7 @@ final class GiftSetupScreenComponent: Component { if isChannelGift { upgradeFooterRawString = environment.strings.Gift_SendChannel_Upgrade_Info(peerName).string } else { - if forceUnique { + if forceUnique == true { upgradeFooterRawString = environment.strings.Gift_Send_Upgrade_ForcedInfo(peerName).string } else { upgradeFooterRawString = environment.strings.Gift_Send_Upgrade_Info(peerName).string @@ -1201,8 +1204,8 @@ final class GiftSetupScreenComponent: Component { ) )), ], alignment: .left, spacing: 2.0)), - accessory: .toggle(ListActionItemComponent.Toggle(style: .regular, isOn: self.includeUpgrade, isEnabled: !forceUnique, action: { [weak self] _ in - guard let self, !forceUnique else { + accessory: .toggle(ListActionItemComponent.Toggle(style: .regular, isOn: self.includeUpgrade, isEnabled: forceUnique != true, action: { [weak self] _ in + guard let self, forceUnique != true else { return } self.includeUpgrade = !self.includeUpgrade @@ -1748,7 +1751,7 @@ final class GiftSetupScreenComponent: Component { public final class GiftSetupScreen: ViewControllerComponentContainer { public enum Subject: Equatable { case premium(PremiumGiftProduct) - case starGift(StarGift.Gift, Bool) + case starGift(StarGift.Gift, Bool?) } private let context: AccountContext diff --git a/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftStoreScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftStoreScreen.swift index 99f6f05b84..1ca1c6317f 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftStoreScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftStoreScreen.swift @@ -789,6 +789,11 @@ final class GiftStoreScreenComponent: Component { } self.component = component + var isLoading = false + if self.state?.starGiftsState?.gifts == nil || self.state?.starGiftsState?.dataState == .loading { + isLoading = true + } + let theme = environment.theme let strings = environment.strings @@ -887,6 +892,10 @@ final class GiftStoreScreenComponent: Component { balanceIconView.bounds = CGRect(origin: .zero, size: balanceIconSize) } + var topInset: CGFloat = 0.0 + if environment.statusBarHeight > 0.0 { + topInset = environment.statusBarHeight - 6.0 + } let titleSize = self.title.update( transition: transition, component: AnyComponent(MultilineTextComponent( @@ -900,7 +909,7 @@ final class GiftStoreScreenComponent: Component { if titleView.superview == nil { self.addSubview(titleView) } - transition.setFrame(view: titleView, frame: CGRect(origin: CGPoint(x: floor((availableSize.width - titleSize.width) / 2.0), y: 10.0), size: titleSize)) + transition.setFrame(view: titleView, frame: CGRect(origin: CGPoint(x: floor((availableSize.width - titleSize.width) / 2.0), y: topInset + 10.0), size: titleSize)) } let effectiveCount: Int32 @@ -922,7 +931,7 @@ final class GiftStoreScreenComponent: Component { environment: {}, containerSize: CGSize(width: availableSize.width - headerSideInset * 2.0, height: 100.0) ) - let subtitleFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - subtitleSize.width) / 2.0), y: 31.0), size: subtitleSize) + let subtitleFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - subtitleSize.width) / 2.0), y: topInset + 31.0), size: subtitleSize) if let subtitleView = self.subtitle.view { if subtitleView.superview == nil { self.addSubview(subtitleView) @@ -984,10 +993,10 @@ final class GiftStoreScreenComponent: Component { modelTitle = environment.strings.Gift_Store_Filter_Selected_Model(modelCount) } if backdropCount > 0 { - backdropTitle = environment.strings.Gift_Store_Filter_Selected_Backdrop(modelCount) + backdropTitle = environment.strings.Gift_Store_Filter_Selected_Backdrop(backdropCount) } if symbolCount > 0 { - symbolTitle = environment.strings.Gift_Store_Filter_Selected_Symbol(modelCount) + symbolTitle = environment.strings.Gift_Store_Filter_Selected_Symbol(symbolCount) } } @@ -1036,7 +1045,7 @@ final class GiftStoreScreenComponent: Component { if filterSelectorView.superview == nil { self.addSubview(filterSelectorView) } - transition.setFrame(view: filterSelectorView, frame: CGRect(origin: CGPoint(x: floor((availableSize.width - filterSize.width) / 2.0), y: 56.0), size: filterSize)) + transition.setFrame(view: filterSelectorView, frame: CGRect(origin: CGPoint(x: floor((availableSize.width - filterSize.width) / 2.0), y: topInset + 56.0), size: filterSize)) } if let starGifts = self.state?.starGiftsState?.gifts { @@ -1078,12 +1087,7 @@ final class GiftStoreScreenComponent: Component { self.topOverscrollLayer.frame = CGRect(origin: CGPoint(x: 0.0, y: -3000.0), size: CGSize(width: availableSize.width, height: 3000.0)) self.updateScrolling(transition: transition) - - var isLoading = false - if self.state?.starGiftsState?.gifts == nil || self.state?.starGiftsState?.dataState == .loading { - isLoading = true - } - + let loadingTransition: ComponentTransition = .easeInOut(duration: 0.25) if isLoading { self.loadingNode.update(size: availableSize, theme: environment.theme, transition: .immediate) diff --git a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift index b1ed83e615..db684ec86e 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift @@ -805,6 +805,7 @@ private final class GiftViewSheetContent: CombinedComponent { default: break } + self.updated(transition: .easeInOut(duration: 0.2)) let text = presentationData.strings.Gift_View_Resale_Unlist_Success(giftTitle).string let tooltipController = UndoOverlayController( @@ -880,7 +881,8 @@ private final class GiftViewSheetContent: CombinedComponent { default: break } - + self.updated(transition: .easeInOut(duration: 0.2)) + var text = presentationData.strings.Gift_View_Resale_List_Success(giftTitle).string if update { let starsString = presentationData.strings.Gift_View_Resale_Relist_Success_Stars(Int32(price))