mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-29 11:25:38 +00:00
Various improvements
This commit is contained in:
parent
99840de8d7
commit
ac28ed9d74
@ -15180,7 +15180,7 @@ Error: %8$@";
|
|||||||
"Notification.GiftAuction.Acquired" = "You've successfully bought a gift in the auction for %@.";
|
"Notification.GiftAuction.Acquired" = "You've successfully bought a gift in the auction for %@.";
|
||||||
|
|
||||||
"Gift.Auction.Auction" = "auction";
|
"Gift.Auction.Auction" = "auction";
|
||||||
"Gift.Auction.Description" = "Top %@ bidders will get a **%@** this round. [Learn More >]()";
|
"Gift.Auction.Description" = "Top %@ bidders will get **%@** gifts this round. [Learn More >]()";
|
||||||
"Gift.Auction.Ended" = "Auction ended";
|
"Gift.Auction.Ended" = "Auction ended";
|
||||||
"Gift.Auction.FirstSale" = "First Sale";
|
"Gift.Auction.FirstSale" = "First Sale";
|
||||||
"Gift.Auction.LastSale" = "Last Sale";
|
"Gift.Auction.LastSale" = "Last Sale";
|
||||||
@ -15213,6 +15213,14 @@ Error: %8$@";
|
|||||||
"Gift.AuctionBid.TopWinners" = "Top 3 Winners";
|
"Gift.AuctionBid.TopWinners" = "Top 3 Winners";
|
||||||
"Gift.AuctionBid.PlaceBid" = "Place a %@ Bid";
|
"Gift.AuctionBid.PlaceBid" = "Place a %@ Bid";
|
||||||
"Gift.AuctionBid.AddToBid" = "Add %@ to Your Bid";
|
"Gift.AuctionBid.AddToBid" = "Add %@ to Your Bid";
|
||||||
|
"Gift.AuctionBid.Placed.Title" = "Your bid has been placed";
|
||||||
|
"Gift.AuctionBid.Placed.Text" = "If you fall below the top %@, your bid will roll over to the next drop.";
|
||||||
|
"Gift.AuctionBid.Increased.Title" = "Your bid has been increased";
|
||||||
|
"Gift.AuctionBid.Increased.Text" = "If you fall below the top %@, your bid will roll over to the next drop.";
|
||||||
|
"Gift.AuctionBid.AddMoreStars" = "Add at least %@ to increase your bid.";
|
||||||
|
"Gift.AuctionBid.AddMoreStars.Stars_1" = "%@ Star";
|
||||||
|
"Gift.AuctionBid.AddMoreStars.Stars_any" = "%@ Stars";
|
||||||
|
"Gift.AuctionBid.Top" = "TOP %@";
|
||||||
|
|
||||||
"Gift.Auction.Context.About" = "About";
|
"Gift.Auction.Context.About" = "About";
|
||||||
"Gift.Auction.Context.CopyLink" = "Copy Link";
|
"Gift.Auction.Context.CopyLink" = "Copy Link";
|
||||||
@ -15264,3 +15272,24 @@ Error: %8$@";
|
|||||||
"Gift.Auction.Ongoing.Text" = "You’ve already bid in this gift auction for **%@**.";
|
"Gift.Auction.Ongoing.Text" = "You’ve already bid in this gift auction for **%@**.";
|
||||||
"Gift.Auction.Ongoing.TextYourself" = "You’ve already bid in this gift auction for yourself.";
|
"Gift.Auction.Ongoing.TextYourself" = "You’ve already bid in this gift auction for yourself.";
|
||||||
"Gift.Auction.Ongoing.View" = "View";
|
"Gift.Auction.Ongoing.View" = "View";
|
||||||
|
|
||||||
|
"Gift.Auction.Info.Title" = "Auction";
|
||||||
|
"Gift.Auction.Info.Description" = "Join the battle for exclusive gifts.";
|
||||||
|
|
||||||
|
"Gift.Auction.Info.TopBidders.Title_1" = "Top %@ Bidder";
|
||||||
|
"Gift.Auction.Info.TopBidders.Title_any" = "Top %@ Bidders";
|
||||||
|
"Gift.Auction.Info.TopBidders.Text" = "%@ are dropped in %@ to the top %@ by bid amount.";
|
||||||
|
"Gift.Auction.Info.TopBidders.Gifts_1" = "%@ gift";
|
||||||
|
"Gift.Auction.Info.TopBidders.Gifts_any" = "%@ gifts";
|
||||||
|
"Gift.Auction.Info.TopBidders.Rounds_1" = "%@ round";
|
||||||
|
"Gift.Auction.Info.TopBidders.Rounds_any" = "%@ rounds";
|
||||||
|
"Gift.Auction.Info.TopBidders.Bidders_1" = "%@ bidder";
|
||||||
|
"Gift.Auction.Info.TopBidders.Bidders_any" = "%@ bidders";
|
||||||
|
|
||||||
|
"Gift.Auction.Info.Carryover.Title" = "Bid Carryover";
|
||||||
|
"Gift.Auction.Info.Carryover.Text" = "If your bid leaves the top %@, it will automatically join the next drop.";
|
||||||
|
|
||||||
|
"Gift.Auction.Info.Missed.Title" = "Missed Bidders";
|
||||||
|
"Gift.Auction.Info.Missed.Text" = "If your bid doesn't win after the final drop, your Stars will be fully refunded.";
|
||||||
|
|
||||||
|
"Gift.Auction.Info.Understood" = "Understood";
|
||||||
|
|||||||
@ -1422,7 +1422,7 @@ public protocol SharedAccountContext: AnyObject {
|
|||||||
func makeGiftViewScreen(context: AccountContext, message: EngineMessage, shareStory: ((StarGift.UniqueGift) -> Void)?) -> ViewController
|
func makeGiftViewScreen(context: AccountContext, message: EngineMessage, shareStory: ((StarGift.UniqueGift) -> Void)?) -> ViewController
|
||||||
func makeGiftViewScreen(context: AccountContext, gift: StarGift.UniqueGift, shareStory: ((StarGift.UniqueGift) -> Void)?, openChatTheme: (() -> Void)?, dismissed: (() -> Void)?) -> ViewController
|
func makeGiftViewScreen(context: AccountContext, gift: StarGift.UniqueGift, shareStory: ((StarGift.UniqueGift) -> Void)?, openChatTheme: (() -> Void)?, dismissed: (() -> Void)?) -> ViewController
|
||||||
func makeGiftWearPreviewScreen(context: AccountContext, gift: StarGift.UniqueGift) -> ViewController
|
func makeGiftWearPreviewScreen(context: AccountContext, gift: StarGift.UniqueGift) -> ViewController
|
||||||
func makeGiftAuctionInfoScreen(context: AccountContext, gift: StarGift, completion: (() -> Void)?) -> ViewController
|
func makeGiftAuctionInfoScreen(context: AccountContext, auctionContext: GiftAuctionContext, completion: (() -> Void)?) -> ViewController
|
||||||
func makeGiftAuctionBidScreen(context: AccountContext, auctionContext: GiftAuctionContext) -> ViewController
|
func makeGiftAuctionBidScreen(context: AccountContext, auctionContext: GiftAuctionContext) -> ViewController
|
||||||
func makeGiftAuctionViewScreen(context: AccountContext, auctionContext: GiftAuctionContext) -> ViewController
|
func makeGiftAuctionViewScreen(context: AccountContext, auctionContext: GiftAuctionContext) -> ViewController
|
||||||
func makeGiftAuctionActiveBidsScreen(context: AccountContext) -> ViewController
|
func makeGiftAuctionActiveBidsScreen(context: AccountContext) -> ViewController
|
||||||
|
|||||||
@ -91,7 +91,7 @@ public final class GiftAuctionContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public var currentBidPeerId: EnginePeer.Id? {
|
public var currentBidPeerId: EnginePeer.Id? {
|
||||||
if self.myState?.bidAmount != nil {
|
if self.myState?.bidAmount != nil, case .ongoing = self.auctionState {
|
||||||
return self.myState?.bidPeerId
|
return self.myState?.bidPeerId
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
@ -145,10 +145,19 @@ public final class GiftAuctionContext {
|
|||||||
self.myState = myState
|
self.myState = myState
|
||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
|
|
||||||
|
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||||
|
var effectiveTimeout = timeout
|
||||||
|
if case let .ongoing(_, _, _, _, _, _, nextRoundDate, _, _, _) = auctionState {
|
||||||
|
let delta = nextRoundDate - currentTime
|
||||||
|
if delta > 0 && delta < timeout {
|
||||||
|
effectiveTimeout = delta
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.pushState()
|
self.pushState()
|
||||||
|
|
||||||
self.updateTimer?.invalidate()
|
self.updateTimer?.invalidate()
|
||||||
self.updateTimer = SwiftSignalKit.Timer(timeout: Double(timeout), repeat: false, completion: { [weak self] _ in
|
self.updateTimer = SwiftSignalKit.Timer(timeout: Double(effectiveTimeout), repeat: false, completion: { [weak self] _ in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -385,11 +394,11 @@ public class GiftAuctionsManager {
|
|||||||
guard let self, let activeAuctions else {
|
guard let self, let activeAuctions else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var auctionContexts: [Int64 : GiftAuctionContext] = [:]
|
|
||||||
for auction in activeAuctions {
|
for auction in activeAuctions {
|
||||||
auctionContexts[auction.gift.giftId] = auction
|
if self.auctionContexts[auction.gift.giftId] == nil {
|
||||||
|
self.auctionContexts[auction.gift.giftId] = auction
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.auctionContexts = auctionContexts
|
|
||||||
self.updateState()
|
self.updateState()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -417,7 +426,7 @@ public class GiftAuctionsManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func storeAuctionContext(auctionContext: GiftAuctionContext) {
|
public func storeAuctionContext(auctionContext: GiftAuctionContext) {
|
||||||
self.auctionContexts[auctionContext.gift.giftId] = auctionContext
|
self.auctionContexts[auctionContext.gift.giftId] = auctionContext
|
||||||
self.updateState()
|
self.updateState()
|
||||||
}
|
}
|
||||||
@ -427,7 +436,7 @@ public class GiftAuctionsManager {
|
|||||||
for auction in self.auctionContexts.values.sorted(by: { $0.gift.giftId < $1.gift.giftId }) {
|
for auction in self.auctionContexts.values.sorted(by: { $0.gift.giftId < $1.gift.giftId }) {
|
||||||
signals.append(auction.state
|
signals.append(auction.state
|
||||||
|> mapToSignal { state in
|
|> mapToSignal { state in
|
||||||
if let state, state.myState.bidAmount != nil {
|
if let state, state.myState.bidAmount != nil, case .ongoing = state.auctionState {
|
||||||
return .single(state)
|
return .single(state)
|
||||||
} else {
|
} else {
|
||||||
return .complete()
|
return .complete()
|
||||||
|
|||||||
@ -369,11 +369,22 @@ final class GiftOptionsScreenComponent: Component {
|
|||||||
guard let giftAuctionsManager = component.context.giftAuctionsManager else {
|
guard let giftAuctionsManager = component.context.giftAuctionsManager else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.loadingGiftId = gift.id
|
||||||
|
Queue.mainQueue().after(0.25) {
|
||||||
|
if self.loadingGiftId != nil {
|
||||||
|
self.state?.updated()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.auctionDisposable.set((giftAuctionsManager.auctionContext(for: .giftId(gift.id))
|
self.auctionDisposable.set((giftAuctionsManager.auctionContext(for: .giftId(gift.id))
|
||||||
|> deliverOnMainQueue).start(next: { [weak self, weak mainController] auctionContext in
|
|> deliverOnMainQueue).start(next: { [weak self, weak mainController] auctionContext in
|
||||||
guard let auctionContext, let component = self?.component, let mainController else {
|
guard let self, let auctionContext, let component = self.component, let mainController else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
self.loadingGiftId = nil
|
||||||
|
self.state?.updated()
|
||||||
|
|
||||||
if let currentBidPeerId = auctionContext.currentBidPeerId {
|
if let currentBidPeerId = auctionContext.currentBidPeerId {
|
||||||
if currentBidPeerId == component.peerId {
|
if currentBidPeerId == component.peerId {
|
||||||
let giftController = component.context.sharedContext.makeGiftAuctionBidScreen(
|
let giftController = component.context.sharedContext.makeGiftAuctionBidScreen(
|
||||||
@ -1317,6 +1328,13 @@ final class GiftOptionsScreenComponent: Component {
|
|||||||
let hasAnyGifts = hasGenericGifts || hasTransferGifts
|
let hasAnyGifts = hasGenericGifts || hasTransferGifts
|
||||||
|
|
||||||
if isSelfGift || isChannelGift || isPremiumDisabled {
|
if isSelfGift || isChannelGift || isPremiumDisabled {
|
||||||
|
if !self.premiumItems.isEmpty {
|
||||||
|
for (_, itemView) in self.premiumItems {
|
||||||
|
itemView.view?.removeFromSuperview()
|
||||||
|
}
|
||||||
|
self.premiumItems.removeAll()
|
||||||
|
}
|
||||||
|
|
||||||
contentHeight += 6.0
|
contentHeight += 6.0
|
||||||
} else {
|
} else {
|
||||||
if let premiumProducts = state.premiumProducts {
|
if let premiumProducts = state.premiumProducts {
|
||||||
|
|||||||
@ -810,11 +810,10 @@ private final class SliderBackgroundComponent: Component {
|
|||||||
topLineFrameTransition.setFrame(layer: self.topBackgroundLine, frame: topLineFrame)
|
topLineFrameTransition.setFrame(layer: self.topBackgroundLine, frame: topLineFrame)
|
||||||
topLineAlphaTransition.setAlpha(layer: self.topBackgroundLine, alpha: topLineAlpha)
|
topLineAlphaTransition.setAlpha(layer: self.topBackgroundLine, alpha: topLineAlpha)
|
||||||
|
|
||||||
//TODO:localize
|
|
||||||
let topTextSize = self.topForegroundText.update(
|
let topTextSize = self.topForegroundText.update(
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(MultilineTextComponent(
|
component: AnyComponent(MultilineTextComponent(
|
||||||
text: .plain(NSAttributedString(string: "TOP \(component.giftsPerRound)", font: Font.semibold(15.0), textColor: UIColor(white: 1.0, alpha: 0.4)))
|
text: .plain(NSAttributedString(string: component.strings.Gift_AuctionBid_Top("\(component.giftsPerRound)").string, font: Font.semibold(15.0), textColor: UIColor(white: 1.0, alpha: 0.4)))
|
||||||
)),
|
)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: availableSize.width, height: 100.0)
|
containerSize: CGSize(width: availableSize.width, height: 100.0)
|
||||||
@ -822,7 +821,7 @@ private final class SliderBackgroundComponent: Component {
|
|||||||
let _ = self.topBackgroundText.update(
|
let _ = self.topBackgroundText.update(
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(MultilineTextComponent(
|
component: AnyComponent(MultilineTextComponent(
|
||||||
text: .plain(NSAttributedString(string: "TOP \(component.giftsPerRound)", font: Font.semibold(15.0), textColor: component.theme.overallDarkAppearance ? UIColor(white: 1.0, alpha: 0.22) : UIColor(white: 0.0, alpha: 0.2)))
|
text: .plain(NSAttributedString(string: component.strings.Gift_AuctionBid_Top("\(component.giftsPerRound)").string, font: Font.semibold(15.0), textColor: component.theme.overallDarkAppearance ? UIColor(white: 1.0, alpha: 0.22) : UIColor(white: 0.0, alpha: 0.2)))
|
||||||
)),
|
)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: availableSize.width, height: 100.0)
|
containerSize: CGSize(width: availableSize.width, height: 100.0)
|
||||||
@ -1364,21 +1363,30 @@ private final class GiftAuctionBidScreenComponent: Component {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isUpdate = false
|
||||||
let value = Int64(self.amount.realValue)
|
let value = Int64(self.amount.realValue)
|
||||||
if let myBidAmount = self.giftAuctionState?.myState.bidAmount {
|
if let myBidAmount = self.giftAuctionState?.myState.bidAmount {
|
||||||
|
isUpdate = true
|
||||||
if value == myBidAmount {
|
if value == myBidAmount {
|
||||||
controller.dismiss()
|
controller.dismiss()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let giftsPerRounds = gift.auctionGiftsPerRound ?? 50
|
||||||
|
|
||||||
|
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
||||||
if let myBidAmount = self.giftAuctionState?.myState.bidAmount, let myMinBidAmount = self.giftAuctionState?.myState.minBidAmount, value < myMinBidAmount {
|
if let myBidAmount = self.giftAuctionState?.myState.bidAmount, let myMinBidAmount = self.giftAuctionState?.myState.minBidAmount, value < myMinBidAmount {
|
||||||
HapticFeedback().error()
|
HapticFeedback().error()
|
||||||
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
|
||||||
controller.present(
|
controller.present(
|
||||||
UndoOverlayController(
|
UndoOverlayController(
|
||||||
presentationData: presentationData,
|
presentationData: presentationData,
|
||||||
content: .info(title: nil, text: "Add at least \(myMinBidAmount - myBidAmount) Stars to increase your bid.", timeout: nil, customUndoText: nil),
|
content: .info(
|
||||||
|
title: nil,
|
||||||
|
text: presentationData.strings.Gift_AuctionBid_AddMoreStars(presentationData.strings.Gift_AuctionBid_AddMoreStars_Stars(Int32(clamping: myMinBidAmount - myBidAmount))).string,
|
||||||
|
timeout: nil,
|
||||||
|
customUndoText: nil
|
||||||
|
),
|
||||||
position: .bottom,
|
position: .bottom,
|
||||||
action: { _ in return true }
|
action: { _ in return true }
|
||||||
),
|
),
|
||||||
@ -1432,12 +1440,19 @@ private final class GiftAuctionBidScreenComponent: Component {
|
|||||||
|
|
||||||
self.amount = self.amount.withMinAllowedRealValue(Int(value))
|
self.amount = self.amount.withMinAllowedRealValue(Int(value))
|
||||||
|
|
||||||
//TODO:localize
|
let title = isUpdate ? presentationData.strings.Gift_AuctionBid_Increased_Title : presentationData.strings.Gift_AuctionBid_Placed_Title
|
||||||
|
let text = isUpdate ? presentationData.strings.Gift_AuctionBid_Increased_Text("\(giftsPerRounds)").string : presentationData.strings.Gift_AuctionBid_Placed_Text("\(giftsPerRounds)").string
|
||||||
|
|
||||||
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
||||||
controller?.present(
|
controller?.present(
|
||||||
UndoOverlayController(
|
UndoOverlayController(
|
||||||
presentationData: presentationData,
|
presentationData: presentationData,
|
||||||
content: .actionSucceeded(title: "Your bid has been placed", text: "If you fall below the top 50, your bid will roll over to the next drop.", cancel: nil, destructive: false),
|
content: .actionSucceeded(
|
||||||
|
title: title,
|
||||||
|
text: text,
|
||||||
|
cancel: nil,
|
||||||
|
destructive: false
|
||||||
|
),
|
||||||
position: .bottom,
|
position: .bottom,
|
||||||
action: { _ in return true }
|
action: { _ in return true }
|
||||||
),
|
),
|
||||||
@ -1571,6 +1586,7 @@ private final class GiftAuctionBidScreenComponent: Component {
|
|||||||
|
|
||||||
let context = component.context
|
let context = component.context
|
||||||
let gift = component.auctionContext.gift
|
let gift = component.auctionContext.gift
|
||||||
|
let auctionContext = component.auctionContext
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
|
||||||
var link = ""
|
var link = ""
|
||||||
@ -1583,7 +1599,7 @@ private final class GiftAuctionBidScreenComponent: Component {
|
|||||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Gift_Auction_Context_About, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Info"), color: theme.contextMenu.primaryColor) }, action: { [weak controller] c, f in
|
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Gift_Auction_Context_About, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Info"), color: theme.contextMenu.primaryColor) }, action: { [weak controller] c, f in
|
||||||
f(.default)
|
f(.default)
|
||||||
|
|
||||||
let infoController = context.sharedContext.makeGiftAuctionInfoScreen(context: context, gift: gift, completion: nil)
|
let infoController = context.sharedContext.makeGiftAuctionInfoScreen(context: context, auctionContext: auctionContext, completion: nil)
|
||||||
controller?.push(infoController)
|
controller?.push(infoController)
|
||||||
})))
|
})))
|
||||||
|
|
||||||
@ -1973,7 +1989,7 @@ private final class GiftAuctionBidScreenComponent: Component {
|
|||||||
var dropsLeftAnimatedItems: [AnimatedTextComponent.Item] = []
|
var dropsLeftAnimatedItems: [AnimatedTextComponent.Item] = []
|
||||||
|
|
||||||
if let auctionState = self.giftAuctionState?.auctionState {
|
if let auctionState = self.giftAuctionState?.auctionState {
|
||||||
if case let .ongoing(_, _, _, minBidAmount, _, _, nextDropDate, _, dropsLeft, _) = auctionState {
|
if case let .ongoing(_, _, _, minBidAmount, _, _, nextDropDate, dropsLeft, _, _) = auctionState {
|
||||||
var minBidAmount = minBidAmount
|
var minBidAmount = minBidAmount
|
||||||
if let myMinBidAmmount = self.giftAuctionState?.myState.minBidAmount {
|
if let myMinBidAmmount = self.giftAuctionState?.myState.minBidAmount {
|
||||||
minBidAmount = myMinBidAmmount
|
minBidAmount = myMinBidAmmount
|
||||||
@ -2040,7 +2056,7 @@ private final class GiftAuctionBidScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||||
let dropTimeout = nextDropDate - currentTime
|
let dropTimeout = max(0, nextDropDate - currentTime)
|
||||||
|
|
||||||
let minutes = Int(dropTimeout / 60)
|
let minutes = Int(dropTimeout / 60)
|
||||||
let seconds = Int(dropTimeout % 60)
|
let seconds = Int(dropTimeout % 60)
|
||||||
|
|||||||
@ -26,17 +26,20 @@ private final class GiftAuctionInfoSheetContent: CombinedComponent {
|
|||||||
|
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
let gift: StarGift
|
let gift: StarGift
|
||||||
|
let auctionContext: GiftAuctionContext
|
||||||
let animateOut: ActionSlot<Action<()>>
|
let animateOut: ActionSlot<Action<()>>
|
||||||
let getController: () -> ViewController?
|
let getController: () -> ViewController?
|
||||||
|
|
||||||
init(
|
init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
gift: StarGift,
|
gift: StarGift,
|
||||||
|
auctionContext: GiftAuctionContext,
|
||||||
animateOut: ActionSlot<Action<()>>,
|
animateOut: ActionSlot<Action<()>>,
|
||||||
getController: @escaping () -> ViewController?
|
getController: @escaping () -> ViewController?
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.gift = gift
|
self.gift = gift
|
||||||
|
self.auctionContext = auctionContext
|
||||||
self.animateOut = animateOut
|
self.animateOut = animateOut
|
||||||
self.getController = getController
|
self.getController = getController
|
||||||
}
|
}
|
||||||
@ -53,19 +56,42 @@ private final class GiftAuctionInfoSheetContent: CombinedComponent {
|
|||||||
|
|
||||||
final class State: ComponentState {
|
final class State: ComponentState {
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
|
private let auctionContext: GiftAuctionContext
|
||||||
private let animateOut: ActionSlot<Action<()>>
|
private let animateOut: ActionSlot<Action<()>>
|
||||||
private let getController: () -> ViewController?
|
private let getController: () -> ViewController?
|
||||||
|
|
||||||
|
private(set) var rounds: Int32 = 50
|
||||||
|
|
||||||
|
fileprivate let playButtonAnimation = ActionSlot<Void>()
|
||||||
|
private var didPlayAnimation = false
|
||||||
|
|
||||||
init(
|
init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
|
auctionContext: GiftAuctionContext,
|
||||||
animateOut: ActionSlot<Action<()>>,
|
animateOut: ActionSlot<Action<()>>,
|
||||||
getController: @escaping () -> ViewController?
|
getController: @escaping () -> ViewController?
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
|
self.auctionContext = auctionContext
|
||||||
self.animateOut = animateOut
|
self.animateOut = animateOut
|
||||||
self.getController = getController
|
self.getController = getController
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
|
let _ = (self.auctionContext.state
|
||||||
|
|> deliverOnMainQueue).startStandalone(next: { [weak self] state in
|
||||||
|
if let self, case let .ongoing(_, _, _, _, _, _, _, _, _, totalRounds) = state?.auctionState {
|
||||||
|
self.rounds = totalRounds
|
||||||
|
self.updated()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func playAnimationIfNeeded() {
|
||||||
|
if !self.didPlayAnimation {
|
||||||
|
self.didPlayAnimation = true
|
||||||
|
self.playButtonAnimation.invoke(Void())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func dismiss(animated: Bool) {
|
func dismiss(animated: Bool) {
|
||||||
@ -83,7 +109,7 @@ private final class GiftAuctionInfoSheetContent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func makeState() -> State {
|
func makeState() -> State {
|
||||||
return State(context: self.context, animateOut: self.animateOut, getController: self.getController)
|
return State(context: self.context, auctionContext: self.auctionContext, animateOut: self.animateOut, getController: self.getController)
|
||||||
}
|
}
|
||||||
|
|
||||||
static var body: Body {
|
static var body: Body {
|
||||||
@ -101,7 +127,6 @@ private final class GiftAuctionInfoSheetContent: CombinedComponent {
|
|||||||
|
|
||||||
let theme = environment.theme
|
let theme = environment.theme
|
||||||
let strings = environment.strings
|
let strings = environment.strings
|
||||||
let _ = strings
|
|
||||||
|
|
||||||
let sideInset: CGFloat = 30.0 + environment.safeInsets.left
|
let sideInset: CGFloat = 30.0 + environment.safeInsets.left
|
||||||
let textSideInset: CGFloat = 30.0 + environment.safeInsets.left
|
let textSideInset: CGFloat = 30.0 + environment.safeInsets.left
|
||||||
@ -137,7 +162,7 @@ private final class GiftAuctionInfoSheetContent: CombinedComponent {
|
|||||||
|
|
||||||
let title = title.update(
|
let title = title.update(
|
||||||
component: BalancedTextComponent(
|
component: BalancedTextComponent(
|
||||||
text: .plain(NSAttributedString(string: "Auction", font: titleFont, textColor: textColor)),
|
text: .plain(NSAttributedString(string: strings.Gift_Auction_Info_Title, font: titleFont, textColor: textColor)),
|
||||||
horizontalAlignment: .center,
|
horizontalAlignment: .center,
|
||||||
maximumNumberOfLines: 0,
|
maximumNumberOfLines: 0,
|
||||||
lineSpacing: 0.1
|
lineSpacing: 0.1
|
||||||
@ -153,7 +178,7 @@ private final class GiftAuctionInfoSheetContent: CombinedComponent {
|
|||||||
|
|
||||||
let text = text.update(
|
let text = text.update(
|
||||||
component: BalancedTextComponent(
|
component: BalancedTextComponent(
|
||||||
text: .plain(NSAttributedString(string: "Join the battle for exclusive gifts.", font: textFont, textColor: secondaryTextColor)),
|
text: .plain(NSAttributedString(string: strings.Gift_Auction_Info_Description, font: textFont, textColor: secondaryTextColor)),
|
||||||
horizontalAlignment: .center,
|
horizontalAlignment: .center,
|
||||||
maximumNumberOfLines: 0,
|
maximumNumberOfLines: 0,
|
||||||
lineSpacing: 0.2
|
lineSpacing: 0.2
|
||||||
@ -167,15 +192,14 @@ private final class GiftAuctionInfoSheetContent: CombinedComponent {
|
|||||||
contentSize.height += text.size.height
|
contentSize.height += text.size.height
|
||||||
contentSize.height += spacing + 9.0
|
contentSize.height += spacing + 9.0
|
||||||
|
|
||||||
//TODO:localize
|
|
||||||
var items: [AnyComponentWithIdentity<Empty>] = []
|
var items: [AnyComponentWithIdentity<Empty>] = []
|
||||||
items.append(
|
items.append(
|
||||||
AnyComponentWithIdentity(
|
AnyComponentWithIdentity(
|
||||||
id: "top",
|
id: "top",
|
||||||
component: AnyComponent(ParagraphComponent(
|
component: AnyComponent(ParagraphComponent(
|
||||||
title: "Top \(auctionGiftsPerRound) Bidders",
|
title: strings.Gift_Auction_Info_TopBidders_Title(auctionGiftsPerRound),
|
||||||
titleColor: textColor,
|
titleColor: textColor,
|
||||||
text: "\(auctionGiftsPerRound) gifts are dropped in 10 rounds to the top \(auctionGiftsPerRound) bidders by bid amount.",
|
text: strings.Gift_Auction_Info_TopBidders_Text(strings.Gift_Auction_Info_TopBidders_Gifts(auctionGiftsPerRound), strings.Gift_Auction_Info_TopBidders_Rounds(state.rounds), strings.Gift_Auction_Info_TopBidders_Bidders(auctionGiftsPerRound)).string,
|
||||||
textColor: secondaryTextColor,
|
textColor: secondaryTextColor,
|
||||||
accentColor: linkColor,
|
accentColor: linkColor,
|
||||||
iconName: "Premium/Auction/Drop",
|
iconName: "Premium/Auction/Drop",
|
||||||
@ -187,9 +211,9 @@ private final class GiftAuctionInfoSheetContent: CombinedComponent {
|
|||||||
AnyComponentWithIdentity(
|
AnyComponentWithIdentity(
|
||||||
id: "carryover",
|
id: "carryover",
|
||||||
component: AnyComponent(ParagraphComponent(
|
component: AnyComponent(ParagraphComponent(
|
||||||
title: "Bid Carryover",
|
title: strings.Gift_Auction_Info_Carryover_Title,
|
||||||
titleColor: textColor,
|
titleColor: textColor,
|
||||||
text: "If your bid leaves the top \(auctionGiftsPerRound), it will automatically join the next drop.",
|
text: strings.Gift_Auction_Info_Carryover_Text("\(auctionGiftsPerRound)").string,
|
||||||
textColor: secondaryTextColor,
|
textColor: secondaryTextColor,
|
||||||
accentColor: linkColor,
|
accentColor: linkColor,
|
||||||
iconName: "Premium/Auction/NextDrop",
|
iconName: "Premium/Auction/NextDrop",
|
||||||
@ -201,9 +225,9 @@ private final class GiftAuctionInfoSheetContent: CombinedComponent {
|
|||||||
AnyComponentWithIdentity(
|
AnyComponentWithIdentity(
|
||||||
id: "missed",
|
id: "missed",
|
||||||
component: AnyComponent(ParagraphComponent(
|
component: AnyComponent(ParagraphComponent(
|
||||||
title: "Missed Bidders",
|
title: strings.Gift_Auction_Info_Missed_Title,
|
||||||
titleColor: textColor,
|
titleColor: textColor,
|
||||||
text: "If your bid doesn't win after the final drop, your Stars will be fully refunded.",
|
text: strings.Gift_Auction_Info_Missed_Text,
|
||||||
textColor: secondaryTextColor,
|
textColor: secondaryTextColor,
|
||||||
accentColor: linkColor,
|
accentColor: linkColor,
|
||||||
iconName: "Premium/Auction/Refund",
|
iconName: "Premium/Auction/Refund",
|
||||||
@ -251,16 +275,15 @@ private final class GiftAuctionInfoSheetContent: CombinedComponent {
|
|||||||
|
|
||||||
|
|
||||||
var buttonTitle: [AnyComponentWithIdentity<Empty>] = []
|
var buttonTitle: [AnyComponentWithIdentity<Empty>] = []
|
||||||
let playButtonAnimation = ActionSlot<Void>()
|
|
||||||
buttonTitle.append(AnyComponentWithIdentity(id: 0, component: AnyComponent(LottieComponent(
|
buttonTitle.append(AnyComponentWithIdentity(id: 0, component: AnyComponent(LottieComponent(
|
||||||
content: LottieComponent.AppBundleContent(name: "anim_ok"),
|
content: LottieComponent.AppBundleContent(name: "anim_ok"),
|
||||||
color: theme.list.itemCheckColors.foregroundColor,
|
color: theme.list.itemCheckColors.foregroundColor,
|
||||||
startingPosition: .begin,
|
startingPosition: .begin,
|
||||||
size: CGSize(width: 28.0, height: 28.0),
|
size: CGSize(width: 28.0, height: 28.0),
|
||||||
playOnce: playButtonAnimation
|
playOnce: state.playButtonAnimation
|
||||||
))))
|
))))
|
||||||
buttonTitle.append(AnyComponentWithIdentity(id: 1, component: AnyComponent(ButtonTextContentComponent(
|
buttonTitle.append(AnyComponentWithIdentity(id: 1, component: AnyComponent(ButtonTextContentComponent(
|
||||||
text: "Understood",
|
text: strings.Gift_Auction_Info_Understood,
|
||||||
badge: 0,
|
badge: 0,
|
||||||
textColor: theme.list.itemCheckColors.foregroundColor,
|
textColor: theme.list.itemCheckColors.foregroundColor,
|
||||||
badgeBackground: theme.list.itemCheckColors.foregroundColor,
|
badgeBackground: theme.list.itemCheckColors.foregroundColor,
|
||||||
@ -303,6 +326,8 @@ private final class GiftAuctionInfoSheetContent: CombinedComponent {
|
|||||||
|
|
||||||
contentSize.height += 30.0
|
contentSize.height += 30.0
|
||||||
|
|
||||||
|
state.playAnimationIfNeeded()
|
||||||
|
|
||||||
return contentSize
|
return contentSize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -313,13 +338,16 @@ final class GiftAuctionInfoSheetComponent: CombinedComponent {
|
|||||||
|
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
let gift: StarGift
|
let gift: StarGift
|
||||||
|
let auctionContext: GiftAuctionContext
|
||||||
|
|
||||||
init(
|
init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
gift: StarGift
|
gift: StarGift,
|
||||||
|
auctionContext: GiftAuctionContext
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.gift = gift
|
self.gift = gift
|
||||||
|
self.auctionContext = auctionContext
|
||||||
}
|
}
|
||||||
|
|
||||||
static func ==(lhs: GiftAuctionInfoSheetComponent, rhs: GiftAuctionInfoSheetComponent) -> Bool {
|
static func ==(lhs: GiftAuctionInfoSheetComponent, rhs: GiftAuctionInfoSheetComponent) -> Bool {
|
||||||
@ -347,6 +375,7 @@ final class GiftAuctionInfoSheetComponent: CombinedComponent {
|
|||||||
content: AnyComponent<EnvironmentType>(GiftAuctionInfoSheetContent(
|
content: AnyComponent<EnvironmentType>(GiftAuctionInfoSheetContent(
|
||||||
context: context.component.context,
|
context: context.component.context,
|
||||||
gift: context.component.gift,
|
gift: context.component.gift,
|
||||||
|
auctionContext: context.component.auctionContext,
|
||||||
animateOut: animateOut,
|
animateOut: animateOut,
|
||||||
getController: controller
|
getController: controller
|
||||||
)),
|
)),
|
||||||
@ -422,23 +451,22 @@ final class GiftAuctionInfoSheetComponent: CombinedComponent {
|
|||||||
|
|
||||||
public final class GiftAuctionInfoScreen: ViewControllerComponentContainer {
|
public final class GiftAuctionInfoScreen: ViewControllerComponentContainer {
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private let gift: StarGift
|
|
||||||
fileprivate let completion: (() -> Void)?
|
fileprivate let completion: (() -> Void)?
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
gift: StarGift,
|
auctionContext: GiftAuctionContext,
|
||||||
completion: (() -> Void)?
|
completion: (() -> Void)?
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.gift = gift
|
|
||||||
self.completion = completion
|
self.completion = completion
|
||||||
|
|
||||||
super.init(
|
super.init(
|
||||||
context: context,
|
context: context,
|
||||||
component: GiftAuctionInfoSheetComponent(
|
component: GiftAuctionInfoSheetComponent(
|
||||||
context: context,
|
context: context,
|
||||||
gift: gift
|
gift: auctionContext.gift,
|
||||||
|
auctionContext: auctionContext
|
||||||
),
|
),
|
||||||
navigationBarAppearance: .none,
|
navigationBarAppearance: .none,
|
||||||
statusBarStyle: .ignore,
|
statusBarStyle: .ignore,
|
||||||
|
|||||||
@ -291,6 +291,7 @@ private final class GiftAuctionViewSheetContent: CombinedComponent {
|
|||||||
|
|
||||||
let context = self.context
|
let context = self.context
|
||||||
let gift = self.auctionContext.gift
|
let gift = self.auctionContext.gift
|
||||||
|
let auctionContext = self.auctionContext
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
|
||||||
var link = ""
|
var link = ""
|
||||||
@ -300,12 +301,14 @@ private final class GiftAuctionViewSheetContent: CombinedComponent {
|
|||||||
|
|
||||||
var items: [ContextMenuItem] = []
|
var items: [ContextMenuItem] = []
|
||||||
|
|
||||||
|
if let auctionState = self.auctionState, case .ongoing = auctionState.auctionState {
|
||||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Gift_Auction_Context_About, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Info"), color: theme.contextMenu.primaryColor) }, action: { [weak controller] c, f in
|
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Gift_Auction_Context_About, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Info"), color: theme.contextMenu.primaryColor) }, action: { [weak controller] c, f in
|
||||||
f(.default)
|
f(.default)
|
||||||
|
|
||||||
let infoController = context.sharedContext.makeGiftAuctionInfoScreen(context: context, gift: gift, completion: nil)
|
let infoController = context.sharedContext.makeGiftAuctionInfoScreen(context: context, auctionContext: auctionContext, completion: nil)
|
||||||
controller?.push(infoController)
|
controller?.push(infoController)
|
||||||
})))
|
})))
|
||||||
|
}
|
||||||
|
|
||||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Gift_Auction_Context_CopyLink, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Link"), color: theme.contextMenu.primaryColor) }, action: { [weak controller] c, f in
|
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Gift_Auction_Context_CopyLink, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Link"), color: theme.contextMenu.primaryColor) }, action: { [weak controller] c, f in
|
||||||
f(.default)
|
f(.default)
|
||||||
@ -599,7 +602,7 @@ private final class GiftAuctionViewSheetContent: CombinedComponent {
|
|||||||
if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String {
|
if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String {
|
||||||
let controller = component.context.sharedContext.makeGiftAuctionInfoScreen(
|
let controller = component.context.sharedContext.makeGiftAuctionInfoScreen(
|
||||||
context: component.context,
|
context: component.context,
|
||||||
gift: component.auctionContext.gift,
|
auctionContext: component.auctionContext,
|
||||||
completion: nil
|
completion: nil
|
||||||
)
|
)
|
||||||
environment.controller()?.push(controller)
|
environment.controller()?.push(controller)
|
||||||
@ -636,10 +639,15 @@ private final class GiftAuctionViewSheetContent: CombinedComponent {
|
|||||||
if state.giftAuctionAcquiredGifts.count > 0, case let .generic(gift) = component.auctionContext.gift {
|
if state.giftAuctionAcquiredGifts.count > 0, case let .generic(gift) = component.auctionContext.gift {
|
||||||
originY += 5.0
|
originY += 5.0
|
||||||
|
|
||||||
let text = strings.Gift_Auction_ItemsBought(Int32(state.giftAuctionAcquiredGifts.count))
|
|
||||||
let acquiredButton = acquiredButton.update(
|
let acquiredButton = acquiredButton.update(
|
||||||
component: PlainButtonComponent(content: AnyComponent(
|
component: PlainButtonComponent(content: AnyComponent(
|
||||||
HStack([
|
HStack([
|
||||||
|
AnyComponentWithIdentity(id: "count", component: AnyComponent(
|
||||||
|
MultilineTextComponent(text: .plain(NSAttributedString(string: presentationStringsFormattedNumber(Int32(state.giftAuctionAcquiredGifts.count), dateTimeFormat.groupingSeparator), font: Font.regular(17.0), textColor: theme.actionSheet.controlAccentColor)))
|
||||||
|
)),
|
||||||
|
AnyComponentWithIdentity(id: "spacing", component: AnyComponent(
|
||||||
|
Rectangle(color: .clear, width: 8.0, height: 1.0)
|
||||||
|
)),
|
||||||
AnyComponentWithIdentity(id: "icon", component: AnyComponent(
|
AnyComponentWithIdentity(id: "icon", component: AnyComponent(
|
||||||
GiftItemComponent(
|
GiftItemComponent(
|
||||||
context: component.context,
|
context: component.context,
|
||||||
@ -647,16 +655,16 @@ private final class GiftAuctionViewSheetContent: CombinedComponent {
|
|||||||
strings: strings,
|
strings: strings,
|
||||||
peer: nil,
|
peer: nil,
|
||||||
subject: .starGift(gift: gift, price: ""),
|
subject: .starGift(gift: gift, price: ""),
|
||||||
mode: .tableIcon
|
mode: .buttonIcon
|
||||||
)
|
)
|
||||||
)),
|
)),
|
||||||
AnyComponentWithIdentity(id: "text", component: AnyComponent(
|
AnyComponentWithIdentity(id: "text", component: AnyComponent(
|
||||||
MultilineTextComponent(text: .plain(NSAttributedString(string: text, font: Font.regular(17.0), textColor: theme.actionSheet.controlAccentColor)))
|
MultilineTextComponent(text: .plain(NSAttributedString(string: " \(strings.Gift_Auction_ItemsBought(Int32(state.giftAuctionAcquiredGifts.count)))", font: Font.regular(17.0), textColor: theme.actionSheet.controlAccentColor)))
|
||||||
)),
|
)),
|
||||||
AnyComponentWithIdentity(id: "chevron", component: AnyComponent(
|
AnyComponentWithIdentity(id: "arrow", component: AnyComponent(
|
||||||
BundleIconComponent(name: "Settings/TextArrowRight", tintColor: environment.theme.actionSheet.controlAccentColor)
|
BundleIconComponent(name: "Chat/Context Menu/Arrow", tintColor: theme.actionSheet.controlAccentColor)
|
||||||
))
|
))
|
||||||
], spacing: 6.0)
|
], spacing: 0.0)
|
||||||
), action: { [weak state] in
|
), action: { [weak state] in
|
||||||
guard let state else {
|
guard let state else {
|
||||||
return
|
return
|
||||||
|
|||||||
@ -3842,8 +3842,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
return controller
|
return controller
|
||||||
}
|
}
|
||||||
|
|
||||||
public func makeGiftAuctionInfoScreen(context: AccountContext, gift: StarGift, completion: (() -> Void)?) -> ViewController {
|
public func makeGiftAuctionInfoScreen(context: AccountContext, auctionContext: GiftAuctionContext, completion: (() -> Void)?) -> ViewController {
|
||||||
return GiftAuctionInfoScreen(context: context, gift: gift, completion: completion)
|
return GiftAuctionInfoScreen(context: context, auctionContext: auctionContext, completion: completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func makeGiftAuctionBidScreen(context: AccountContext, auctionContext: GiftAuctionContext) -> ViewController {
|
public func makeGiftAuctionBidScreen(context: AccountContext, auctionContext: GiftAuctionContext) -> ViewController {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user