mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-06-20 18:24:43 +00:00
Merge commit '1be0aaef7cc19f910f3928668e3acc80f2d4b59e'
This commit is contained in:
@@ -15180,7 +15180,7 @@ Error: %8$@";
|
||||
"Notification.GiftAuction.Acquired" = "You've successfully bought a gift in the auction for %@.";
|
||||
|
||||
"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.FirstSale" = "First Sale";
|
||||
"Gift.Auction.LastSale" = "Last Sale";
|
||||
@@ -15213,6 +15213,15 @@ Error: %8$@";
|
||||
"Gift.AuctionBid.TopWinners" = "Top 3 Winners";
|
||||
"Gift.AuctionBid.PlaceBid" = "Place a %@ 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.AuctionBid.Custom" = "Custom";
|
||||
|
||||
"Gift.Auction.Context.About" = "About";
|
||||
"Gift.Auction.Context.CopyLink" = "Copy Link";
|
||||
@@ -15264,3 +15273,29 @@ Error: %8$@";
|
||||
"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.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";
|
||||
|
||||
"Location.SendLocation" = "Send Location";
|
||||
|
||||
"Camera.LiveStream.Change" = "change";
|
||||
"Camera.LiveStream.StartLiveStream" = "Start Live Stream";
|
||||
|
||||
@@ -1422,7 +1422,7 @@ public protocol SharedAccountContext: AnyObject {
|
||||
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 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 makeGiftAuctionViewScreen(context: AccountContext, auctionContext: GiftAuctionContext) -> ViewController
|
||||
func makeGiftAuctionActiveBidsScreen(context: AccountContext) -> ViewController
|
||||
|
||||
+1
-2
@@ -341,8 +341,7 @@ public final class AuthorizationSequenceCountrySelectionController: ViewControll
|
||||
self.statusBar.statusBarStyle = theme.rootController.statusBarStyle.style
|
||||
|
||||
if glass {
|
||||
//TODO:localize
|
||||
self.title = "Select Country"
|
||||
self.title = strings.Login_SelectCountry
|
||||
} else {
|
||||
let navigationContentNode = AuthorizationSequenceCountrySelectionNavigationContentNode(theme: theme, strings: strings, cancel: { [weak self] in
|
||||
self?.dismissed?()
|
||||
|
||||
@@ -446,9 +446,7 @@ public func storyLocationPickerController(
|
||||
) -> ViewController {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: defaultDarkColorPresentationTheme)
|
||||
let updatedPresentationData: (PresentationData, Signal<PresentationData, NoError>) = (presentationData, .single(presentationData))
|
||||
let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: nil, buttons: [.standalone], initialButton: .standalone, fromMenu: false, hasTextInput: false, makeEntityInputView: {
|
||||
return nil
|
||||
})
|
||||
let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: nil, buttons: [.standalone], initialButton: .standalone, fromMenu: false, hasTextInput: false)
|
||||
controller.requestController = { _, present in
|
||||
let locationPickerController = LocationPickerController(context: context, updatedPresentationData: updatedPresentationData, mode: .share(peer: nil, selfPeer: nil, hasLiveLocation: false), source: .story, initialLocation: location, completion: { location, queryId, resultId, address, countryCode in
|
||||
completion(location, queryId, resultId, address, countryCode)
|
||||
|
||||
@@ -1533,11 +1533,10 @@ final class LocationPickerControllerNode: ViewControllerTracingNode, CLLocationM
|
||||
foreground: self.presentationData.theme.list.itemCheckColors.foregroundColor,
|
||||
pressedColor: self.presentationData.theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.9),
|
||||
)
|
||||
//TODO:localize
|
||||
var buttonContents: [AnyComponentWithIdentity<Empty>] = [
|
||||
AnyComponentWithIdentity(
|
||||
id: AnyHashable("label"),
|
||||
component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: "Send Location", font: Font.semibold(17.0), textColor: self.presentationData.theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center))))
|
||||
component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: self.presentationData.strings.Location_SendLocation, font: Font.semibold(17.0), textColor: self.presentationData.theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center))))
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
@@ -553,7 +553,7 @@ open class TelegramBaseController: ViewController, KeyShortcutResponder {
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if !"".isEmpty, self.giftAuctionStates.count == 1, let gift = self.giftAuctionStates.first?.gift, case let .generic(gift) = gift {
|
||||
if self.giftAuctionStates.count == 1, let gift = self.giftAuctionStates.first?.gift, case let .generic(gift) = gift {
|
||||
if let giftAuctionsManager = self.context.giftAuctionsManager {
|
||||
let _ = (giftAuctionsManager.auctionContext(for: .giftId(gift.id))
|
||||
|> deliverOnMainQueue).start(next: { [weak self] auction in
|
||||
|
||||
@@ -91,7 +91,7 @@ public final class GiftAuctionContext {
|
||||
}
|
||||
|
||||
public var currentBidPeerId: EnginePeer.Id? {
|
||||
if self.myState?.bidAmount != nil {
|
||||
if self.myState?.bidAmount != nil, case .ongoing = self.auctionState {
|
||||
return self.myState?.bidPeerId
|
||||
} else {
|
||||
return nil
|
||||
@@ -145,10 +145,19 @@ public final class GiftAuctionContext {
|
||||
self.myState = myState
|
||||
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.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 {
|
||||
return
|
||||
}
|
||||
@@ -341,7 +350,7 @@ public class GiftAuctionsManager {
|
||||
for (giftId, update) in updates {
|
||||
if let auctionContext = self.auctionContexts[giftId] {
|
||||
auctionContext.updateAuctionState(update)
|
||||
} else {
|
||||
} else if case .ongoing = update {
|
||||
reload = true
|
||||
break
|
||||
}
|
||||
@@ -385,11 +394,11 @@ public class GiftAuctionsManager {
|
||||
guard let self, let activeAuctions else {
|
||||
return
|
||||
}
|
||||
var auctionContexts: [Int64 : GiftAuctionContext] = [:]
|
||||
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()
|
||||
}))
|
||||
}
|
||||
@@ -417,7 +426,7 @@ public class GiftAuctionsManager {
|
||||
}
|
||||
}
|
||||
|
||||
func storeAuctionContext(auctionContext: GiftAuctionContext) {
|
||||
public func storeAuctionContext(auctionContext: GiftAuctionContext) {
|
||||
self.auctionContexts[auctionContext.gift.giftId] = auctionContext
|
||||
self.updateState()
|
||||
}
|
||||
@@ -427,7 +436,7 @@ public class GiftAuctionsManager {
|
||||
for auction in self.auctionContexts.values.sorted(by: { $0.gift.giftId < $1.gift.giftId }) {
|
||||
signals.append(auction.state
|
||||
|> mapToSignal { state in
|
||||
if let state, state.myState.bidAmount != nil {
|
||||
if let state, state.myState.bidAmount != nil, case .ongoing = state.auctionState {
|
||||
return .single(state)
|
||||
} else {
|
||||
return .complete()
|
||||
@@ -439,17 +448,60 @@ public class GiftAuctionsManager {
|
||||
}
|
||||
|
||||
public extension GiftAuctionContext.State {
|
||||
var place: Int32? {
|
||||
guard case let .ongoing(_, _, _, _, bidLevels, _, _, _, _, _) = self.auctionState, let myBid = self.myState.bidAmount, let myBidDate = self.myState.bidDate else {
|
||||
func getPlace(myBid: Int64?, myBidDate: Int32?) -> Int32? {
|
||||
guard case let .ongoing(_, _, _, _, bidLevels, _, _, _, _, _) = self.auctionState else {
|
||||
return nil
|
||||
}
|
||||
var place: Int32 = 1
|
||||
for level in bidLevels {
|
||||
if myBid < level.amount || (myBid == level.amount && myBidDate > level.date) {
|
||||
place = level.position + 1
|
||||
guard let myBid = myBid ?? self.myState.bidAmount else {
|
||||
return nil
|
||||
}
|
||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||
let myBidDate = self.myState.bidDate ?? currentTime
|
||||
|
||||
let levels = bidLevels
|
||||
guard !levels.isEmpty else {
|
||||
return 1
|
||||
}
|
||||
|
||||
func isWorse(than level: GiftAuctionContext.State.BidLevel) -> Bool {
|
||||
if myBid < level.amount {
|
||||
return true
|
||||
}
|
||||
if myBid == level.amount, myBidDate > level.date {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var lowerIndex: Int = -1
|
||||
for (i, level) in levels.enumerated() {
|
||||
if isWorse(than: level) {
|
||||
lowerIndex = i
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return place
|
||||
if lowerIndex == -1 {
|
||||
return 1
|
||||
}
|
||||
|
||||
let lowerPosition = levels[lowerIndex].position
|
||||
let nextPosition: Int32
|
||||
let nextIndex = lowerIndex + 1
|
||||
if nextIndex < levels.count {
|
||||
nextPosition = levels[nextIndex].position
|
||||
} else {
|
||||
nextPosition = lowerPosition
|
||||
}
|
||||
if nextPosition == lowerPosition + 1 {
|
||||
return lowerPosition + 1
|
||||
} else {
|
||||
return nextPosition
|
||||
}
|
||||
}
|
||||
|
||||
var place: Int32? {
|
||||
return self.getPlace(myBid: nil, myBidDate: nil)
|
||||
}
|
||||
|
||||
var startDate: Int32 {
|
||||
|
||||
+3
-3
@@ -413,12 +413,13 @@ public final class StreamAsComponent: Component {
|
||||
})
|
||||
}
|
||||
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 })
|
||||
let avatarSize = CGSize(width: 32.0, height: 32.0)
|
||||
self.avatarNode.frame = CGRect(origin: .zero, size: avatarSize)
|
||||
if let peer = self.peer {
|
||||
self.avatarNode.setPeer(
|
||||
context: component.context,
|
||||
theme: component.context.sharedContext.currentPresentationData.with({ $0 }).theme,
|
||||
theme: presentationData.theme,
|
||||
peer: peer,
|
||||
synchronousLoad: true
|
||||
)
|
||||
@@ -444,12 +445,11 @@ public final class StreamAsComponent: Component {
|
||||
|
||||
var maxWidth = titleFrame.maxX
|
||||
if !component.isCustomTarget {
|
||||
//TODO:localize
|
||||
let subtitleSize = self.subtitle.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(
|
||||
MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(string: "change", font: Font.regular(11.0), textColor: UIColor(white: 1.0, alpha: 0.8), paragraphAlignment: .left))
|
||||
text: .plain(NSAttributedString(string: presentationData.strings.Camera_LiveStream_Change, font: Font.regular(11.0), textColor: UIColor(white: 1.0, alpha: 0.8), paragraphAlignment: .left))
|
||||
)
|
||||
),
|
||||
environment: {},
|
||||
|
||||
+1
-2
@@ -252,11 +252,10 @@ private final class ShutterButtonContentComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
//TODO:localize
|
||||
let labelSize = self.label.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(
|
||||
Text(text: "Start Live Stream", font: Font.semibold(17.0), color: .white)
|
||||
Text(text: component.strings.Camera_LiveStream_StartLiveStream, font: Font.semibold(17.0), color: .white)
|
||||
),
|
||||
environment: {},
|
||||
containerSize: availableSize
|
||||
|
||||
+20
-2
@@ -314,7 +314,7 @@ final class GiftOptionsScreenComponent: Component {
|
||||
}
|
||||
|
||||
let _ = (component.context.engine.payments.checkCanSendStarGift(giftId: gift.id)
|
||||
|> deliverOnMainQueue).start(next: { [weak self, weak controller] result in
|
||||
|> deliverOnMainQueue).start(next: { [weak self, weak controller] result in
|
||||
guard let self, let controller else {
|
||||
return
|
||||
}
|
||||
@@ -369,11 +369,22 @@ final class GiftOptionsScreenComponent: Component {
|
||||
guard let giftAuctionsManager = component.context.giftAuctionsManager else {
|
||||
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))
|
||||
|> 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
|
||||
}
|
||||
self.loadingGiftId = nil
|
||||
self.state?.updated()
|
||||
|
||||
if let currentBidPeerId = auctionContext.currentBidPeerId {
|
||||
if currentBidPeerId == component.peerId {
|
||||
let giftController = component.context.sharedContext.makeGiftAuctionBidScreen(
|
||||
@@ -1317,6 +1328,13 @@ final class GiftOptionsScreenComponent: Component {
|
||||
let hasAnyGifts = hasGenericGifts || hasTransferGifts
|
||||
|
||||
if isSelfGift || isChannelGift || isPremiumDisabled {
|
||||
if !self.premiumItems.isEmpty {
|
||||
for (_, itemView) in self.premiumItems {
|
||||
itemView.view?.removeFromSuperview()
|
||||
}
|
||||
self.premiumItems.removeAll()
|
||||
}
|
||||
|
||||
contentHeight += 6.0
|
||||
} else {
|
||||
if let premiumProducts = state.premiumProducts {
|
||||
|
||||
@@ -98,6 +98,7 @@ final class BadgeLabelView: UIView {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func update(value: String, transition: ComponentTransition) -> CGSize {
|
||||
if value.contains(" ") {
|
||||
for (_, view) in self.itemViews {
|
||||
|
||||
+99
-28
@@ -29,6 +29,7 @@ import BotPaymentsUI
|
||||
import UndoUI
|
||||
import GiftItemComponent
|
||||
import LottieComponent
|
||||
import EdgeEffect
|
||||
|
||||
private final class BadgeComponent: Component {
|
||||
let theme: PresentationTheme
|
||||
@@ -810,11 +811,10 @@ private final class SliderBackgroundComponent: Component {
|
||||
topLineFrameTransition.setFrame(layer: self.topBackgroundLine, frame: topLineFrame)
|
||||
topLineAlphaTransition.setAlpha(layer: self.topBackgroundLine, alpha: topLineAlpha)
|
||||
|
||||
//TODO:localize
|
||||
let topTextSize = self.topForegroundText.update(
|
||||
transition: .immediate,
|
||||
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: {},
|
||||
containerSize: CGSize(width: availableSize.width, height: 100.0)
|
||||
@@ -822,7 +822,7 @@ private final class SliderBackgroundComponent: Component {
|
||||
let _ = self.topBackgroundText.update(
|
||||
transition: .immediate,
|
||||
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: {},
|
||||
containerSize: CGSize(width: availableSize.width, height: 100.0)
|
||||
@@ -952,7 +952,7 @@ private final class GiftAuctionBidScreenComponent: Component {
|
||||
|
||||
private static func makeSliderSteps(minRealValue: Int, maxRealValue: Int, isLogarithmic: Bool) -> [Int] {
|
||||
if isLogarithmic {
|
||||
var sliderSteps: [Int] = [1, 10, 50, 100, 500, 1_000, 2_000, 5_000, 7_500, 10_000, 20_000, 30_000]
|
||||
var sliderSteps: [Int] = [1, 10, 50, 100, 500, 1_000, 2_000, 5_000, 7_500, 15_000, 20_000, 30_000, 40_000, 50_000]
|
||||
sliderSteps.removeAll(where: { $0 <= minRealValue })
|
||||
sliderSteps.insert(minRealValue, at: 0)
|
||||
sliderSteps.removeAll(where: { $0 >= maxRealValue })
|
||||
@@ -1028,6 +1028,10 @@ private final class GiftAuctionBidScreenComponent: Component {
|
||||
func withMinAllowedRealValue(_ minAllowedRealValue: Int) -> Amount {
|
||||
return Amount(realValue: self.realValue, minRealValue: self.minRealValue, minAllowedRealValue: minAllowedRealValue, maxRealValue: self.maxRealValue, maxSliderValue: self.maxSliderValue, isLogarithmic: self.isLogarithmic)
|
||||
}
|
||||
|
||||
func withMaxRealValue(_ maxRealValue: Int) -> Amount {
|
||||
return Amount(realValue: self.realValue, minRealValue: self.minRealValue, minAllowedRealValue: self.minAllowedRealValue, maxRealValue: maxRealValue, maxSliderValue: self.maxSliderValue, isLogarithmic: self.isLogarithmic)
|
||||
}
|
||||
}
|
||||
|
||||
final class View: UIView, UIScrollViewDelegate {
|
||||
@@ -1040,6 +1044,9 @@ private final class GiftAuctionBidScreenComponent: Component {
|
||||
private let scrollContentView: UIView
|
||||
private let hierarchyTrackingNode: HierarchyTrackingNode
|
||||
|
||||
private let topEdgeEffectView: EdgeEffectView
|
||||
private let bottomEdgeEffectView: EdgeEffectView
|
||||
|
||||
private var balanceOverlay = ComponentView<Empty>()
|
||||
|
||||
private let backgroundHandleView: UIImageView
|
||||
@@ -1116,6 +1123,13 @@ private final class GiftAuctionBidScreenComponent: Component {
|
||||
|
||||
self.hierarchyTrackingNode = HierarchyTrackingNode()
|
||||
|
||||
self.topEdgeEffectView = EdgeEffectView()
|
||||
self.topEdgeEffectView.clipsToBounds = true
|
||||
self.topEdgeEffectView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
|
||||
self.topEdgeEffectView.layer.cornerRadius = 40.0
|
||||
|
||||
self.bottomEdgeEffectView = EdgeEffectView()
|
||||
|
||||
super.init(frame: frame)
|
||||
|
||||
self.addSubview(self.dimView)
|
||||
@@ -1359,26 +1373,34 @@ private final class GiftAuctionBidScreenComponent: Component {
|
||||
}
|
||||
|
||||
private var isLoading = false
|
||||
private func placeBid() {
|
||||
private func commitBid(value: Int64) {
|
||||
guard let component = self.component, case let .generic(gift) = component.gift, let controller = self.environment?.controller() else {
|
||||
return
|
||||
}
|
||||
|
||||
let value = Int64(self.amount.realValue)
|
||||
var isUpdate = false
|
||||
if let myBidAmount = self.giftAuctionState?.myState.bidAmount {
|
||||
isUpdate = true
|
||||
if value == myBidAmount {
|
||||
controller.dismiss()
|
||||
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 {
|
||||
HapticFeedback().error()
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
||||
controller.present(
|
||||
UndoOverlayController(
|
||||
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,
|
||||
action: { _ in return true }
|
||||
),
|
||||
@@ -1428,16 +1450,32 @@ private final class GiftAuctionBidScreenComponent: Component {
|
||||
return
|
||||
}
|
||||
self.isLoading = false
|
||||
|
||||
let newMaxValue = Int(Double(value) * 1.5)
|
||||
var updatedAmount = self.amount.withMinAllowedRealValue(Int(value))
|
||||
if newMaxValue > self.amount.maxRealValue {
|
||||
updatedAmount = updatedAmount.withMaxRealValue(newMaxValue)
|
||||
}
|
||||
self.amount = updatedAmount
|
||||
self.state?.updated()
|
||||
|
||||
self.amount = self.amount.withMinAllowedRealValue(Int(value))
|
||||
if !isUpdate {
|
||||
component.auctionContext.load()
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
//TODO:localize
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
||||
controller?.present(
|
||||
UndoOverlayController(
|
||||
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,
|
||||
action: { _ in return true }
|
||||
),
|
||||
@@ -1571,6 +1609,7 @@ private final class GiftAuctionBidScreenComponent: Component {
|
||||
|
||||
let context = component.context
|
||||
let gift = component.auctionContext.gift
|
||||
let auctionContext = component.auctionContext
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
var link = ""
|
||||
@@ -1583,7 +1622,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
|
||||
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)
|
||||
})))
|
||||
|
||||
@@ -1710,8 +1749,12 @@ private final class GiftAuctionBidScreenComponent: Component {
|
||||
peerIds.append(context.account.peerId)
|
||||
|
||||
var minBidAmount: Int64 = 100
|
||||
if case let .ongoing(_, _, _, auctionMinBidAmount, _, _, _, _, _, _) = state?.auctionState {
|
||||
var maxBidAmount: Int64 = 50000
|
||||
if case let .ongoing(_, _, _, auctionMinBidAmount, bidLevels, _, _, _, _, _) = state?.auctionState {
|
||||
minBidAmount = auctionMinBidAmount
|
||||
if let firstLevel = bidLevels.first(where: { $0.position == 1 }) {
|
||||
maxBidAmount = max(maxBidAmount, Int64(Double(firstLevel.amount) * 1.5))
|
||||
}
|
||||
}
|
||||
var currentValue = max(Int(minBidAmount), 100)
|
||||
if let myBidAmount = state?.myState.bidAmount {
|
||||
@@ -1723,7 +1766,7 @@ private final class GiftAuctionBidScreenComponent: Component {
|
||||
minAllowedRealValue = myBidAmount
|
||||
}
|
||||
|
||||
self.amount = Amount(realValue: currentValue, minRealValue: Int(minBidAmount), minAllowedRealValue: Int(minAllowedRealValue), maxRealValue: 30000, maxSliderValue: 999, isLogarithmic: true)
|
||||
self.amount = Amount(realValue: currentValue, minRealValue: Int(minBidAmount), minAllowedRealValue: Int(minAllowedRealValue), maxRealValue: Int(maxBidAmount), maxSliderValue: 999, isLogarithmic: true)
|
||||
transition = .immediate
|
||||
}
|
||||
|
||||
@@ -1765,6 +1808,8 @@ private final class GiftAuctionBidScreenComponent: Component {
|
||||
self.backgroundLayer.backgroundColor = environment.theme.actionSheet.opaqueItemBackgroundColor.cgColor
|
||||
}
|
||||
|
||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||
|
||||
transition.setFrame(view: self.dimView, frame: CGRect(origin: CGPoint(), size: availableSize))
|
||||
|
||||
var contentHeight: CGFloat = 0.0
|
||||
@@ -1973,7 +2018,7 @@ private final class GiftAuctionBidScreenComponent: Component {
|
||||
var dropsLeftAnimatedItems: [AnimatedTextComponent.Item] = []
|
||||
|
||||
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
|
||||
if let myMinBidAmmount = self.giftAuctionState?.myState.minBidAmount {
|
||||
minBidAmount = myMinBidAmmount
|
||||
@@ -2039,8 +2084,7 @@ private final class GiftAuctionBidScreenComponent: Component {
|
||||
minBidAnimatedItems.append(AnimatedTextComponent.Item(id: "static", content: .text(minBidString)))
|
||||
}
|
||||
|
||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||
let dropTimeout = nextDropDate - currentTime
|
||||
let dropTimeout = max(0, nextDropDate - currentTime)
|
||||
|
||||
let minutes = Int(dropTimeout / 60)
|
||||
let seconds = Int(dropTimeout % 60)
|
||||
@@ -2219,19 +2263,16 @@ private final class GiftAuctionBidScreenComponent: Component {
|
||||
var topBidsComponents: [(EnginePeer.Id, AnyComponent<Empty>)] = []
|
||||
|
||||
if let giftAuctionState = self.giftAuctionState, case let .ongoing(_, _, _, _, bidLevels, topBidders, _, _, _, _) = giftAuctionState.auctionState {
|
||||
if var myBidAmount = giftAuctionState.myState.bidAmount, let myBidDate = giftAuctionState.myState.bidDate, let peer = self.peersMap[component.context.account.peerId] {
|
||||
if var myBidAmount = giftAuctionState.myState.bidAmount, var myBidDate = giftAuctionState.myState.bidDate, let peer = self.peersMap[component.context.account.peerId] {
|
||||
var place: Int32 = 1
|
||||
var isBiddingUp = false
|
||||
if self.amount.realValue > myBidAmount {
|
||||
myBidAmount = Int64(self.amount.realValue)
|
||||
myBidDate = currentTime
|
||||
isBiddingUp = true
|
||||
}
|
||||
for level in bidLevels {
|
||||
if myBidAmount < level.amount || (myBidAmount == level.amount && myBidDate > level.date) {
|
||||
place = level.position + 1
|
||||
}
|
||||
}
|
||||
|
||||
place = giftAuctionState.getPlace(myBid: myBidAmount, myBidDate: myBidDate) ?? 1
|
||||
|
||||
var bidTitle: String
|
||||
var bidTitleColor: UIColor
|
||||
var bidStatus: PeerComponent.Status?
|
||||
@@ -2496,17 +2537,31 @@ private final class GiftAuctionBidScreenComponent: Component {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
self.placeBid()
|
||||
self.commitBid(value: Int64(self.amount.realValue))
|
||||
}
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: availableSize.width - buttonInsets.left - buttonInsets.right, height: 54.0)
|
||||
)
|
||||
|
||||
|
||||
let edgeEffectHeight: CGFloat = 80.0
|
||||
let edgeEffectFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: availableSize.width, height: edgeEffectHeight))
|
||||
transition.setFrame(view: self.topEdgeEffectView, frame: edgeEffectFrame)
|
||||
self.topEdgeEffectView.update(content: environment.theme.actionSheet.opaqueItemBackgroundColor, blur: true, alpha: 1.0, rect: edgeEffectFrame, edge: .top, edgeSize: edgeEffectFrame.height, transition: transition)
|
||||
if self.topEdgeEffectView.superview == nil {
|
||||
self.navigationBarContainer.insertSubview(self.topEdgeEffectView, at: 0)
|
||||
}
|
||||
|
||||
var bottomPanelHeight = 13.0 + buttonInsets.bottom + actionButtonSize.height
|
||||
|
||||
let bottomEdgeEffectHeight: CGFloat = bottomPanelHeight
|
||||
let bottomEdgeEffectFrame = CGRect(origin: CGPoint(x: 0.0, y: availableSize.height - bottomEdgeEffectHeight), size: CGSize(width: availableSize.width, height: bottomEdgeEffectHeight))
|
||||
transition.setFrame(view: self.bottomEdgeEffectView, frame: bottomEdgeEffectFrame)
|
||||
self.bottomEdgeEffectView.update(content: environment.theme.actionSheet.opaqueItemBackgroundColor, blur: true, alpha: 1.0, rect: bottomEdgeEffectFrame, edge: .bottom, edgeSize: bottomEdgeEffectFrame.height, transition: transition)
|
||||
if self.bottomEdgeEffectView.superview == nil {
|
||||
self.containerView.addSubview(self.bottomEdgeEffectView)
|
||||
}
|
||||
|
||||
let actionButtonFrame = CGRect(origin: CGPoint(x: buttonInsets.left, y: availableSize.height - buttonInsets.bottom - actionButtonSize.height), size: actionButtonSize)
|
||||
bottomPanelHeight -= 1.0
|
||||
if let actionButtonView = actionButton.view {
|
||||
@@ -2525,7 +2580,7 @@ private final class GiftAuctionBidScreenComponent: Component {
|
||||
|
||||
let scrollContentHeight = max(topInset + contentHeight + containerInset, availableSize.height - containerInset)
|
||||
|
||||
self.scrollContentClippingView.layer.cornerRadius = 10.0
|
||||
self.scrollContentClippingView.layer.cornerRadius = 38.0
|
||||
|
||||
self.itemLayout = ItemLayout(containerSize: availableSize, containerInset: containerInset, containerCornerRadius: environment.deviceMetrics.screenCornerRadius, bottomInset: environment.safeInsets.bottom, topInset: topInset)
|
||||
|
||||
@@ -2626,10 +2681,26 @@ public class GiftAuctionBidScreen: ViewControllerComponentContainer {
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func dismissAllTooltips() {
|
||||
self.window?.forEachController({ controller in
|
||||
if let controller = controller as? UndoOverlayController {
|
||||
controller.dismiss()
|
||||
}
|
||||
})
|
||||
self.forEachController({ controller in
|
||||
if let controller = controller as? UndoOverlayController {
|
||||
controller.dismiss()
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
override public func dismiss(completion: (() -> Void)? = nil) {
|
||||
if !self.isDismissed {
|
||||
self.isDismissed = true
|
||||
|
||||
self.dismissAllTooltips()
|
||||
|
||||
if let componentView = self.node.hostView.componentView as? GiftAuctionBidScreenComponent.View {
|
||||
componentView.animateOut(completion: { [weak self] in
|
||||
completion?()
|
||||
|
||||
+47
-19
@@ -26,17 +26,20 @@ private final class GiftAuctionInfoSheetContent: CombinedComponent {
|
||||
|
||||
let context: AccountContext
|
||||
let gift: StarGift
|
||||
let auctionContext: GiftAuctionContext
|
||||
let animateOut: ActionSlot<Action<()>>
|
||||
let getController: () -> ViewController?
|
||||
|
||||
init(
|
||||
context: AccountContext,
|
||||
gift: StarGift,
|
||||
auctionContext: GiftAuctionContext,
|
||||
animateOut: ActionSlot<Action<()>>,
|
||||
getController: @escaping () -> ViewController?
|
||||
) {
|
||||
self.context = context
|
||||
self.gift = gift
|
||||
self.auctionContext = auctionContext
|
||||
self.animateOut = animateOut
|
||||
self.getController = getController
|
||||
}
|
||||
@@ -53,19 +56,42 @@ private final class GiftAuctionInfoSheetContent: CombinedComponent {
|
||||
|
||||
final class State: ComponentState {
|
||||
private let context: AccountContext
|
||||
private let auctionContext: GiftAuctionContext
|
||||
private let animateOut: ActionSlot<Action<()>>
|
||||
private let getController: () -> ViewController?
|
||||
|
||||
private(set) var rounds: Int32 = 50
|
||||
|
||||
fileprivate let playButtonAnimation = ActionSlot<Void>()
|
||||
private var didPlayAnimation = false
|
||||
|
||||
init(
|
||||
context: AccountContext,
|
||||
auctionContext: GiftAuctionContext,
|
||||
animateOut: ActionSlot<Action<()>>,
|
||||
getController: @escaping () -> ViewController?
|
||||
) {
|
||||
self.context = context
|
||||
self.auctionContext = auctionContext
|
||||
self.animateOut = animateOut
|
||||
self.getController = getController
|
||||
|
||||
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) {
|
||||
@@ -83,7 +109,7 @@ private final class GiftAuctionInfoSheetContent: CombinedComponent {
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -101,7 +127,6 @@ private final class GiftAuctionInfoSheetContent: CombinedComponent {
|
||||
|
||||
let theme = environment.theme
|
||||
let strings = environment.strings
|
||||
let _ = strings
|
||||
|
||||
let sideInset: 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(
|
||||
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,
|
||||
maximumNumberOfLines: 0,
|
||||
lineSpacing: 0.1
|
||||
@@ -153,7 +178,7 @@ private final class GiftAuctionInfoSheetContent: CombinedComponent {
|
||||
|
||||
let text = text.update(
|
||||
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,
|
||||
maximumNumberOfLines: 0,
|
||||
lineSpacing: 0.2
|
||||
@@ -167,15 +192,14 @@ private final class GiftAuctionInfoSheetContent: CombinedComponent {
|
||||
contentSize.height += text.size.height
|
||||
contentSize.height += spacing + 9.0
|
||||
|
||||
//TODO:localize
|
||||
var items: [AnyComponentWithIdentity<Empty>] = []
|
||||
items.append(
|
||||
AnyComponentWithIdentity(
|
||||
id: "top",
|
||||
component: AnyComponent(ParagraphComponent(
|
||||
title: "Top \(auctionGiftsPerRound) Bidders",
|
||||
title: strings.Gift_Auction_Info_TopBidders_Title(auctionGiftsPerRound),
|
||||
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,
|
||||
accentColor: linkColor,
|
||||
iconName: "Premium/Auction/Drop",
|
||||
@@ -187,9 +211,9 @@ private final class GiftAuctionInfoSheetContent: CombinedComponent {
|
||||
AnyComponentWithIdentity(
|
||||
id: "carryover",
|
||||
component: AnyComponent(ParagraphComponent(
|
||||
title: "Bid Carryover",
|
||||
title: strings.Gift_Auction_Info_Carryover_Title,
|
||||
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,
|
||||
accentColor: linkColor,
|
||||
iconName: "Premium/Auction/NextDrop",
|
||||
@@ -201,9 +225,9 @@ private final class GiftAuctionInfoSheetContent: CombinedComponent {
|
||||
AnyComponentWithIdentity(
|
||||
id: "missed",
|
||||
component: AnyComponent(ParagraphComponent(
|
||||
title: "Missed Bidders",
|
||||
title: strings.Gift_Auction_Info_Missed_Title,
|
||||
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,
|
||||
accentColor: linkColor,
|
||||
iconName: "Premium/Auction/Refund",
|
||||
@@ -251,16 +275,15 @@ private final class GiftAuctionInfoSheetContent: CombinedComponent {
|
||||
|
||||
|
||||
var buttonTitle: [AnyComponentWithIdentity<Empty>] = []
|
||||
let playButtonAnimation = ActionSlot<Void>()
|
||||
buttonTitle.append(AnyComponentWithIdentity(id: 0, component: AnyComponent(LottieComponent(
|
||||
content: LottieComponent.AppBundleContent(name: "anim_ok"),
|
||||
color: theme.list.itemCheckColors.foregroundColor,
|
||||
startingPosition: .begin,
|
||||
size: CGSize(width: 28.0, height: 28.0),
|
||||
playOnce: playButtonAnimation
|
||||
playOnce: state.playButtonAnimation
|
||||
))))
|
||||
buttonTitle.append(AnyComponentWithIdentity(id: 1, component: AnyComponent(ButtonTextContentComponent(
|
||||
text: "Understood",
|
||||
text: strings.Gift_Auction_Info_Understood,
|
||||
badge: 0,
|
||||
textColor: theme.list.itemCheckColors.foregroundColor,
|
||||
badgeBackground: theme.list.itemCheckColors.foregroundColor,
|
||||
@@ -303,6 +326,8 @@ private final class GiftAuctionInfoSheetContent: CombinedComponent {
|
||||
|
||||
contentSize.height += 30.0
|
||||
|
||||
state.playAnimationIfNeeded()
|
||||
|
||||
return contentSize
|
||||
}
|
||||
}
|
||||
@@ -313,13 +338,16 @@ final class GiftAuctionInfoSheetComponent: CombinedComponent {
|
||||
|
||||
let context: AccountContext
|
||||
let gift: StarGift
|
||||
let auctionContext: GiftAuctionContext
|
||||
|
||||
init(
|
||||
context: AccountContext,
|
||||
gift: StarGift
|
||||
gift: StarGift,
|
||||
auctionContext: GiftAuctionContext
|
||||
) {
|
||||
self.context = context
|
||||
self.gift = gift
|
||||
self.auctionContext = auctionContext
|
||||
}
|
||||
|
||||
static func ==(lhs: GiftAuctionInfoSheetComponent, rhs: GiftAuctionInfoSheetComponent) -> Bool {
|
||||
@@ -347,6 +375,7 @@ final class GiftAuctionInfoSheetComponent: CombinedComponent {
|
||||
content: AnyComponent<EnvironmentType>(GiftAuctionInfoSheetContent(
|
||||
context: context.component.context,
|
||||
gift: context.component.gift,
|
||||
auctionContext: context.component.auctionContext,
|
||||
animateOut: animateOut,
|
||||
getController: controller
|
||||
)),
|
||||
@@ -422,23 +451,22 @@ final class GiftAuctionInfoSheetComponent: CombinedComponent {
|
||||
|
||||
public final class GiftAuctionInfoScreen: ViewControllerComponentContainer {
|
||||
private let context: AccountContext
|
||||
private let gift: StarGift
|
||||
fileprivate let completion: (() -> Void)?
|
||||
|
||||
public init(
|
||||
context: AccountContext,
|
||||
gift: StarGift,
|
||||
auctionContext: GiftAuctionContext,
|
||||
completion: (() -> Void)?
|
||||
) {
|
||||
self.context = context
|
||||
self.gift = gift
|
||||
self.completion = completion
|
||||
|
||||
super.init(
|
||||
context: context,
|
||||
component: GiftAuctionInfoSheetComponent(
|
||||
context: context,
|
||||
gift: gift
|
||||
gift: auctionContext.gift,
|
||||
auctionContext: auctionContext
|
||||
),
|
||||
navigationBarAppearance: .none,
|
||||
statusBarStyle: .ignore,
|
||||
|
||||
+21
-13
@@ -291,6 +291,7 @@ private final class GiftAuctionViewSheetContent: CombinedComponent {
|
||||
|
||||
let context = self.context
|
||||
let gift = self.auctionContext.gift
|
||||
let auctionContext = self.auctionContext
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
var link = ""
|
||||
@@ -300,12 +301,14 @@ private final class GiftAuctionViewSheetContent: CombinedComponent {
|
||||
|
||||
var items: [ContextMenuItem] = []
|
||||
|
||||
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)
|
||||
|
||||
let infoController = context.sharedContext.makeGiftAuctionInfoScreen(context: context, gift: gift, completion: nil)
|
||||
controller?.push(infoController)
|
||||
})))
|
||||
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
|
||||
f(.default)
|
||||
|
||||
let infoController = context.sharedContext.makeGiftAuctionInfoScreen(context: context, auctionContext: auctionContext, completion: nil)
|
||||
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
|
||||
f(.default)
|
||||
@@ -599,7 +602,7 @@ private final class GiftAuctionViewSheetContent: CombinedComponent {
|
||||
if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String {
|
||||
let controller = component.context.sharedContext.makeGiftAuctionInfoScreen(
|
||||
context: component.context,
|
||||
gift: component.auctionContext.gift,
|
||||
auctionContext: component.auctionContext,
|
||||
completion: nil
|
||||
)
|
||||
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 {
|
||||
originY += 5.0
|
||||
|
||||
let text = strings.Gift_Auction_ItemsBought(Int32(state.giftAuctionAcquiredGifts.count))
|
||||
let acquiredButton = acquiredButton.update(
|
||||
component: PlainButtonComponent(content: AnyComponent(
|
||||
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(
|
||||
GiftItemComponent(
|
||||
context: component.context,
|
||||
@@ -647,16 +655,16 @@ private final class GiftAuctionViewSheetContent: CombinedComponent {
|
||||
strings: strings,
|
||||
peer: nil,
|
||||
subject: .starGift(gift: gift, price: ""),
|
||||
mode: .tableIcon
|
||||
mode: .buttonIcon
|
||||
)
|
||||
)),
|
||||
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(
|
||||
BundleIconComponent(name: "Settings/TextArrowRight", tintColor: environment.theme.actionSheet.controlAccentColor)
|
||||
AnyComponentWithIdentity(id: "arrow", component: AnyComponent(
|
||||
BundleIconComponent(name: "Chat/Context Menu/Arrow", tintColor: theme.actionSheet.controlAccentColor)
|
||||
))
|
||||
], spacing: 6.0)
|
||||
], spacing: 0.0)
|
||||
), action: { [weak state] in
|
||||
guard let state else {
|
||||
return
|
||||
|
||||
@@ -292,9 +292,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
}
|
||||
}))
|
||||
|
||||
if arguments.upgradeStars == nil {
|
||||
self.fetchUpgradeForm()
|
||||
}
|
||||
self.fetchUpgradeForm()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2139,6 +2137,31 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
}
|
||||
} else {
|
||||
self.scheduledUpgradeCommit = true
|
||||
|
||||
self.inProgress = true
|
||||
self.updated()
|
||||
|
||||
Queue.mainQueue().after(5.0, {
|
||||
if self.scheduledUpgradeCommit {
|
||||
self.scheduledUpgradeCommit = false
|
||||
self.inProgress = false
|
||||
self.updated()
|
||||
|
||||
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
|
||||
let alertController = textAlertController(
|
||||
context: self.context,
|
||||
title: nil,
|
||||
text: presentationData.strings.Login_UnknownError,
|
||||
actions: [
|
||||
TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})
|
||||
],
|
||||
parseMarkdown: true
|
||||
)
|
||||
if let controller = self.getController() {
|
||||
controller.present(alertController, in: .window(.root))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3842,8 +3842,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
return controller
|
||||
}
|
||||
|
||||
public func makeGiftAuctionInfoScreen(context: AccountContext, gift: StarGift, completion: (() -> Void)?) -> ViewController {
|
||||
return GiftAuctionInfoScreen(context: context, gift: gift, completion: completion)
|
||||
public func makeGiftAuctionInfoScreen(context: AccountContext, auctionContext: GiftAuctionContext, completion: (() -> Void)?) -> ViewController {
|
||||
return GiftAuctionInfoScreen(context: context, auctionContext: auctionContext, completion: completion)
|
||||
}
|
||||
|
||||
public func makeGiftAuctionBidScreen(context: AccountContext, auctionContext: GiftAuctionContext) -> ViewController {
|
||||
|
||||
Reference in New Issue
Block a user