mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2026-02-22 18:43:14 +00:00
655 lines
28 KiB
Swift
655 lines
28 KiB
Swift
import Foundation
|
|
import UIKit
|
|
import Display
|
|
import ComponentFlow
|
|
import SwiftSignalKit
|
|
import TelegramCore
|
|
import TelegramPresentationData
|
|
import TelegramStringFormatting
|
|
import ViewControllerComponent
|
|
import BundleIconComponent
|
|
import MultilineTextComponent
|
|
import GiftItemComponent
|
|
import AccountContext
|
|
import AnimatedTextComponent
|
|
import Markdown
|
|
import PresentationDataUtils
|
|
import GiftViewScreen
|
|
import NavigationStackComponent
|
|
import GiftStoreScreen
|
|
import ResizableSheetComponent
|
|
import TooltipUI
|
|
import GlassBarButtonComponent
|
|
import ConfettiEffect
|
|
import GiftLoadingShimmerView
|
|
|
|
final class SelectGiftPageContent: Component {
|
|
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
|
|
|
let context: AccountContext
|
|
let craftContext: CraftGiftsContext
|
|
let resaleContext: ResaleGiftsContext
|
|
let gift: StarGift.UniqueGift
|
|
let genericGift: StarGift.Gift
|
|
let selectedGiftIds: Set<Int64>
|
|
let starsTopUpOptions: Signal<[StarsTopUpOption]?, NoError>
|
|
let selectGift: (GiftItem) -> Void
|
|
let dismiss: () -> Void
|
|
|
|
init(
|
|
context: AccountContext,
|
|
craftContext: CraftGiftsContext,
|
|
resaleContext: ResaleGiftsContext,
|
|
gift: StarGift.UniqueGift,
|
|
genericGift: StarGift.Gift,
|
|
selectedGiftIds: Set<Int64>,
|
|
starsTopUpOptions: Signal<[StarsTopUpOption]?, NoError>,
|
|
selectGift: @escaping (GiftItem) -> Void,
|
|
dismiss: @escaping () -> Void
|
|
) {
|
|
self.context = context
|
|
self.craftContext = craftContext
|
|
self.resaleContext = resaleContext
|
|
self.gift = gift
|
|
self.genericGift = genericGift
|
|
self.selectedGiftIds = selectedGiftIds
|
|
self.starsTopUpOptions = starsTopUpOptions
|
|
self.selectGift = selectGift
|
|
self.dismiss = dismiss
|
|
}
|
|
|
|
static func ==(lhs: SelectGiftPageContent, rhs: SelectGiftPageContent) -> Bool {
|
|
if lhs.context !== rhs.context {
|
|
return false
|
|
}
|
|
if lhs.gift != rhs.gift {
|
|
return false
|
|
}
|
|
if lhs.selectedGiftIds != rhs.selectedGiftIds {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
final class View: UIView, UIScrollViewDelegate {
|
|
private let myGiftsTitle = ComponentView<Empty>()
|
|
private var gifts: [AnyHashable: ComponentView<Empty>] = [:]
|
|
private let myGiftsPlaceholder = ComponentView<Empty>()
|
|
private let loadingView = GiftLoadingShimmerView()
|
|
|
|
private let storeGiftsTitle = ComponentView<Empty>()
|
|
private let storeGifts = ComponentView<Empty>()
|
|
|
|
private var craftState: CraftGiftsContext.State?
|
|
private var craftStateDisposable: Disposable?
|
|
|
|
private var availableGifts: [GiftItem] = []
|
|
private var giftMap: [Int64: GiftItem] = [:]
|
|
|
|
private var component: SelectGiftPageContent?
|
|
private weak var state: EmptyComponentState?
|
|
private var environment: ViewControllerComponentContainer.Environment?
|
|
private var isUpdating: Bool = false
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
|
|
self.layer.cornerRadius = 40.0
|
|
self.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
|
|
|
|
self.addSubview(self.loadingView)
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
deinit {
|
|
self.craftStateDisposable?.dispose()
|
|
}
|
|
|
|
func update(component: SelectGiftPageContent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<ViewControllerComponentContainer.Environment>, transition: ComponentTransition) -> CGSize {
|
|
self.isUpdating = true
|
|
defer {
|
|
self.isUpdating = false
|
|
}
|
|
|
|
if self.component == nil {
|
|
let initialGiftItem = GiftItem(
|
|
gift: component.gift,
|
|
reference: .slug(slug: component.gift.slug)
|
|
)
|
|
self.availableGifts = [
|
|
initialGiftItem
|
|
]
|
|
self.giftMap = [initialGiftItem.gift.id: initialGiftItem]
|
|
|
|
self.craftStateDisposable = (component.craftContext.state
|
|
|> deliverOnMainQueue).start(next: { [weak self] state in
|
|
guard let self else {
|
|
return
|
|
}
|
|
//let isFirstTime = self.craftState == nil
|
|
self.craftState = state
|
|
|
|
var items: [GiftItem] = []
|
|
var map: [Int64: GiftItem] = [:]
|
|
var foundInitial = false
|
|
for gift in state.gifts {
|
|
guard let reference = gift.reference, case let .unique(uniqueGift) = gift.gift else {
|
|
continue
|
|
}
|
|
let giftItem = GiftItem(
|
|
gift: uniqueGift,
|
|
reference: reference
|
|
)
|
|
map[uniqueGift.id] = giftItem
|
|
if uniqueGift.id == component.gift.id {
|
|
foundInitial = true
|
|
} else {
|
|
if component.selectedGiftIds.contains(uniqueGift.id) {
|
|
continue
|
|
}
|
|
items.append(giftItem)
|
|
}
|
|
}
|
|
|
|
if !foundInitial {
|
|
map[initialGiftItem.gift.id] = initialGiftItem
|
|
}
|
|
self.availableGifts = items
|
|
self.giftMap = map
|
|
|
|
self.state?.updated(transition: .spring(duration: 0.4))
|
|
})
|
|
}
|
|
|
|
let environment = environment[ViewControllerComponentContainer.Environment.self].value
|
|
|
|
let sideInset: CGFloat = 16.0 + environment.safeInsets.left
|
|
|
|
self.component = component
|
|
self.state = state
|
|
self.environment = environment
|
|
|
|
self.backgroundColor = environment.theme.actionSheet.opaqueItemBackgroundColor
|
|
|
|
var contentHeight: CGFloat = 88.0
|
|
|
|
let myGiftsTitleSize = self.myGiftsTitle.update(
|
|
transition: transition,
|
|
component: AnyComponent(
|
|
MultilineTextComponent(text: .plain(NSAttributedString(string: "Your Gifts".uppercased(), font: Font.semibold(14.0), textColor: environment.theme.actionSheet.secondaryTextColor)))
|
|
),
|
|
environment: {},
|
|
containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 100.0)
|
|
)
|
|
let myGiftsTitleFrame = CGRect(origin: CGPoint(x: 26.0, y: contentHeight), size: myGiftsTitleSize)
|
|
if let myGiftsTitleView = self.myGiftsTitle.view {
|
|
if myGiftsTitleView.superview == nil {
|
|
self.addSubview(myGiftsTitleView)
|
|
}
|
|
transition.setFrame(view: myGiftsTitleView, frame: myGiftsTitleFrame)
|
|
}
|
|
|
|
contentHeight += 32.0
|
|
|
|
let itemSpacing: CGFloat = 10.0
|
|
let itemSideInset = 16.0
|
|
let itemsInRow: Int
|
|
if availableSize.width > availableSize.height || availableSize.width > 480.0 {
|
|
if case .tablet = environment.deviceMetrics.type {
|
|
itemsInRow = 4
|
|
} else {
|
|
itemsInRow = 5
|
|
}
|
|
} else {
|
|
itemsInRow = 3
|
|
}
|
|
let itemWidth = (availableSize.width - itemSideInset * 2.0 - itemSpacing * CGFloat(itemsInRow - 1)) / CGFloat(itemsInRow)
|
|
let itemSize = CGSize(width: itemWidth, height: itemWidth)
|
|
|
|
|
|
var isLoading = false
|
|
if self.availableGifts.isEmpty, case .loading = (self.craftState?.dataState ?? .loading) {
|
|
isLoading = true
|
|
}
|
|
let loadingTransition: ComponentTransition = .easeInOut(duration: 0.25)
|
|
let loadingSize = CGSize(width: availableSize.width, height: 180.0)
|
|
if isLoading {
|
|
contentHeight += 120.0
|
|
self.loadingView.update(size: loadingSize, theme: environment.theme, itemSize: itemSize, showFilters: false, isPlain: true, transition: .immediate)
|
|
loadingTransition.setAlpha(view: self.loadingView, alpha: 1.0)
|
|
} else {
|
|
loadingTransition.setAlpha(view: self.loadingView, alpha: 0.0)
|
|
}
|
|
transition.setFrame(view: self.loadingView, frame: CGRect(origin: CGPoint(x: 0.0, y: contentHeight - 170.0), size: loadingSize))
|
|
|
|
var itemFrame = CGRect(origin: CGPoint(x: itemSideInset, y: contentHeight), size: itemSize)
|
|
var itemsHeight: CGFloat = 0.0
|
|
var validIds: [AnyHashable] = []
|
|
for gift in self.availableGifts {
|
|
let isVisible = "".isEmpty
|
|
// if visibleBounds.intersects(itemFrame) {
|
|
// isVisible = true
|
|
// }
|
|
if isVisible {
|
|
let itemId = AnyHashable(gift.gift.id)
|
|
validIds.append(itemId)
|
|
|
|
var itemTransition = transition
|
|
let visibleItem: ComponentView<Empty>
|
|
if let current = self.gifts[itemId] {
|
|
visibleItem = current
|
|
} else {
|
|
visibleItem = ComponentView()
|
|
self.gifts[itemId] = visibleItem
|
|
itemTransition = .immediate
|
|
}
|
|
|
|
var ribbonColor: GiftItemComponent.Ribbon.Color = .blue
|
|
let ribbonText = "#\(gift.gift.number)"
|
|
for attribute in gift.gift.attributes {
|
|
if case let .backdrop(_, _, innerColor, outerColor, _, _, _) = attribute {
|
|
ribbonColor = .custom(outerColor, innerColor)
|
|
break
|
|
}
|
|
}
|
|
|
|
let badge: String? = gift.gift.craftChancePermille.flatMap { "+\($0 / 10)%" }
|
|
|
|
let _ = visibleItem.update(
|
|
transition: itemTransition,
|
|
component: AnyComponent(
|
|
GiftItemComponent(
|
|
context: component.context,
|
|
style: .glass,
|
|
theme: environment.theme,
|
|
strings: environment.strings,
|
|
peer: nil,
|
|
subject: .uniqueGift(gift: gift.gift, price: nil),
|
|
ribbon: GiftItemComponent.Ribbon(text: ribbonText, font: .monospaced, color: ribbonColor, outline: nil),
|
|
badge: badge,
|
|
resellPrice: nil,
|
|
isHidden: false,
|
|
isSelected: false,
|
|
isPinned: false,
|
|
isEditing: false,
|
|
mode: .grid,
|
|
action: { [weak self] in
|
|
guard let self, let component = self.component else {
|
|
return
|
|
}
|
|
component.selectGift(gift)
|
|
component.dismiss()
|
|
},
|
|
contextAction: { _, _ in }
|
|
)
|
|
),
|
|
environment: {},
|
|
containerSize: itemSize
|
|
)
|
|
if let itemView = visibleItem.view {
|
|
if itemView.superview == nil {
|
|
if let _ = self.loadingView.superview {
|
|
self.insertSubview(itemView, belowSubview: self.loadingView)
|
|
} else {
|
|
self.addSubview(itemView)
|
|
}
|
|
if !transition.animation.isImmediate {
|
|
itemView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
|
|
}
|
|
}
|
|
itemTransition.setFrame(view: itemView, frame: itemFrame)
|
|
}
|
|
}
|
|
|
|
itemsHeight = itemFrame.maxY - contentHeight
|
|
|
|
itemFrame.origin.x += itemFrame.width + itemSpacing
|
|
if itemFrame.maxX > availableSize.width {
|
|
itemFrame.origin.x = itemSideInset
|
|
itemFrame.origin.y += itemSize.height + itemSpacing
|
|
}
|
|
}
|
|
|
|
var removeIds: [AnyHashable] = []
|
|
for (id, item) in self.gifts {
|
|
if !validIds.contains(id) {
|
|
removeIds.append(id)
|
|
if let itemView = item.view {
|
|
if !transition.animation.isImmediate {
|
|
itemView.layer.animateScale(from: 1.0, to: 0.01, duration: 0.25, removeOnCompletion: false)
|
|
itemView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false, completion: { _ in
|
|
itemView.removeFromSuperview()
|
|
})
|
|
} else {
|
|
itemView.removeFromSuperview()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for id in removeIds {
|
|
self.gifts.removeValue(forKey: id)
|
|
}
|
|
|
|
if let state = self.craftState, case .ready = state.dataState, self.availableGifts.isEmpty {
|
|
contentHeight += 10.0
|
|
let myGiftsPlaceholderSize = self.myGiftsPlaceholder.update(
|
|
transition: .immediate,
|
|
component: AnyComponent(
|
|
MultilineTextComponent(
|
|
text: .plain(NSAttributedString(string: "You don't have other gifts\nfrom this collection", font: Font.regular(13.0), textColor: environment.theme.list.itemSecondaryTextColor)),
|
|
horizontalAlignment: .center,
|
|
maximumNumberOfLines: 3,
|
|
lineSpacing: 0.1
|
|
)
|
|
),
|
|
environment: {},
|
|
containerSize: CGSize(width: availableSize.width - 32.0, height: .greatestFiniteMagnitude)
|
|
)
|
|
let myGiftsPlaceholderFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - myGiftsPlaceholderSize.width) / 2.0), y: contentHeight), size: myGiftsPlaceholderSize)
|
|
if let myGiftsPlaceholderView = self.myGiftsPlaceholder.view {
|
|
if myGiftsPlaceholderView.superview == nil {
|
|
self.addSubview(myGiftsPlaceholderView)
|
|
}
|
|
myGiftsPlaceholderView.frame = myGiftsPlaceholderFrame
|
|
}
|
|
contentHeight += myGiftsPlaceholderSize.height
|
|
contentHeight += 32.0
|
|
} else {
|
|
contentHeight += itemsHeight
|
|
contentHeight += 24.0
|
|
}
|
|
|
|
let storeGiftsTitleSize = self.storeGiftsTitle.update(
|
|
transition: transition,
|
|
component: AnyComponent(
|
|
MultilineTextComponent(text: .plain(NSAttributedString(string: "SUITABLE GIFTS ON SALE".uppercased(), font: Font.semibold(14.0), textColor: environment.theme.actionSheet.secondaryTextColor)))
|
|
),
|
|
environment: {},
|
|
containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 100.0)
|
|
)
|
|
let storeGiftsTitleFrame = CGRect(origin: CGPoint(x: 26.0, y: contentHeight), size: storeGiftsTitleSize)
|
|
if let storeGiftsTitleView = self.storeGiftsTitle.view {
|
|
if storeGiftsTitleView.superview == nil {
|
|
self.addSubview(storeGiftsTitleView)
|
|
}
|
|
transition.setFrame(view: storeGiftsTitleView, frame: storeGiftsTitleFrame)
|
|
}
|
|
contentHeight += 28.0
|
|
|
|
self.storeGifts.parentState = state
|
|
let storeGiftsSize = self.storeGifts.update(
|
|
transition: transition,
|
|
component: AnyComponent(
|
|
GiftStoreContentComponent(
|
|
context: component.context,
|
|
resaleGiftsContext: component.resaleContext,
|
|
theme: environment.theme,
|
|
strings: environment.strings,
|
|
dateTimeFormat: environment.dateTimeFormat,
|
|
safeInsets: UIEdgeInsets(),
|
|
statusBarHeight: contentHeight - 62.0,
|
|
navigationHeight: 0.0,
|
|
overNavigationContainer: self,
|
|
starsContext: component.context.starsContext!,
|
|
peerId: component.context.account.peerId,
|
|
gift: component.genericGift,
|
|
isPlain: true,
|
|
confirmPurchaseImmediately: true,
|
|
starsTopUpOptions: component.starsTopUpOptions,
|
|
scrollToTop: {},
|
|
controller: environment.controller,
|
|
completion: { [weak self] uniqueGift in
|
|
guard let self, let component = self.component, let controller = self.environment?.controller() as? SelectCraftGiftScreen, let navigationController = controller.navigationController else {
|
|
return
|
|
}
|
|
let giftItem = GiftItem(gift: uniqueGift, reference: .slug(slug: uniqueGift.slug))
|
|
component.selectGift(giftItem)
|
|
component.dismiss()
|
|
|
|
navigationController.view.addSubview(ConfettiView(frame: navigationController.view.bounds))
|
|
|
|
Queue.mainQueue().after(1.0) {
|
|
component.craftContext.reload()
|
|
}
|
|
}
|
|
)
|
|
),
|
|
environment: {},
|
|
containerSize: CGSize(width: availableSize.width, height: .greatestFiniteMagnitude)
|
|
)
|
|
let storeGiftsFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: storeGiftsSize)
|
|
if let storeGiftsView = self.storeGifts.view as? GiftStoreContentComponent.View {
|
|
if storeGiftsView.superview == nil {
|
|
self.insertSubview(storeGiftsView, at: 0)
|
|
}
|
|
transition.setFrame(view: storeGiftsView, frame: storeGiftsFrame)
|
|
|
|
storeGiftsView.updateScrolling(bounds: CGRect(origin: .zero, size: availableSize), transition: .immediate)
|
|
}
|
|
contentHeight += storeGiftsSize.height
|
|
contentHeight += 90.0
|
|
|
|
return CGSize(width: availableSize.width, height: contentHeight)
|
|
}
|
|
}
|
|
|
|
func makeView() -> View {
|
|
return View(frame: CGRect())
|
|
}
|
|
|
|
func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<ViewControllerComponentContainer.Environment>, transition: ComponentTransition) -> CGSize {
|
|
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
|
|
}
|
|
}
|
|
|
|
private final class SheetContainerComponent: CombinedComponent {
|
|
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
|
|
|
let context: AccountContext
|
|
let craftContext: CraftGiftsContext
|
|
let resaleContext: ResaleGiftsContext
|
|
let gift: StarGift.UniqueGift
|
|
let genericGift: StarGift.Gift
|
|
let selectedGiftIds: Set<Int64>
|
|
let starsTopUpOptions: Signal<[StarsTopUpOption]?, NoError>
|
|
let selectGift: (GiftItem) -> Void
|
|
|
|
init(
|
|
context: AccountContext,
|
|
craftContext: CraftGiftsContext,
|
|
resaleContext: ResaleGiftsContext,
|
|
gift: StarGift.UniqueGift,
|
|
genericGift: StarGift.Gift,
|
|
selectedGiftIds: Set<Int64>,
|
|
starsTopUpOptions: Signal<[StarsTopUpOption]?, NoError>,
|
|
selectGift: @escaping (GiftItem) -> Void
|
|
) {
|
|
self.context = context
|
|
self.craftContext = craftContext
|
|
self.resaleContext = resaleContext
|
|
self.gift = gift
|
|
self.genericGift = genericGift
|
|
self.selectedGiftIds = selectedGiftIds
|
|
self.starsTopUpOptions = starsTopUpOptions
|
|
self.selectGift = selectGift
|
|
}
|
|
|
|
static func ==(lhs: SheetContainerComponent, rhs: SheetContainerComponent) -> Bool {
|
|
if lhs.context !== rhs.context {
|
|
return false
|
|
}
|
|
if lhs.gift != rhs.gift {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
final class State: ComponentState {
|
|
}
|
|
|
|
func makeState() -> State {
|
|
return State()
|
|
}
|
|
|
|
static var body: Body {
|
|
let sheet = Child(ResizableSheetComponent<EnvironmentType>.self)
|
|
let animateOut = StoredActionSlot(Action<Void>.self)
|
|
|
|
return { context in
|
|
let component = context.component
|
|
let environment = context.environment[EnvironmentType.self]
|
|
|
|
let controller = environment.controller
|
|
|
|
let dismiss: (Bool) -> Void = { animated in
|
|
if animated {
|
|
animateOut.invoke(Action { _ in
|
|
if let controller = controller() {
|
|
controller.dismiss(completion: nil)
|
|
}
|
|
})
|
|
} else {
|
|
if let controller = controller() {
|
|
controller.dismiss(completion: nil)
|
|
}
|
|
}
|
|
}
|
|
|
|
let theme = environment.theme
|
|
|
|
let backgroundColor = environment.theme.list.modalPlainBackgroundColor
|
|
|
|
let sheet = sheet.update(
|
|
component: ResizableSheetComponent<EnvironmentType>(
|
|
content: AnyComponent<EnvironmentType>(
|
|
SelectGiftPageContent(
|
|
context: component.context,
|
|
craftContext: component.craftContext,
|
|
resaleContext: component.resaleContext,
|
|
gift: component.gift,
|
|
genericGift: component.genericGift,
|
|
selectedGiftIds: component.selectedGiftIds,
|
|
starsTopUpOptions: component.starsTopUpOptions,
|
|
selectGift: component.selectGift,
|
|
dismiss: {
|
|
dismiss(true)
|
|
}
|
|
)
|
|
),
|
|
titleItem: AnyComponent(
|
|
MultilineTextComponent(text: .plain(NSAttributedString(string: "Select Gifts", font: Font.semibold(17.0), textColor: environment.theme.actionSheet.primaryTextColor)))
|
|
),
|
|
leftItem: AnyComponent(
|
|
GlassBarButtonComponent(
|
|
size: CGSize(width: 44.0, height: 44.0),
|
|
backgroundColor: nil,
|
|
isDark: theme.overallDarkAppearance,
|
|
state: .glass,
|
|
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
|
|
BundleIconComponent(
|
|
name: "Navigation/Close",
|
|
tintColor: theme.chat.inputPanel.panelControlColor
|
|
)
|
|
)),
|
|
action: { _ in
|
|
dismiss(true)
|
|
}
|
|
)
|
|
),
|
|
rightItem: nil,
|
|
bottomItem: nil,
|
|
backgroundColor: .color(backgroundColor),
|
|
isFullscreen: false,
|
|
animateOut: animateOut
|
|
),
|
|
environment: {
|
|
environment
|
|
ResizableSheetComponentEnvironment(
|
|
theme: theme,
|
|
statusBarHeight: environment.statusBarHeight,
|
|
safeInsets: environment.safeInsets,
|
|
metrics: environment.metrics,
|
|
deviceMetrics: environment.deviceMetrics,
|
|
isDisplaying: environment.value.isVisible,
|
|
isCentered: environment.metrics.widthClass == .regular,
|
|
screenSize: context.availableSize,
|
|
regularMetricsSize: CGSize(width: 430.0, height: 900.0),
|
|
dismiss: { animated in
|
|
dismiss(animated)
|
|
}
|
|
)
|
|
},
|
|
availableSize: context.availableSize,
|
|
transition: context.transition
|
|
)
|
|
|
|
context.add(sheet
|
|
.position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height / 2.0))
|
|
)
|
|
|
|
return context.availableSize
|
|
}
|
|
}
|
|
}
|
|
|
|
final class SelectCraftGiftScreen: ViewControllerComponentContainer {
|
|
public init(
|
|
context: AccountContext,
|
|
craftContext: CraftGiftsContext,
|
|
resaleContext: ResaleGiftsContext,
|
|
gift: StarGift.UniqueGift,
|
|
genericGift: StarGift.Gift,
|
|
selectedGiftIds: Set<Int64>,
|
|
starsTopUpOptions: Signal<[StarsTopUpOption]?, NoError>,
|
|
selectGift: @escaping (GiftItem) -> Void
|
|
) {
|
|
super.init(
|
|
context: context,
|
|
component: SheetContainerComponent(
|
|
context: context,
|
|
craftContext: craftContext,
|
|
resaleContext: resaleContext,
|
|
gift: gift,
|
|
genericGift: genericGift,
|
|
selectedGiftIds: selectedGiftIds,
|
|
starsTopUpOptions: starsTopUpOptions,
|
|
selectGift: selectGift
|
|
),
|
|
navigationBarAppearance: .none,
|
|
statusBarStyle: .ignore,
|
|
theme: .default
|
|
)
|
|
|
|
self.navigationPresentation = .flatModal
|
|
}
|
|
|
|
required public init(coder aDecoder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
fileprivate func dismissAllTooltips() {
|
|
self.window?.forEachController({ controller in
|
|
if let controller = controller as? TooltipScreen {
|
|
controller.dismiss(inPlace: false)
|
|
}
|
|
})
|
|
self.forEachController({ controller in
|
|
if let controller = controller as? TooltipScreen {
|
|
controller.dismiss(inPlace: false)
|
|
}
|
|
return true
|
|
})
|
|
}
|
|
|
|
public func dismissAnimated() {
|
|
self.dismissAllTooltips()
|
|
|
|
if let view = self.node.hostView.findTaggedView(tag: ResizableSheetComponent<ViewControllerComponentContainer.Environment>.View.Tag()) as? ResizableSheetComponent<ViewControllerComponentContainer.Environment>.View {
|
|
view.dismissAnimated()
|
|
}
|
|
}
|
|
}
|