From b47660b22c4ccb3dd58fc05629497f568b6765b5 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Fri, 6 Feb 2026 19:35:09 +0400 Subject: [PATCH] Various fixes --- .../Sources/GiftCraftScreen.swift | 64 +++++++++++++------ .../Sources/SelectCraftGiftScreen.swift | 15 ++++- .../Sources/GiftStoreScreen.swift | 14 ++-- .../Sources/GiftViewScreen.swift | 36 ++++++++++- 4 files changed, 100 insertions(+), 29 deletions(-) diff --git a/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/GiftCraftScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/GiftCraftScreen.swift index 519d1fe142..eefa74f502 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/GiftCraftScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/GiftCraftScreen.swift @@ -69,6 +69,7 @@ private final class CraftGiftPageContent: Component { let starsTopUpOptionsPromise: Promise<[StarsTopUpOption]?> let selectGift: (Int32, GiftItem) -> Void let removeGift: (Int32) -> Void + let craftAnotherGift: () -> Void let dismiss: () -> Void init( @@ -86,6 +87,7 @@ private final class CraftGiftPageContent: Component { starsTopUpOptionsPromise: Promise<[StarsTopUpOption]?>, selectGift: @escaping (Int32, GiftItem) -> Void, removeGift: @escaping (Int32) -> Void, + craftAnotherGift: @escaping () -> Void, dismiss: @escaping () -> Void ) { self.context = context @@ -102,6 +104,7 @@ private final class CraftGiftPageContent: Component { self.starsTopUpOptionsPromise = starsTopUpOptionsPromise self.selectGift = selectGift self.removeGift = removeGift + self.craftAnotherGift = craftAnotherGift self.dismiss = dismiss } @@ -1203,7 +1206,13 @@ private final class CraftGiftPageContent: Component { } if let _ = view { if case let .gift(gift) = component.result { - let giftController = GiftViewScreen(context: component.context, subject: .profileGift(component.context.account.peerId, gift)) + let giftController = GiftViewScreen( + context: component.context, + subject: .profileGift(component.context.account.peerId, gift), + customAction: .init(title: environment.strings.Gift_Craft_CraftingFailed_CraftAnotherGift, action: { + component.craftAnotherGift() + }) + ) if let navigationController = controller.navigationController { navigationController.pushViewController(giftController, animated: true) @@ -1548,6 +1557,36 @@ private final class SheetContainerComponent: CombinedComponent { } } + let navigationController = environment.controller()?.navigationController as? NavigationController + let profileGiftsContext = (environment.controller() as? GiftCraftScreen)?.profileGiftsContext + let resaleContext = state.resaleContext + let starsTopUpOptionsPromise = state.starsTopUpOptionsPromise + let craftAnotherGift = { [weak navigationController] in + guard let navigationController else { + return + } + if let genericGift = externalState.starGiftsMap[component.gift.giftId] { + HapticFeedback().impact(.light) + + let selectController = SelectCraftGiftScreen( + context: component.context, + craftContext: component.craftContext, + resaleContext: resaleContext, + gift: component.gift, + genericGift: genericGift, + selectedGiftIds: Set(), + starsTopUpOptions: starsTopUpOptionsPromise.get(), + selectGift: { [weak navigationController] item in + if let navigationController{ + let craftController = GiftCraftScreen(context: component.context, gift: item.gift, profileGiftsContext: profileGiftsContext) + navigationController.pushViewController(craftController) + } + } + ) + navigationController.pushViewController(selectController) + } + } + let theme = environment.theme var colors: (UIColor, UIColor, UIColor, UIColor, UIColor) = ( @@ -1720,6 +1759,7 @@ private final class SheetContainerComponent: CombinedComponent { state.selectedGiftIds[index] = nil state.updated(transition: .spring(duration: 0.4)) }, + craftAnotherGift: craftAnotherGift, dismiss: { dismiss(true) } @@ -1791,26 +1831,8 @@ private final class SheetContainerComponent: CombinedComponent { if state.displayInfo { state.displayInfo = false state.updated(transition: .spring(duration: 0.3)) - } else if state.displayFailure, let genericGift = externalState.starGiftsMap[component.gift.giftId] { - HapticFeedback().impact(.light) - - let selectController = SelectCraftGiftScreen( - context: component.context, - craftContext: component.craftContext, - resaleContext: state.resaleContext, - gift: component.gift, - genericGift: genericGift, - selectedGiftIds: Set(), - starsTopUpOptions: state.starsTopUpOptionsPromise.get(), - selectGift: { item in - if let controller = controller() as? GiftCraftScreen, let navigationController = controller.navigationController as? NavigationController { - let craftController = GiftCraftScreen(context: component.context, gift: item.gift, profileGiftsContext: controller.profileGiftsContext) - controller.dismissAnimated() - navigationController.pushViewController(craftController) - } - } - ) - environment.controller()?.push(selectController) + } else if state.displayFailure { + craftAnotherGift() } else { HapticFeedback().impact(.medium) diff --git a/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/SelectCraftGiftScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/SelectCraftGiftScreen.swift index 456486acd9..e366d5df97 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/SelectCraftGiftScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftCraftScreen/Sources/SelectCraftGiftScreen.swift @@ -153,6 +153,8 @@ final class SelectGiftPageContent: Component { } transition.setFrame(view: self.loadingView, frame: CGRect(origin: CGPoint(x: 0.0, y: contentHeight - 170.0), size: loadingSize)) + let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) + var itemFrame = CGRect(origin: CGPoint(x: itemSideInset, y: contentHeight), size: itemSize) var itemsHeight: CGFloat = 0.0 var validIds: [AnyHashable] = [] @@ -245,6 +247,12 @@ final class SelectGiftPageContent: Component { } } itemTransition.setFrame(view: itemView, frame: itemFrame) + + var canCraft = true + if let profileGift = self.giftMap[gift.gift.id], let canCraftDate = profileGift.canCraftAt, currentTime < canCraftDate { + canCraft = false + } + transition.setAlpha(view: itemView, alpha: canCraft ? 1.0 : 0.5) } } @@ -414,6 +422,7 @@ final class SelectGiftPageContent: Component { contentHeight += 32.0 contentHeight = self.updateScrolling(interactive: false, transition: transition) + let originalContentHeight = contentHeight let resaleCount = component.genericGift.availability?.resale ?? 0 let saleTitle = environment.strings.Gift_Craft_Select_SaleGiftsCount(Int32(clamping: resaleCount)).uppercased() @@ -483,7 +492,11 @@ final class SelectGiftPageContent: Component { } transition.setFrame(view: storeGiftsView, frame: storeGiftsFrame) - storeGiftsView.updateScrolling(bounds: CGRect(origin: .zero, size: availableSize), transition: .immediate) + var effectiveBounds = CGRect(origin: .zero, size: CGSize(width: availableSize.width, height: 1000.0)) + if let bounds = self.currentBounds { + effectiveBounds = bounds.offsetBy(dx: 0.0, dy: -originalContentHeight) + } + storeGiftsView.updateScrolling(bounds: effectiveBounds, transition: .immediate) } contentHeight += storeGiftsSize.height contentHeight += 90.0 diff --git a/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftStoreScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftStoreScreen.swift index e711deca73..a9676d8f57 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftStoreScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftStoreScreen/Sources/GiftStoreScreen.swift @@ -183,7 +183,7 @@ public final class GiftStoreContentComponent: Component { if let initialCount = self.initialCount, initialCount < minimumCountToDisplayFilters { topInset = component.navigationHeight } - + let visibleBounds = bounds.insetBy(dx: 0.0, dy: -10.0) if let starGifts = self.effectiveGifts { let sideInset: CGFloat = 16.0 + component.safeInsets.left @@ -1269,8 +1269,10 @@ final class GiftStoreScreenComponent: Component { guard let self, let component = self.component, let environment = self.environment else { return } - let controller = component.context.sharedContext.makeStarsTransactionsScreen(context: component.context, starsContext: starsContext) - environment.controller()?.push(controller) + Queue.mainQueue().after(0.3) { + let controller = component.context.sharedContext.makeStarsTransactionsScreen(context: component.context, starsContext: starsContext) + environment.controller()?.push(controller) + } } ))) @@ -1283,8 +1285,10 @@ final class GiftStoreScreenComponent: Component { guard let self, let component = self.component, let environment = self.environment else { return } - let controller = component.context.sharedContext.makeStarsTransactionsScreen(context: component.context, starsContext: tonContext) - environment.controller()?.push(controller) + Queue.mainQueue().after(0.3) { + let controller = component.context.sharedContext.makeStarsTransactionsScreen(context: component.context, starsContext: tonContext) + environment.controller()?.push(controller) + } } ))) diff --git a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift index 7e082fd710..ad6c98bd12 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift @@ -4677,7 +4677,26 @@ private final class GiftViewSheetContent: CombinedComponent { ) let buttonChild: _UpdatedChildComponent - if state.canSkip { + if let controller = controller() as? GiftViewScreen, let customAction = controller.customAction { + buttonChild = button.update( + component: ButtonComponent( + background: buttonBackground, + content: AnyComponentWithIdentity( + id: AnyHashable("custom"), + component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: customAction.title, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)))) + ), + isEnabled: true, + displaysProgress: state.inProgress, + action: { [weak state] in + if let state { + customAction.action() + state.dismiss(animated: true) + } + }), + availableSize: buttonSize, + transition: context.transition + ) + } else if state.canSkip { buttonChild = button.update( component: ButtonComponent( background: buttonBackground, @@ -5630,6 +5649,16 @@ public class GiftViewScreen: ViewControllerComponentContainer { } } + public struct CustomAction { + public let title: String + public let action: () -> Void + + public init(title: String, action: @escaping () -> Void) { + self.title = title + self.action = action + } + } + private let context: AccountContext private let subject: GiftViewScreen.Subject @@ -5671,6 +5700,7 @@ public class GiftViewScreen: ViewControllerComponentContainer { fileprivate let togglePinnedToTop: ((StarGiftReference, Bool) -> Bool)? fileprivate let shareStory: ((StarGift.UniqueGift) -> Void)? fileprivate let openChatTheme: (() -> Void)? + fileprivate let customAction: CustomAction? public var disposed: () -> Void = {} @@ -5690,7 +5720,8 @@ public class GiftViewScreen: ViewControllerComponentContainer { updateResellStars: ((StarGiftReference, CurrencyAmount?) -> Signal)? = nil, togglePinnedToTop: ((StarGiftReference, Bool) -> Bool)? = nil, shareStory: ((StarGift.UniqueGift) -> Void)? = nil, - openChatTheme: (() -> Void)? = nil + openChatTheme: (() -> Void)? = nil, + customAction: CustomAction? = nil ) { self.context = context self.subject = subject @@ -5706,6 +5737,7 @@ public class GiftViewScreen: ViewControllerComponentContainer { self.togglePinnedToTop = togglePinnedToTop self.shareStory = shareStory self.openChatTheme = openChatTheme + self.customAction = customAction if case let .unique(gift) = subject.arguments?.gift, gift.resellForTonOnly { self.balanceCurrency = .ton