mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-07-21 10:41:12 +00:00
Merge commit '34372148fb42eee7bc7cd724cb475dba0dc0e95d'
# Conflicts: # submodules/TelegramCore/Sources/TelegramEngine/Payments/Stars.swift # submodules/TelegramUI/Components/Stars/StarsAvatarComponent/Sources/StarsAvatarComponent.swift # submodules/TelegramUI/Components/Stars/StarsTransactionScreen/Sources/StarsTransactionScreen.swift # submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsBalanceComponent.swift # submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsTransactionsListPanelComponent.swift
This commit is contained in:
commit
adae44e26f
@ -1213,6 +1213,7 @@ public protocol SharedAccountContext: AnyObject {
|
|||||||
func makeStoryStatsController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, peerId: EnginePeer.Id, storyId: Int32, storyItem: EngineStoryItem, fromStory: Bool) -> ViewController
|
func makeStoryStatsController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, peerId: EnginePeer.Id, storyId: Int32, storyItem: EngineStoryItem, fromStory: Bool) -> ViewController
|
||||||
|
|
||||||
func makeStarsTransactionsScreen(context: AccountContext, starsContext: StarsContext) -> ViewController
|
func makeStarsTransactionsScreen(context: AccountContext, starsContext: StarsContext) -> ViewController
|
||||||
|
func makeTonTransactionsScreen(context: AccountContext, tonContext: StarsContext) -> ViewController
|
||||||
func makeStarsPurchaseScreen(context: AccountContext, starsContext: StarsContext, options: [Any], purpose: StarsPurchasePurpose, completion: @escaping (Int64) -> Void) -> ViewController
|
func makeStarsPurchaseScreen(context: AccountContext, starsContext: StarsContext, options: [Any], purpose: StarsPurchasePurpose, completion: @escaping (Int64) -> Void) -> ViewController
|
||||||
func makeStarsTransferScreen(context: AccountContext, starsContext: StarsContext, invoice: TelegramMediaInvoice, source: BotPaymentInvoiceSource, extendedMedia: [TelegramExtendedMedia], inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?, EnginePeer?)?, NoError>, completion: @escaping (Bool) -> Void) -> ViewController
|
func makeStarsTransferScreen(context: AccountContext, starsContext: StarsContext, invoice: TelegramMediaInvoice, source: BotPaymentInvoiceSource, extendedMedia: [TelegramExtendedMedia], inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?, EnginePeer?)?, NoError>, completion: @escaping (Bool) -> Void) -> ViewController
|
||||||
func makeStarsSubscriptionTransferScreen(context: AccountContext, starsContext: StarsContext, invoice: TelegramMediaInvoice, link: String, inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?, EnginePeer?)?, NoError>, navigateToPeer: @escaping (EnginePeer) -> Void) -> ViewController
|
func makeStarsSubscriptionTransferScreen(context: AccountContext, starsContext: StarsContext, invoice: TelegramMediaInvoice, link: String, inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?, EnginePeer?)?, NoError>, navigateToPeer: @escaping (EnginePeer) -> Void) -> ViewController
|
||||||
|
@ -87,6 +87,12 @@ public extension ComponentTransition.Update {
|
|||||||
transition.setBounds(view: view, bounds: CGRect(origin: CGPoint(), size: size))
|
transition.setBounds(view: view, bounds: CGRect(origin: CGPoint(), size: size))
|
||||||
transition.setPosition(view: view, position: position)
|
transition.setPosition(view: view, position: position)
|
||||||
transition.setScale(view: view, scale: scale)
|
transition.setScale(view: view, scale: scale)
|
||||||
|
} else {
|
||||||
|
if view is UIScrollView {
|
||||||
|
let frame = component.size.centered(around: component._position ?? CGPoint())
|
||||||
|
if view.frame != frame {
|
||||||
|
transition.setFrame(view: view, frame: frame)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if component._anchorPoint != nil {
|
if component._anchorPoint != nil {
|
||||||
view.bounds = CGRect(origin: CGPoint(), size: size)
|
view.bounds = CGRect(origin: CGPoint(), size: size)
|
||||||
@ -95,6 +101,7 @@ public extension ComponentTransition.Update {
|
|||||||
}
|
}
|
||||||
transition.setPosition(view: view, position: position)
|
transition.setPosition(view: view, position: position)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
let opacity = component._opacity ?? 1.0
|
let opacity = component._opacity ?? 1.0
|
||||||
if view.alpha != opacity {
|
if view.alpha != opacity {
|
||||||
transition.setAlpha(view: view, alpha: opacity)
|
transition.setAlpha(view: view, alpha: opacity)
|
||||||
|
@ -723,6 +723,9 @@ public extension CombinedComponent {
|
|||||||
updatedChild.view.bounds = CGRect(origin: CGPoint(), size: updatedChild.size)
|
updatedChild.view.bounds = CGRect(origin: CGPoint(), size: updatedChild.size)
|
||||||
updatedChild.view.center = updatedChild._position ?? CGPoint()
|
updatedChild.view.center = updatedChild._position ?? CGPoint()
|
||||||
updatedChild.view.transform = CGAffineTransform(scaleX: scale, y: scale)
|
updatedChild.view.transform = CGAffineTransform(scaleX: scale, y: scale)
|
||||||
|
} else {
|
||||||
|
if updatedChild.view is UIScrollView {
|
||||||
|
updatedChild.view.frame = updatedChild.size.centered(around: updatedChild._position ?? CGPoint())
|
||||||
} else {
|
} else {
|
||||||
updatedChild.view.bounds = CGRect(origin: CGPoint(), size: updatedChild.size)
|
updatedChild.view.bounds = CGRect(origin: CGPoint(), size: updatedChild.size)
|
||||||
if updatedChild.view.layer.anchorPoint != CGPoint(x: 0.5, y: 0.5) {
|
if updatedChild.view.layer.anchorPoint != CGPoint(x: 0.5, y: 0.5) {
|
||||||
@ -731,6 +734,7 @@ public extension CombinedComponent {
|
|||||||
updatedChild.view.center = updatedChild._position ?? CGPoint()
|
updatedChild.view.center = updatedChild._position ?? CGPoint()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
updatedChild.view.alpha = updatedChild._opacity ?? 1.0
|
updatedChild.view.alpha = updatedChild._opacity ?? 1.0
|
||||||
updatedChild.view.clipsToBounds = updatedChild._clipsToBounds ?? false
|
updatedChild.view.clipsToBounds = updatedChild._clipsToBounds ?? false
|
||||||
|
BIN
submodules/PremiumUI/Resources/diamond.scn
Normal file
BIN
submodules/PremiumUI/Resources/diamond.scn
Normal file
Binary file not shown.
@ -280,9 +280,9 @@ final class StarsTransactionItemNode: ListViewItemNode, ItemListItemNode {
|
|||||||
let itemLabel: NSAttributedString
|
let itemLabel: NSAttributedString
|
||||||
let labelString: String
|
let labelString: String
|
||||||
|
|
||||||
let absCount = StarsAmount(value: abs(item.transaction.count.value), nanos: abs(item.transaction.count.nanos))
|
let absCount = StarsAmount(value: abs(item.transaction.count.amount.value), nanos: abs(item.transaction.count.amount.nanos))
|
||||||
let formattedLabel = presentationStringsFormattedNumber(absCount, item.presentationData.dateTimeFormat.groupingSeparator)
|
let formattedLabel = presentationStringsFormattedNumber(absCount, item.presentationData.dateTimeFormat.groupingSeparator)
|
||||||
if item.transaction.count < StarsAmount.zero {
|
if item.transaction.count.amount < StarsAmount.zero {
|
||||||
labelString = "- \(formattedLabel)"
|
labelString = "- \(formattedLabel)"
|
||||||
} else {
|
} else {
|
||||||
labelString = "+ \(formattedLabel)"
|
labelString = "+ \(formattedLabel)"
|
||||||
|
@ -618,9 +618,9 @@ private final class StarsContextImpl {
|
|||||||
}
|
}
|
||||||
var transactions = state.transactions
|
var transactions = state.transactions
|
||||||
if addTransaction {
|
if addTransaction {
|
||||||
transactions.insert(.init(flags: [.isLocal], id: "\(arc4random())", count: balance, currency: self.ton ? .ton : .stars, date: Int32(Date().timeIntervalSince1970), peer: .appStore, title: nil, description: nil, photo: nil, transactionDate: nil, transactionUrl: nil, paidMessageId: nil, giveawayMessageId: nil, media: [], subscriptionPeriod: nil, starGift: nil, floodskipNumber: nil, starrefCommissionPermille: nil, starrefPeerId: nil, starrefAmount: nil, paidMessageCount: nil, premiumGiftMonths: nil), at: 0)
|
let count = CurrencyAmount(amount: balance, currency: self.ton ? .ton : .stars)
|
||||||
|
transactions.insert(.init(flags: [.isLocal], id: "\(arc4random())", count: count, date: Int32(Date().timeIntervalSince1970), peer: .appStore, title: nil, description: nil, photo: nil, transactionDate: nil, transactionUrl: nil, paidMessageId: nil, giveawayMessageId: nil, media: [], subscriptionPeriod: nil, starGift: nil, floodskipNumber: nil, starrefCommissionPermille: nil, starrefPeerId: nil, starrefAmount: nil, paidMessageCount: nil, premiumGiftMonths: nil), at: 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.updateState(StarsContext.State(flags: [.isPendingBalance], balance: max(StarsAmount(value: 0, nanos: 0), state.balance + balance), subscriptions: state.subscriptions, canLoadMoreSubscriptions: state.canLoadMoreSubscriptions, transactions: transactions, canLoadMoreTransactions: state.canLoadMoreTransactions, isLoading: state.isLoading))
|
self.updateState(StarsContext.State(flags: [.isPendingBalance], balance: max(StarsAmount(value: 0, nanos: 0), state.balance + balance), subscriptions: state.subscriptions, canLoadMoreSubscriptions: state.canLoadMoreSubscriptions, transactions: transactions, canLoadMoreTransactions: state.canLoadMoreTransactions, isLoading: state.isLoading))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -724,9 +724,7 @@ private extension StarsContext.State.Transaction {
|
|||||||
let media = extendedMedia.flatMap({ $0.compactMap { textMediaAndExpirationTimerFromApiMedia($0, PeerId(0)).media } }) ?? []
|
let media = extendedMedia.flatMap({ $0.compactMap { textMediaAndExpirationTimerFromApiMedia($0, PeerId(0)).media } }) ?? []
|
||||||
let _ = subscriptionPeriod
|
let _ = subscriptionPeriod
|
||||||
|
|
||||||
let amount = CurrencyAmount(apiAmount: stars)
|
self.init(flags: flags, id: id, count: CurrencyAmount(apiAmount: stars), date: date, peer: parsedPeer, title: title, description: description, photo: photo.flatMap(TelegramMediaWebFile.init), transactionDate: transactionDate, transactionUrl: transactionUrl, paidMessageId: paidMessageId, giveawayMessageId: giveawayMessageId, media: media, subscriptionPeriod: subscriptionPeriod, starGift: starGift.flatMap { StarGift(apiStarGift: $0) }, floodskipNumber: floodskipNumber, starrefCommissionPermille: starrefCommissionPermille, starrefPeerId: starrefPeer?.peerId, starrefAmount: starrefAmount.flatMap(StarsAmount.init(apiAmount:)), paidMessageCount: paidMessageCount, premiumGiftMonths: premiumGiftMonths)
|
||||||
|
|
||||||
self.init(flags: flags, id: id, count: amount.amount, currency: amount.currency, date: date, peer: parsedPeer, title: title, description: description, photo: photo.flatMap(TelegramMediaWebFile.init), transactionDate: transactionDate, transactionUrl: transactionUrl, paidMessageId: paidMessageId, giveawayMessageId: giveawayMessageId, media: media, subscriptionPeriod: subscriptionPeriod, starGift: starGift.flatMap { StarGift(apiStarGift: $0) }, floodskipNumber: floodskipNumber, starrefCommissionPermille: starrefCommissionPermille, starrefPeerId: starrefPeer?.peerId, starrefAmount: starrefAmount.flatMap(StarsAmount.init(apiAmount:)), paidMessageCount: paidMessageCount, premiumGiftMonths: premiumGiftMonths)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -791,8 +789,7 @@ public final class StarsContext {
|
|||||||
|
|
||||||
public let flags: Flags
|
public let flags: Flags
|
||||||
public let id: String
|
public let id: String
|
||||||
public let count: StarsAmount
|
public let count: CurrencyAmount
|
||||||
public let currency: CurrencyAmount.Currency
|
|
||||||
public let date: Int32
|
public let date: Int32
|
||||||
public let peer: Peer
|
public let peer: Peer
|
||||||
public let title: String?
|
public let title: String?
|
||||||
@ -815,8 +812,7 @@ public final class StarsContext {
|
|||||||
public init(
|
public init(
|
||||||
flags: Flags,
|
flags: Flags,
|
||||||
id: String,
|
id: String,
|
||||||
count: StarsAmount,
|
count: CurrencyAmount,
|
||||||
currency: CurrencyAmount.Currency,
|
|
||||||
date: Int32,
|
date: Int32,
|
||||||
peer: Peer,
|
peer: Peer,
|
||||||
title: String?,
|
title: String?,
|
||||||
@ -839,7 +835,6 @@ public final class StarsContext {
|
|||||||
self.flags = flags
|
self.flags = flags
|
||||||
self.id = id
|
self.id = id
|
||||||
self.count = count
|
self.count = count
|
||||||
self.currency = currency
|
|
||||||
self.date = date
|
self.date = date
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
self.title = title
|
self.title = title
|
||||||
@ -1079,7 +1074,7 @@ public final class StarsContext {
|
|||||||
return peerId!
|
return peerId!
|
||||||
}
|
}
|
||||||
|
|
||||||
public let ton: Bool
|
let ton: Bool
|
||||||
|
|
||||||
public var currentState: StarsContext.State? {
|
public var currentState: StarsContext.State? {
|
||||||
var state: StarsContext.State?
|
var state: StarsContext.State?
|
||||||
@ -1173,9 +1168,9 @@ private final class StarsTransactionsContextImpl {
|
|||||||
case .all:
|
case .all:
|
||||||
initialTransactions = currentTransactions
|
initialTransactions = currentTransactions
|
||||||
case .incoming:
|
case .incoming:
|
||||||
initialTransactions = currentTransactions.filter { $0.count > StarsAmount.zero }
|
initialTransactions = currentTransactions.filter { $0.count.amount > StarsAmount.zero }
|
||||||
case .outgoing:
|
case .outgoing:
|
||||||
initialTransactions = currentTransactions.filter { $0.count < StarsAmount.zero }
|
initialTransactions = currentTransactions.filter { $0.count.amount < StarsAmount.zero }
|
||||||
}
|
}
|
||||||
|
|
||||||
self._state = StarsTransactionsContext.State(transactions: initialTransactions, canLoadMore: true, isLoading: false)
|
self._state = StarsTransactionsContext.State(transactions: initialTransactions, canLoadMore: true, isLoading: false)
|
||||||
@ -1193,9 +1188,9 @@ private final class StarsTransactionsContextImpl {
|
|||||||
case .all:
|
case .all:
|
||||||
filteredTransactions = currentTransactions
|
filteredTransactions = currentTransactions
|
||||||
case .incoming:
|
case .incoming:
|
||||||
filteredTransactions = currentTransactions.filter { $0.count > StarsAmount.zero }
|
filteredTransactions = currentTransactions.filter { $0.count.amount > StarsAmount.zero }
|
||||||
case .outgoing:
|
case .outgoing:
|
||||||
filteredTransactions = currentTransactions.filter { $0.count < StarsAmount.zero }
|
filteredTransactions = currentTransactions.filter { $0.count.amount < StarsAmount.zero }
|
||||||
}
|
}
|
||||||
|
|
||||||
if !filteredTransactions.isEmpty && self._state.transactions.isEmpty && filteredTransactions != initialTransactions {
|
if !filteredTransactions.isEmpty && self._state.transactions.isEmpty && filteredTransactions != initialTransactions {
|
||||||
@ -1220,9 +1215,9 @@ private final class StarsTransactionsContextImpl {
|
|||||||
case .all:
|
case .all:
|
||||||
filteredTransactions = currentTransactions
|
filteredTransactions = currentTransactions
|
||||||
case .incoming:
|
case .incoming:
|
||||||
filteredTransactions = currentTransactions.filter { $0.count > StarsAmount.zero }
|
filteredTransactions = currentTransactions.filter { $0.count.amount > StarsAmount.zero }
|
||||||
case .outgoing:
|
case .outgoing:
|
||||||
filteredTransactions = currentTransactions.filter { $0.count < StarsAmount.zero }
|
filteredTransactions = currentTransactions.filter { $0.count.amount < StarsAmount.zero }
|
||||||
}
|
}
|
||||||
|
|
||||||
if filteredTransactions != initialTransactions {
|
if filteredTransactions != initialTransactions {
|
||||||
|
@ -93,6 +93,15 @@ public func formatStarsAmountText(_ amount: StarsAmount, dateTimeFormat: Present
|
|||||||
return balanceText
|
return balanceText
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func formatCurrencyAmountText(_ amount: CurrencyAmount, dateTimeFormat: PresentationDateTimeFormat, showPlus: Bool = false) -> String {
|
||||||
|
switch amount.currency {
|
||||||
|
case .stars:
|
||||||
|
return formatStarsAmountText(amount.amount, dateTimeFormat: dateTimeFormat, showPlus: showPlus)
|
||||||
|
case .ton:
|
||||||
|
return formatTonAmountText(amount.amount.value, dateTimeFormat: dateTimeFormat, showPlus: showPlus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private let invalidAddressCharacters = CharacterSet(charactersIn: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=").inverted
|
private let invalidAddressCharacters = CharacterSet(charactersIn: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=").inverted
|
||||||
public func isValidTonAddress(_ address: String, exactLength: Bool = false) -> Bool {
|
public func isValidTonAddress(_ address: String, exactLength: Bool = false) -> Bool {
|
||||||
if address.count > walletAddressLength || address.rangeOfCharacter(from: invalidAddressCharacters) != nil {
|
if address.count > walletAddressLength || address.rangeOfCharacter(from: invalidAddressCharacters) != nil {
|
||||||
|
@ -1037,9 +1037,9 @@ private func settingsItems(data: PeerInfoScreenData?, context: AccountContext, p
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let tonState = data.tonState {
|
if let tonState = data.tonState {
|
||||||
if !isPremiumDisabled || tonState.balance != .zero {
|
if abs(tonState.balance.value) > 0 {
|
||||||
let balanceText: NSAttributedString
|
let balanceText: NSAttributedString
|
||||||
if tonState.balance != .zero {
|
if abs(tonState.balance.value) > 0 {
|
||||||
let formattedLabel = formatTonAmountText(tonState.balance.value, dateTimeFormat: presentationData.dateTimeFormat)
|
let formattedLabel = formatTonAmountText(tonState.balance.value, dateTimeFormat: presentationData.dateTimeFormat)
|
||||||
let smallLabelFont = Font.regular(floor(presentationData.listsFontSize.itemListBaseFontSize / 17.0 * 13.0))
|
let smallLabelFont = Font.regular(floor(presentationData.listsFontSize.itemListBaseFontSize / 17.0 * 13.0))
|
||||||
let labelFont = Font.regular(presentationData.listsFontSize.itemListBaseFontSize)
|
let labelFont = Font.regular(presentationData.listsFontSize.itemListBaseFontSize)
|
||||||
@ -1049,19 +1049,19 @@ private func settingsItems(data: PeerInfoScreenData?, context: AccountContext, p
|
|||||||
balanceText = NSAttributedString()
|
balanceText = NSAttributedString()
|
||||||
}
|
}
|
||||||
//TODO:localize
|
//TODO:localize
|
||||||
items[.payment]!.append(PeerInfoScreenDisclosureItem(id: 105, label: .attributedText(balanceText), text: "TON", icon: PresentationResourcesSettings.ton, action: {
|
items[.payment]!.append(PeerInfoScreenDisclosureItem(id: 103, label: .attributedText(balanceText), text: "My TON", icon: PresentationResourcesSettings.ton, action: {
|
||||||
interaction.openSettings(.ton)
|
interaction.openSettings(.ton)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !isPremiumDisabled || context.isPremium {
|
if !isPremiumDisabled || context.isPremium {
|
||||||
items[.payment]!.append(PeerInfoScreenDisclosureItem(id: 103, label: .text(""), additionalBadgeLabel: nil, text: presentationData.strings.Settings_Business, icon: PresentationResourcesSettings.business, action: {
|
items[.payment]!.append(PeerInfoScreenDisclosureItem(id: 104, label: .text(""), additionalBadgeLabel: nil, text: presentationData.strings.Settings_Business, icon: PresentationResourcesSettings.business, action: {
|
||||||
interaction.openSettings(.businessSetup)
|
interaction.openSettings(.businessSetup)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
if let starsState = data.starsState {
|
if let starsState = data.starsState {
|
||||||
if !isPremiumDisabled || starsState.balance > StarsAmount.zero {
|
if !isPremiumDisabled || starsState.balance > StarsAmount.zero {
|
||||||
items[.payment]!.append(PeerInfoScreenDisclosureItem(id: 104, label: .text(""), text: presentationData.strings.Settings_SendGift, icon: PresentationResourcesSettings.premiumGift, action: {
|
items[.payment]!.append(PeerInfoScreenDisclosureItem(id: 105, label: .text(""), text: presentationData.strings.Settings_SendGift, icon: PresentationResourcesSettings.premiumGift, action: {
|
||||||
interaction.openSettings(.premiumGift)
|
interaction.openSettings(.premiumGift)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -10670,7 +10670,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
}
|
}
|
||||||
case .ton:
|
case .ton:
|
||||||
if let tonContext = self.controller?.tonContext {
|
if let tonContext = self.controller?.tonContext {
|
||||||
push(self.context.sharedContext.makeStarsTransactionsScreen(context: self.context, starsContext: tonContext))
|
push(self.context.sharedContext.makeTonTransactionsScreen(context: self.context, tonContext: tonContext))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12971,18 +12971,23 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
|
|||||||
self.chatLocation = .peer(id: peerId)
|
self.chatLocation = .peer(id: peerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
if isSettings, let starsContext = context.starsContext {
|
if isSettings {
|
||||||
|
if let starsContext = context.starsContext {
|
||||||
self.starsContext = starsContext
|
self.starsContext = starsContext
|
||||||
starsContext.load(force: true)
|
starsContext.load(force: true)
|
||||||
} else {
|
} else {
|
||||||
self.starsContext = nil
|
self.starsContext = nil
|
||||||
}
|
}
|
||||||
if isSettings, let tonContext = context.tonContext {
|
if let tonContext = context.tonContext {
|
||||||
self.tonContext = tonContext
|
self.tonContext = tonContext
|
||||||
tonContext.load(force: true)
|
tonContext.load(force: true)
|
||||||
} else {
|
} else {
|
||||||
self.tonContext = nil
|
self.tonContext = nil
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
self.starsContext = nil
|
||||||
|
self.tonContext = nil
|
||||||
|
}
|
||||||
|
|
||||||
if isMyProfile, let profileGiftsContext {
|
if isMyProfile, let profileGiftsContext {
|
||||||
profileGiftsContext.updateFilter(.All)
|
profileGiftsContext.updateFilter(.All)
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
|
||||||
|
|
||||||
|
swift_library(
|
||||||
|
name = "PremiumDiamondComponent",
|
||||||
|
module_name = "PremiumDiamondComponent",
|
||||||
|
srcs = glob([
|
||||||
|
"Sources/**/*.swift",
|
||||||
|
]),
|
||||||
|
copts = [
|
||||||
|
"-warnings-as-errors",
|
||||||
|
],
|
||||||
|
deps = [
|
||||||
|
"//submodules/AsyncDisplayKit",
|
||||||
|
"//submodules/Display",
|
||||||
|
"//submodules/SSignalKit/SwiftSignalKit",
|
||||||
|
"//submodules/ComponentFlow",
|
||||||
|
"//submodules/AccountContext",
|
||||||
|
"//submodules/AppBundle",
|
||||||
|
"//submodules/GZip",
|
||||||
|
"//submodules/LegacyComponents",
|
||||||
|
"//submodules/Components/MultilineTextComponent:MultilineTextComponent",
|
||||||
|
"//submodules/TelegramUI/Components/Premium/PremiumStarComponent",
|
||||||
|
],
|
||||||
|
visibility = [
|
||||||
|
"//visibility:public",
|
||||||
|
],
|
||||||
|
)
|
@ -0,0 +1,309 @@
|
|||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
import Display
|
||||||
|
import ComponentFlow
|
||||||
|
import SwiftSignalKit
|
||||||
|
import SceneKit
|
||||||
|
import GZip
|
||||||
|
import AppBundle
|
||||||
|
import LegacyComponents
|
||||||
|
import PremiumStarComponent
|
||||||
|
|
||||||
|
private let sceneVersion: Int = 5
|
||||||
|
|
||||||
|
private func deg2rad(_ number: Float) -> Float {
|
||||||
|
return number * .pi / 180
|
||||||
|
}
|
||||||
|
|
||||||
|
private func rad2deg(_ number: Float) -> Float {
|
||||||
|
return number * 180.0 / .pi
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class PremiumDiamondComponent: Component {
|
||||||
|
public init() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func ==(lhs: PremiumDiamondComponent, rhs: PremiumDiamondComponent) -> Bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class View: UIView, SCNSceneRendererDelegate, ComponentTaggedView {
|
||||||
|
public final class Tag {
|
||||||
|
public init() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func matches(tag: Any) -> Bool {
|
||||||
|
if let _ = tag as? Tag {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private var _ready = Promise<Bool>()
|
||||||
|
public var ready: Signal<Bool, NoError> {
|
||||||
|
return self._ready.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
weak var animateFrom: UIView?
|
||||||
|
weak var containerView: UIView?
|
||||||
|
|
||||||
|
private let sceneView: SCNView
|
||||||
|
|
||||||
|
private var timer: SwiftSignalKit.Timer?
|
||||||
|
|
||||||
|
private var component: PremiumDiamondComponent?
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
self.sceneView = SCNView(frame: CGRect(origin: .zero, size: CGSize(width: 64.0, height: 64.0)))
|
||||||
|
self.sceneView.backgroundColor = .clear
|
||||||
|
self.sceneView.transform = CGAffineTransform(scaleX: 0.5, y: 0.5)
|
||||||
|
self.sceneView.isUserInteractionEnabled = false
|
||||||
|
self.sceneView.preferredFramesPerSecond = 60
|
||||||
|
self.sceneView.isJitteringEnabled = true
|
||||||
|
|
||||||
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
self.addSubview(self.sceneView)
|
||||||
|
|
||||||
|
self.setup()
|
||||||
|
|
||||||
|
let panGestureRecoginzer = UIPanGestureRecognizer(target: self, action: #selector(self.handlePan(_:)))
|
||||||
|
self.addGestureRecognizer(panGestureRecoginzer)
|
||||||
|
|
||||||
|
self.disablesInteractiveModalDismiss = true
|
||||||
|
self.disablesInteractiveTransitionGestureRecognizer = true
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
self.timer?.invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
private var previousYaw: Float = 0.0
|
||||||
|
@objc private func handlePan(_ gesture: UIPanGestureRecognizer) {
|
||||||
|
guard let scene = self.sceneView.scene, let node = scene.rootNode.childNode(withName: "star", recursively: false) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let keys = [
|
||||||
|
"rotate",
|
||||||
|
"tapRotate",
|
||||||
|
"continuousRotation"
|
||||||
|
]
|
||||||
|
|
||||||
|
for key in keys {
|
||||||
|
node.removeAnimation(forKey: key)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch gesture.state {
|
||||||
|
case .began:
|
||||||
|
self.previousYaw = 0.0
|
||||||
|
case .changed:
|
||||||
|
let translation = gesture.translation(in: gesture.view)
|
||||||
|
let yawPan = deg2rad(Float(translation.x))
|
||||||
|
|
||||||
|
func rubberBandingOffset(offset: CGFloat, bandingStart: CGFloat) -> CGFloat {
|
||||||
|
let bandedOffset = offset - bandingStart
|
||||||
|
let range: CGFloat = 60.0
|
||||||
|
let coefficient: CGFloat = 0.4
|
||||||
|
return bandingStart + (1.0 - (1.0 / ((bandedOffset * coefficient / range) + 1.0))) * range
|
||||||
|
}
|
||||||
|
|
||||||
|
var pitchTranslation = rubberBandingOffset(offset: abs(translation.y), bandingStart: 0.0)
|
||||||
|
if translation.y < 0.0 {
|
||||||
|
pitchTranslation *= -1.0
|
||||||
|
}
|
||||||
|
let pitchPan = deg2rad(Float(pitchTranslation))
|
||||||
|
|
||||||
|
self.previousYaw = yawPan
|
||||||
|
// Maintain the initial tilt while adding pan gestures
|
||||||
|
let initialTiltX: Float = deg2rad(-15.0)
|
||||||
|
let initialTiltZ: Float = deg2rad(5.0)
|
||||||
|
node.eulerAngles = SCNVector3(initialTiltX + pitchPan, yawPan, initialTiltZ)
|
||||||
|
case .ended:
|
||||||
|
let velocity = gesture.velocity(in: gesture.view)
|
||||||
|
|
||||||
|
var smallAngle = false
|
||||||
|
if (self.previousYaw < .pi / 2 && self.previousYaw > -.pi / 2) && abs(velocity.x) < 200 {
|
||||||
|
smallAngle = true
|
||||||
|
}
|
||||||
|
|
||||||
|
self.playAppearanceAnimation(velocity: velocity.x, smallAngle: smallAngle, explode: !smallAngle && abs(velocity.x) > 600)
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setup() {
|
||||||
|
guard let scene = loadCompressedScene(name: "diamond", version: sceneVersion) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self.sceneView.scene = scene
|
||||||
|
self.sceneView.delegate = self
|
||||||
|
|
||||||
|
let _ = self.sceneView.snapshot()
|
||||||
|
}
|
||||||
|
|
||||||
|
private var didSetReady = false
|
||||||
|
public func renderer(_ renderer: SCNSceneRenderer, didRenderScene scene: SCNScene, atTime time: TimeInterval) {
|
||||||
|
if !self.didSetReady {
|
||||||
|
self.didSetReady = true
|
||||||
|
|
||||||
|
Queue.mainQueue().justDispatch {
|
||||||
|
self._ready.set(.single(true))
|
||||||
|
self.onReady()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func onReady() {
|
||||||
|
self.playAppearanceAnimation(mirror: true, explode: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func playAppearanceAnimation(velocity: CGFloat? = nil, smallAngle: Bool = false, mirror: Bool = false, explode: Bool = false) {
|
||||||
|
guard let scene = self.sceneView.scene else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if explode, let node = scene.rootNode.childNode(withName: "swirl", recursively: false), let particlesLeft = scene.rootNode.childNode(withName: "particles_left", recursively: false), let particlesRight = scene.rootNode.childNode(withName: "particles_right", recursively: false), let particlesBottomLeft = scene.rootNode.childNode(withName: "particles_left_bottom", recursively: false), let particlesBottomRight = scene.rootNode.childNode(withName: "particles_right_bottom", recursively: false) {
|
||||||
|
if let leftParticleSystem = particlesLeft.particleSystems?.first, let rightParticleSystem = particlesRight.particleSystems?.first, let leftBottomParticleSystem = particlesBottomLeft.particleSystems?.first, let rightBottomParticleSystem = particlesBottomRight.particleSystems?.first {
|
||||||
|
leftParticleSystem.speedFactor = 2.0
|
||||||
|
leftParticleSystem.particleVelocity = 1.6
|
||||||
|
leftParticleSystem.birthRate = 60.0
|
||||||
|
leftParticleSystem.particleLifeSpan = 4.0
|
||||||
|
|
||||||
|
rightParticleSystem.speedFactor = 2.0
|
||||||
|
rightParticleSystem.particleVelocity = 1.6
|
||||||
|
rightParticleSystem.birthRate = 60.0
|
||||||
|
rightParticleSystem.particleLifeSpan = 4.0
|
||||||
|
|
||||||
|
leftBottomParticleSystem.particleVelocity = 1.6
|
||||||
|
leftBottomParticleSystem.birthRate = 24.0
|
||||||
|
leftBottomParticleSystem.particleLifeSpan = 7.0
|
||||||
|
|
||||||
|
rightBottomParticleSystem.particleVelocity = 1.6
|
||||||
|
rightBottomParticleSystem.birthRate = 24.0
|
||||||
|
rightBottomParticleSystem.particleLifeSpan = 7.0
|
||||||
|
|
||||||
|
node.physicsField?.isActive = true
|
||||||
|
Queue.mainQueue().after(1.0) {
|
||||||
|
node.physicsField?.isActive = false
|
||||||
|
|
||||||
|
leftParticleSystem.birthRate = 15.0
|
||||||
|
leftParticleSystem.particleVelocity = 1.0
|
||||||
|
leftParticleSystem.particleLifeSpan = 3.0
|
||||||
|
|
||||||
|
rightParticleSystem.birthRate = 15.0
|
||||||
|
rightParticleSystem.particleVelocity = 1.0
|
||||||
|
rightParticleSystem.particleLifeSpan = 3.0
|
||||||
|
|
||||||
|
leftBottomParticleSystem.particleVelocity = 1.0
|
||||||
|
leftBottomParticleSystem.birthRate = 10.0
|
||||||
|
leftBottomParticleSystem.particleLifeSpan = 5.0
|
||||||
|
|
||||||
|
rightBottomParticleSystem.particleVelocity = 1.0
|
||||||
|
rightBottomParticleSystem.birthRate = 10.0
|
||||||
|
rightBottomParticleSystem.particleLifeSpan = 5.0
|
||||||
|
|
||||||
|
let leftAnimation = POPBasicAnimation()
|
||||||
|
leftAnimation.property = (POPAnimatableProperty.property(withName: "speedFactor", initializer: { property in
|
||||||
|
property?.readBlock = { particleSystem, values in
|
||||||
|
values?.pointee = (particleSystem as! SCNParticleSystem).speedFactor
|
||||||
|
}
|
||||||
|
property?.writeBlock = { particleSystem, values in
|
||||||
|
(particleSystem as! SCNParticleSystem).speedFactor = values!.pointee
|
||||||
|
}
|
||||||
|
property?.threshold = 0.01
|
||||||
|
}) as! POPAnimatableProperty)
|
||||||
|
leftAnimation.fromValue = 1.2 as NSNumber
|
||||||
|
leftAnimation.toValue = 0.85 as NSNumber
|
||||||
|
leftAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
|
||||||
|
leftAnimation.duration = 0.5
|
||||||
|
leftParticleSystem.pop_add(leftAnimation, forKey: "speedFactor")
|
||||||
|
|
||||||
|
let rightAnimation = POPBasicAnimation()
|
||||||
|
rightAnimation.property = (POPAnimatableProperty.property(withName: "speedFactor", initializer: { property in
|
||||||
|
property?.readBlock = { particleSystem, values in
|
||||||
|
values?.pointee = (particleSystem as! SCNParticleSystem).speedFactor
|
||||||
|
}
|
||||||
|
property?.writeBlock = { particleSystem, values in
|
||||||
|
(particleSystem as! SCNParticleSystem).speedFactor = values!.pointee
|
||||||
|
}
|
||||||
|
property?.threshold = 0.01
|
||||||
|
}) as! POPAnimatableProperty)
|
||||||
|
rightAnimation.fromValue = 1.2 as NSNumber
|
||||||
|
rightAnimation.toValue = 0.85 as NSNumber
|
||||||
|
rightAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
|
||||||
|
rightAnimation.duration = 0.5
|
||||||
|
rightParticleSystem.pop_add(rightAnimation, forKey: "speedFactor")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// var from = node.presentation.eulerAngles
|
||||||
|
// if abs(from.y - .pi * 2.0) < 0.001 {
|
||||||
|
// from.y = 0.0
|
||||||
|
// }
|
||||||
|
// node.removeAnimation(forKey: "tapRotate")
|
||||||
|
//
|
||||||
|
// var toValue: Float = smallAngle ? 0.0 : .pi * 2.0
|
||||||
|
// if let velocity = velocity, !smallAngle && abs(velocity) > 200 && velocity < 0.0 {
|
||||||
|
// toValue *= -1
|
||||||
|
// }
|
||||||
|
// if mirror {
|
||||||
|
// toValue *= -1
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// let to = SCNVector3(x: from.x, y: toValue, z: from.z)
|
||||||
|
// let distance = rad2deg(to.y - from.y)
|
||||||
|
//
|
||||||
|
// guard !distance.isZero else {
|
||||||
|
// Queue.mainQueue().after(0.1) { [weak self] in
|
||||||
|
// self?.setupContinuousRotation()
|
||||||
|
// }
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// let springAnimation = CASpringAnimation(keyPath: "eulerAngles")
|
||||||
|
// springAnimation.fromValue = NSValue(scnVector3: from)
|
||||||
|
// springAnimation.toValue = NSValue(scnVector3: to)
|
||||||
|
// springAnimation.mass = 1.0
|
||||||
|
// springAnimation.stiffness = 21.0
|
||||||
|
// springAnimation.damping = 5.8
|
||||||
|
// springAnimation.duration = springAnimation.settlingDuration * 0.75
|
||||||
|
// springAnimation.initialVelocity = velocity.flatMap { abs($0 / CGFloat(distance)) } ?? 1.7
|
||||||
|
// springAnimation.completion = { [weak self] finished in
|
||||||
|
// if finished {
|
||||||
|
// self?.setupContinuousRotation()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// node.addAnimation(springAnimation, forKey: "rotate")
|
||||||
|
}
|
||||||
|
|
||||||
|
func update(component: PremiumDiamondComponent, availableSize: CGSize, transition: ComponentTransition) -> CGSize {
|
||||||
|
self.component = component
|
||||||
|
|
||||||
|
self.sceneView.bounds = CGRect(origin: .zero, size: CGSize(width: availableSize.width * 2.0, height: availableSize.height * 2.0))
|
||||||
|
if self.sceneView.superview == self {
|
||||||
|
self.sceneView.center = CGPoint(x: availableSize.width / 2.0, y: availableSize.height / 2.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return availableSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func makeView() -> View {
|
||||||
|
return View(frame: CGRect())
|
||||||
|
}
|
||||||
|
|
||||||
|
public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||||
|
return view.update(component: self, availableSize: availableSize, transition: transition)
|
||||||
|
}
|
||||||
|
}
|
@ -372,42 +372,36 @@ public final class StarsAvatarComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class StarsLabelComponent: CombinedComponent {
|
public final class StarsLabelComponent: CombinedComponent {
|
||||||
let theme: PresentationTheme
|
|
||||||
let currency: CurrencyAmount.Currency
|
|
||||||
let textColor: UIColor
|
|
||||||
let text: NSAttributedString
|
let text: NSAttributedString
|
||||||
let subtext: NSAttributedString?
|
let subtext: NSAttributedString?
|
||||||
|
let iconName: String
|
||||||
|
let iconColor: UIColor?
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
theme: PresentationTheme,
|
|
||||||
currency: CurrencyAmount.Currency,
|
|
||||||
textColor: UIColor,
|
|
||||||
text: NSAttributedString,
|
text: NSAttributedString,
|
||||||
subtext: NSAttributedString? = nil
|
subtext: NSAttributedString? = nil,
|
||||||
|
iconName: String = "Premium/Stars/StarMedium",
|
||||||
|
iconColor: UIColor? = nil
|
||||||
) {
|
) {
|
||||||
self.currency = currency
|
|
||||||
self.theme = theme
|
|
||||||
self.textColor = textColor
|
|
||||||
self.text = text
|
self.text = text
|
||||||
self.subtext = subtext
|
self.subtext = subtext
|
||||||
|
self.iconName = iconName
|
||||||
|
self.iconColor = iconColor
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func ==(lhs: StarsLabelComponent, rhs: StarsLabelComponent) -> Bool {
|
public static func ==(lhs: StarsLabelComponent, rhs: StarsLabelComponent) -> Bool {
|
||||||
if lhs.currency != rhs.currency {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if lhs.theme !== rhs.theme {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if lhs.textColor != rhs.textColor {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if lhs.text != rhs.text {
|
if lhs.text != rhs.text {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if lhs.subtext != rhs.subtext {
|
if lhs.subtext != rhs.subtext {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.iconName != rhs.iconName {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.iconColor != rhs.iconColor {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,6 +419,7 @@ public final class StarsLabelComponent: CombinedComponent {
|
|||||||
transition: context.transition
|
transition: context.transition
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
var subtext: _UpdatedChildComponent? = nil
|
var subtext: _UpdatedChildComponent? = nil
|
||||||
if let sublabel = component.subtext {
|
if let sublabel = component.subtext {
|
||||||
subtext = subLabel.update(
|
subtext = subLabel.update(
|
||||||
@ -434,12 +429,11 @@ public final class StarsLabelComponent: CombinedComponent {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let iconSize: CGSize = component.currency == .ton ? CGSize(width: 16.0, height: 16.0) : CGSize(width: 20.0, height: 20.0)
|
let iconSize = CGSize(width: 20.0, height: 20.0)
|
||||||
let icon = icon.update(
|
let icon = icon.update(
|
||||||
component: BundleIconComponent(
|
component: BundleIconComponent(
|
||||||
name: component.currency == .ton ? "Ads/TonBig" : "Premium/Stars/StarMedium",
|
name: component.iconName,
|
||||||
tintColor: component.currency == .ton ? component.textColor : nil,
|
tintColor: component.iconColor
|
||||||
maxSize: iconSize
|
|
||||||
),
|
),
|
||||||
availableSize: iconSize,
|
availableSize: iconSize,
|
||||||
transition: context.transition
|
transition: context.transition
|
||||||
|
@ -217,7 +217,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
var statusText: String?
|
var statusText: String?
|
||||||
var statusIsDestructive = false
|
var statusIsDestructive = false
|
||||||
|
|
||||||
let count: CurrencyAmount
|
let count: StarsAmount
|
||||||
var countIsGeneric = false
|
var countIsGeneric = false
|
||||||
var countOnTop = false
|
var countOnTop = false
|
||||||
var transactionId: String?
|
var transactionId: String?
|
||||||
@ -257,7 +257,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
titleText = strings.Stars_Transaction_Giveaway_Boost_Stars(Int32(stars))
|
titleText = strings.Stars_Transaction_Giveaway_Boost_Stars(Int32(stars))
|
||||||
descriptionText = ""
|
descriptionText = ""
|
||||||
boostsText = strings.Stars_Transaction_Giveaway_Boost_Boosts(boosts)
|
boostsText = strings.Stars_Transaction_Giveaway_Boost_Boosts(boosts)
|
||||||
count = CurrencyAmount(amount: StarsAmount(value: stars, nanos: 0), currency: .stars)
|
count = StarsAmount(value: stars, nanos: 0)
|
||||||
date = boost.date
|
date = boost.date
|
||||||
toPeer = state.peerMap[peerId]
|
toPeer = state.peerMap[peerId]
|
||||||
giveawayMessageId = boost.giveawayMessageId
|
giveawayMessageId = boost.giveawayMessageId
|
||||||
@ -266,7 +266,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
let usdValue = formatTonUsdValue(pricing.amount.value, divide: false, rate: usdRate, dateTimeFormat: environment.dateTimeFormat)
|
let usdValue = formatTonUsdValue(pricing.amount.value, divide: false, rate: usdRate, dateTimeFormat: environment.dateTimeFormat)
|
||||||
titleText = strings.Stars_Transaction_Subscription_Title
|
titleText = strings.Stars_Transaction_Subscription_Title
|
||||||
descriptionText = strings.Stars_Transaction_Subscription_PerMonthUsd(usdValue).string
|
descriptionText = strings.Stars_Transaction_Subscription_PerMonthUsd(usdValue).string
|
||||||
count = CurrencyAmount(amount: pricing.amount, currency: .stars)
|
count = pricing.amount
|
||||||
countOnTop = true
|
countOnTop = true
|
||||||
date = importer.date
|
date = importer.date
|
||||||
toPeer = importer.peer.peer.flatMap(EnginePeer.init)
|
toPeer = importer.peer.peer.flatMap(EnginePeer.init)
|
||||||
@ -288,7 +288,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
photo = subscription.photo
|
photo = subscription.photo
|
||||||
|
|
||||||
descriptionText = ""
|
descriptionText = ""
|
||||||
count = CurrencyAmount(amount: subscription.pricing.amount, currency: .stars)
|
count = subscription.pricing.amount
|
||||||
date = subscription.untilDate
|
date = subscription.untilDate
|
||||||
if let creationDate = (subscription.peer._asPeer() as? TelegramChannel)?.creationDate, creationDate > 0 {
|
if let creationDate = (subscription.peer._asPeer() as? TelegramChannel)?.creationDate, creationDate > 0 {
|
||||||
additionalDate = creationDate
|
additionalDate = creationDate
|
||||||
@ -376,7 +376,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
titleText = gift.title
|
titleText = gift.title
|
||||||
descriptionText = "\(strings.Gift_Unique_Collectible) #\(presentationStringsFormattedNumber(gift.number, dateTimeFormat.groupingSeparator))"
|
descriptionText = "\(strings.Gift_Unique_Collectible) #\(presentationStringsFormattedNumber(gift.number, dateTimeFormat.groupingSeparator))"
|
||||||
}
|
}
|
||||||
count = CurrencyAmount(amount: transaction.count, currency: transaction.currency)
|
count = transaction.count.amount
|
||||||
transactionId = transaction.id
|
transactionId = transaction.id
|
||||||
date = transaction.date
|
date = transaction.date
|
||||||
if case let .peer(peer) = transaction.peer {
|
if case let .peer(peer) = transaction.peer {
|
||||||
@ -395,7 +395,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
} else if let giveawayMessageIdValue = transaction.giveawayMessageId {
|
} else if let giveawayMessageIdValue = transaction.giveawayMessageId {
|
||||||
titleText = strings.Stars_Transaction_Giveaway_Title
|
titleText = strings.Stars_Transaction_Giveaway_Title
|
||||||
descriptionText = ""
|
descriptionText = ""
|
||||||
count = CurrencyAmount(amount: transaction.count, currency: transaction.currency)
|
count = transaction.count.amount
|
||||||
transactionId = transaction.id
|
transactionId = transaction.id
|
||||||
date = transaction.date
|
date = transaction.date
|
||||||
giveawayMessageId = giveawayMessageIdValue
|
giveawayMessageId = giveawayMessageIdValue
|
||||||
@ -406,7 +406,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
} else if let _ = transaction.subscriptionPeriod {
|
} else if let _ = transaction.subscriptionPeriod {
|
||||||
titleText = strings.Stars_Transaction_SubscriptionFee
|
titleText = strings.Stars_Transaction_SubscriptionFee
|
||||||
descriptionText = ""
|
descriptionText = ""
|
||||||
count = CurrencyAmount(amount: transaction.count, currency: transaction.currency)
|
count = transaction.count.amount
|
||||||
transactionId = transaction.id
|
transactionId = transaction.id
|
||||||
date = transaction.date
|
date = transaction.date
|
||||||
if case let .peer(peer) = transaction.peer {
|
if case let .peer(peer) = transaction.peer {
|
||||||
@ -417,7 +417,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
} else if transaction.flags.contains(.isGift) {
|
} else if transaction.flags.contains(.isGift) {
|
||||||
titleText = strings.Stars_Gift_Received_Title
|
titleText = strings.Stars_Gift_Received_Title
|
||||||
descriptionText = strings.Stars_Gift_Received_Text
|
descriptionText = strings.Stars_Gift_Received_Text
|
||||||
count = CurrencyAmount(amount: transaction.count, currency: transaction.currency)
|
count = transaction.count.amount
|
||||||
countOnTop = true
|
countOnTop = true
|
||||||
transactionId = transaction.id
|
transactionId = transaction.id
|
||||||
date = transaction.date
|
date = transaction.date
|
||||||
@ -446,7 +446,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
countOnTop = false
|
countOnTop = false
|
||||||
descriptionText = ""
|
descriptionText = ""
|
||||||
}
|
}
|
||||||
count = CurrencyAmount(amount: transaction.count, currency: transaction.currency)
|
count = transaction.count.amount
|
||||||
transactionId = transaction.id
|
transactionId = transaction.id
|
||||||
date = transaction.date
|
date = transaction.date
|
||||||
transactionPeer = transaction.peer
|
transactionPeer = transaction.peer
|
||||||
@ -457,7 +457,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
titleText = strings.Stars_Transaction_Reaction_Title
|
titleText = strings.Stars_Transaction_Reaction_Title
|
||||||
descriptionText = ""
|
descriptionText = ""
|
||||||
messageId = transaction.paidMessageId
|
messageId = transaction.paidMessageId
|
||||||
count = CurrencyAmount(amount: transaction.count, currency: transaction.currency)
|
count = transaction.count.amount
|
||||||
transactionId = transaction.id
|
transactionId = transaction.id
|
||||||
date = transaction.date
|
date = transaction.date
|
||||||
if case let .peer(peer) = transaction.peer {
|
if case let .peer(peer) = transaction.peer {
|
||||||
@ -490,7 +490,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
via = strings.Stars_Transaction_PremiumBotTopUp_Subtitle
|
via = strings.Stars_Transaction_PremiumBotTopUp_Subtitle
|
||||||
case .fragment:
|
case .fragment:
|
||||||
if parentPeer.id == component.context.account.peerId {
|
if parentPeer.id == component.context.account.peerId {
|
||||||
if (transaction.count.value < 0 && !transaction.flags.contains(.isRefund)) || (transaction.count.value > 0 && transaction.flags.contains(.isRefund)) {
|
if (transaction.count.amount.value < 0 && !transaction.flags.contains(.isRefund)) || (transaction.count.amount.value > 0 && transaction.flags.contains(.isRefund)) {
|
||||||
titleText = strings.Stars_Transaction_FragmentWithdrawal_Title
|
titleText = strings.Stars_Transaction_FragmentWithdrawal_Title
|
||||||
via = strings.Stars_Transaction_FragmentWithdrawal_Subtitle
|
via = strings.Stars_Transaction_FragmentWithdrawal_Subtitle
|
||||||
} else {
|
} else {
|
||||||
@ -545,7 +545,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
|
|
||||||
messageId = transaction.paidMessageId
|
messageId = transaction.paidMessageId
|
||||||
|
|
||||||
count = CurrencyAmount(amount: transaction.count, currency: transaction.currency)
|
count = transaction.count.amount
|
||||||
transactionId = transaction.id
|
transactionId = transaction.id
|
||||||
date = transaction.date
|
date = transaction.date
|
||||||
if case let .peer(peer) = transaction.peer {
|
if case let .peer(peer) = transaction.peer {
|
||||||
@ -564,7 +564,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
case let .receipt(receipt):
|
case let .receipt(receipt):
|
||||||
titleText = receipt.invoiceMedia.title
|
titleText = receipt.invoiceMedia.title
|
||||||
descriptionText = receipt.invoiceMedia.description
|
descriptionText = receipt.invoiceMedia.description
|
||||||
count = CurrencyAmount(amount: StarsAmount(value: (receipt.invoice.prices.first?.amount ?? receipt.invoiceMedia.totalAmount) * -1, nanos: 0), currency: .stars)
|
count = StarsAmount(value: (receipt.invoice.prices.first?.amount ?? receipt.invoiceMedia.totalAmount) * -1, nanos: 0)
|
||||||
transactionId = receipt.transactionId
|
transactionId = receipt.transactionId
|
||||||
date = receipt.date
|
date = receipt.date
|
||||||
if let peer = state.peerMap[receipt.botPaymentId] {
|
if let peer = state.peerMap[receipt.botPaymentId] {
|
||||||
@ -581,7 +581,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
if case let .giftStars(_, _, countValue, _, _, _) = action.action {
|
if case let .giftStars(_, _, countValue, _, _, _) = action.action {
|
||||||
titleText = incoming ? strings.Stars_Gift_Received_Title : strings.Stars_Gift_Sent_Title
|
titleText = incoming ? strings.Stars_Gift_Received_Title : strings.Stars_Gift_Sent_Title
|
||||||
|
|
||||||
count = CurrencyAmount(amount: StarsAmount(value: countValue, nanos: 0), currency: .stars)
|
count = StarsAmount(value: countValue, nanos: 0)
|
||||||
if !incoming {
|
if !incoming {
|
||||||
countIsGeneric = true
|
countIsGeneric = true
|
||||||
}
|
}
|
||||||
@ -595,7 +595,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
} else if case let .prizeStars(countValue, _, boostPeerId, _, giveawayMessageIdValue) = action.action {
|
} else if case let .prizeStars(countValue, _, boostPeerId, _, giveawayMessageIdValue) = action.action {
|
||||||
titleText = strings.Stars_Transaction_Giveaway_Title
|
titleText = strings.Stars_Transaction_Giveaway_Title
|
||||||
|
|
||||||
count = CurrencyAmount(amount: StarsAmount(value: countValue, nanos: 0), currency: .stars)
|
count = StarsAmount(value: countValue, nanos: 0)
|
||||||
countOnTop = true
|
countOnTop = true
|
||||||
transactionId = nil
|
transactionId = nil
|
||||||
giveawayMessageId = giveawayMessageIdValue
|
giveawayMessageId = giveawayMessageIdValue
|
||||||
@ -648,14 +648,8 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
headerTextColor = theme.actionSheet.primaryTextColor
|
headerTextColor = theme.actionSheet.primaryTextColor
|
||||||
}
|
}
|
||||||
|
|
||||||
let absCount = StarsAmount(value: abs(count.amount.value), nanos: abs(count.amount.nanos))
|
let absCount = StarsAmount(value: abs(count.value), nanos: abs(count.nanos))
|
||||||
let formattedAmount: String
|
let formattedAmount = formatStarsAmountText(absCount, dateTimeFormat: dateTimeFormat)
|
||||||
switch count.currency {
|
|
||||||
case .stars:
|
|
||||||
formattedAmount = formatStarsAmountText(absCount, dateTimeFormat: dateTimeFormat)
|
|
||||||
case .ton:
|
|
||||||
formattedAmount = formatTonAmountText(absCount.value, dateTimeFormat: dateTimeFormat)
|
|
||||||
}
|
|
||||||
let countColor: UIColor
|
let countColor: UIColor
|
||||||
var countFont: UIFont = isSubscription || isSubscriber ? Font.regular(17.0) : Font.semibold(17.0)
|
var countFont: UIFont = isSubscription || isSubscriber ? Font.regular(17.0) : Font.semibold(17.0)
|
||||||
var countBackgroundColor: UIColor?
|
var countBackgroundColor: UIColor?
|
||||||
@ -670,7 +664,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
} else if countIsGeneric {
|
} else if countIsGeneric {
|
||||||
amountText = "\(formattedAmount)"
|
amountText = "\(formattedAmount)"
|
||||||
countColor = theme.list.itemPrimaryTextColor
|
countColor = theme.list.itemPrimaryTextColor
|
||||||
} else if count.amount < StarsAmount.zero {
|
} else if count < StarsAmount.zero {
|
||||||
amountText = "- \(formattedAmount)"
|
amountText = "- \(formattedAmount)"
|
||||||
if case .unique = giftAnimationSubject {
|
if case .unique = giftAnimationSubject {
|
||||||
countColor = .white
|
countColor = .white
|
||||||
@ -712,9 +706,9 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
imageSubject = .gift(premiumGiftMonths)
|
imageSubject = .gift(premiumGiftMonths)
|
||||||
} else if isGift {
|
} else if isGift {
|
||||||
var value: Int32 = 3
|
var value: Int32 = 3
|
||||||
if count.amount.value <= 1000 {
|
if count.value <= 1000 {
|
||||||
value = 3
|
value = 3
|
||||||
} else if count.amount.value < 2500 {
|
} else if count.value < 2500 {
|
||||||
value = 6
|
value = 6
|
||||||
} else {
|
} else {
|
||||||
value = 12
|
value = 12
|
||||||
@ -732,9 +726,9 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
imageSubject = .none
|
imageSubject = .none
|
||||||
}
|
}
|
||||||
if isSubscription || isSubscriber || isSubscriptionFee || giveawayMessageId != nil {
|
if isSubscription || isSubscriber || isSubscriptionFee || giveawayMessageId != nil {
|
||||||
imageIcon = count.currency == .ton ? .ton : .star
|
imageIcon = .star
|
||||||
} else {
|
} else {
|
||||||
imageIcon = count.currency == .ton ? .ton : nil
|
imageIcon = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if isSubscription && "".isEmpty {
|
if isSubscription && "".isEmpty {
|
||||||
@ -817,26 +811,10 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
transition: .immediate
|
transition: .immediate
|
||||||
)
|
)
|
||||||
|
|
||||||
let amountStarIconName: String
|
|
||||||
var amountStarTintColor: UIColor?
|
|
||||||
var amountStarMaxSize: CGSize?
|
|
||||||
var amountOffset = CGPoint()
|
|
||||||
if boostsText != nil {
|
|
||||||
amountStarIconName = "Premium/BoostButtonIcon"
|
|
||||||
} else if case .ton = count.currency {
|
|
||||||
amountStarIconName = "Ads/TonBig"
|
|
||||||
amountStarTintColor = countColor
|
|
||||||
amountStarMaxSize = CGSize(width: 14.0, height: 14.0)
|
|
||||||
amountOffset.y += 3.0
|
|
||||||
} else {
|
|
||||||
amountStarIconName = "Premium/Stars/StarMedium"
|
|
||||||
}
|
|
||||||
|
|
||||||
let amountStar = amountStar.update(
|
let amountStar = amountStar.update(
|
||||||
component: BundleIconComponent(
|
component: BundleIconComponent(
|
||||||
name: amountStarIconName,
|
name: boostsText != nil ? "Premium/BoostButtonIcon" : "Premium/Stars/StarMedium",
|
||||||
tintColor: amountStarTintColor,
|
tintColor: nil
|
||||||
maxSize: amountStarMaxSize
|
|
||||||
),
|
),
|
||||||
availableSize: context.availableSize,
|
availableSize: context.availableSize,
|
||||||
transition: .immediate
|
transition: .immediate
|
||||||
@ -858,7 +836,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
))
|
))
|
||||||
} else if case .unique = giftAnimationSubject {
|
} else if case .unique = giftAnimationSubject {
|
||||||
let reason: String
|
let reason: String
|
||||||
if count.amount < StarsAmount.zero, case let .transaction(transaction, _) = subject {
|
if count < StarsAmount.zero, case let .transaction(transaction, _) = subject {
|
||||||
if transaction.flags.contains(.isStarGiftResale) {
|
if transaction.flags.contains(.isStarGiftResale) {
|
||||||
reason = strings.Stars_Transaction_GiftPurchase
|
reason = strings.Stars_Transaction_GiftPurchase
|
||||||
} else {
|
} else {
|
||||||
@ -914,7 +892,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
} else if isSubscriber {
|
} else if isSubscriber {
|
||||||
title = strings.Stars_Transaction_Subscription_Subscriber
|
title = strings.Stars_Transaction_Subscription_Subscriber
|
||||||
} else {
|
} else {
|
||||||
title = count.amount < StarsAmount.zero || countIsGeneric ? strings.Stars_Transaction_To : strings.Stars_Transaction_From
|
title = count < StarsAmount.zero || countIsGeneric ? strings.Stars_Transaction_To : strings.Stars_Transaction_From
|
||||||
}
|
}
|
||||||
|
|
||||||
let toComponent: AnyComponent<Empty>
|
let toComponent: AnyComponent<Empty>
|
||||||
@ -1019,7 +997,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
id: "prize",
|
id: "prize",
|
||||||
title: strings.Stars_Transaction_Giveaway_Prize,
|
title: strings.Stars_Transaction_Giveaway_Prize,
|
||||||
component: AnyComponent(
|
component: AnyComponent(
|
||||||
MultilineTextComponent(text: .plain(NSAttributedString(string: strings.Stars_Transaction_Giveaway_Stars(Int32(count.amount.value)), font: tableFont, textColor: tableTextColor)))
|
MultilineTextComponent(text: .plain(NSAttributedString(string: strings.Stars_Transaction_Giveaway_Stars(Int32(count.value)), font: tableFont, textColor: tableTextColor)))
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
||||||
@ -1195,7 +1173,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
if let starrefCommissionPermille = transaction.starrefCommissionPermille, transaction.starrefPeerId != nil {
|
if let starrefCommissionPermille = transaction.starrefCommissionPermille, transaction.starrefPeerId != nil {
|
||||||
if transaction.flags.contains(.isPaidMessage) || transaction.flags.contains(.isStarGiftResale) {
|
if transaction.flags.contains(.isPaidMessage) || transaction.flags.contains(.isStarGiftResale) {
|
||||||
var totalStars = transaction.count
|
var totalStars = transaction.count.amount
|
||||||
if let starrefCount = transaction.starrefAmount {
|
if let starrefCount = transaction.starrefAmount {
|
||||||
totalStars = totalStars + starrefCount
|
totalStars = totalStars + starrefCount
|
||||||
}
|
}
|
||||||
@ -1521,7 +1499,6 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
amountLabelOffsetY = 2.0
|
amountLabelOffsetY = 2.0
|
||||||
amountStarOffsetY = 5.0
|
amountStarOffsetY = 5.0
|
||||||
}
|
}
|
||||||
amountStarOffsetY += amountOffset.y
|
|
||||||
|
|
||||||
context.add(amount
|
context.add(amount
|
||||||
.position(CGPoint(x: amountLabelOriginX, y: amountOrigin + amount.size.height / 2.0 + amountLabelOffsetY))
|
.position(CGPoint(x: amountLabelOriginX, y: amountOrigin + amount.size.height / 2.0 + amountLabelOffsetY))
|
||||||
|
@ -50,6 +50,8 @@ swift_library(
|
|||||||
"//submodules/TelegramUI/Components/LottieComponent",
|
"//submodules/TelegramUI/Components/LottieComponent",
|
||||||
"//submodules/TelegramUI/Components/LottieComponentResourceContent",
|
"//submodules/TelegramUI/Components/LottieComponentResourceContent",
|
||||||
"//submodules/TelegramUI/Components/Gifts/GiftAnimationComponent",
|
"//submodules/TelegramUI/Components/Gifts/GiftAnimationComponent",
|
||||||
|
"//submodules/TelegramUI/Components/Premium/PremiumCoinComponent",
|
||||||
|
"//submodules/TelegramUI/Components/Premium/PremiumDiamondComponent",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
@ -16,8 +16,8 @@ final class StarsBalanceComponent: Component {
|
|||||||
let theme: PresentationTheme
|
let theme: PresentationTheme
|
||||||
let strings: PresentationStrings
|
let strings: PresentationStrings
|
||||||
let dateTimeFormat: PresentationDateTimeFormat
|
let dateTimeFormat: PresentationDateTimeFormat
|
||||||
let currency: CurrencyAmount.Currency
|
|
||||||
let count: StarsAmount
|
let count: StarsAmount
|
||||||
|
let isTon: Bool
|
||||||
let rate: Double?
|
let rate: Double?
|
||||||
let actionTitle: String
|
let actionTitle: String
|
||||||
let actionAvailable: Bool
|
let actionAvailable: Bool
|
||||||
@ -35,8 +35,8 @@ final class StarsBalanceComponent: Component {
|
|||||||
theme: PresentationTheme,
|
theme: PresentationTheme,
|
||||||
strings: PresentationStrings,
|
strings: PresentationStrings,
|
||||||
dateTimeFormat: PresentationDateTimeFormat,
|
dateTimeFormat: PresentationDateTimeFormat,
|
||||||
currency: CurrencyAmount.Currency,
|
|
||||||
count: StarsAmount,
|
count: StarsAmount,
|
||||||
|
isTon: Bool = false,
|
||||||
rate: Double?,
|
rate: Double?,
|
||||||
actionTitle: String,
|
actionTitle: String,
|
||||||
actionAvailable: Bool,
|
actionAvailable: Bool,
|
||||||
@ -53,8 +53,8 @@ final class StarsBalanceComponent: Component {
|
|||||||
self.theme = theme
|
self.theme = theme
|
||||||
self.strings = strings
|
self.strings = strings
|
||||||
self.dateTimeFormat = dateTimeFormat
|
self.dateTimeFormat = dateTimeFormat
|
||||||
self.currency = currency
|
|
||||||
self.count = count
|
self.count = count
|
||||||
|
self.isTon = isTon
|
||||||
self.rate = rate
|
self.rate = rate
|
||||||
self.actionTitle = actionTitle
|
self.actionTitle = actionTitle
|
||||||
self.actionAvailable = actionAvailable
|
self.actionAvailable = actionAvailable
|
||||||
@ -100,6 +100,9 @@ final class StarsBalanceComponent: Component {
|
|||||||
if lhs.count != rhs.count {
|
if lhs.count != rhs.count {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.isTon != rhs.isTon {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if lhs.rate != rhs.rate {
|
if lhs.rate != rhs.rate {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -123,8 +126,6 @@ final class StarsBalanceComponent: Component {
|
|||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
|
||||||
self.icon.image = UIImage(bundleImageName: "Premium/Stars/BalanceStar")
|
|
||||||
|
|
||||||
self.addSubview(self.icon)
|
self.addSubview(self.icon)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,6 +134,14 @@ final class StarsBalanceComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func update(component: StarsBalanceComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
func update(component: StarsBalanceComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||||
|
if self.component == nil {
|
||||||
|
if component.isTon {
|
||||||
|
self.icon.image = generateTintedImage(image: UIImage(bundleImageName: "Ads/TonBig"), color: component.theme.list.itemAccentColor)
|
||||||
|
} else {
|
||||||
|
self.icon.image = UIImage(bundleImageName: "Premium/Stars/BalanceStar")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.component = component
|
self.component = component
|
||||||
self.state = state
|
self.state = state
|
||||||
|
|
||||||
@ -168,11 +177,10 @@ final class StarsBalanceComponent: Component {
|
|||||||
var contentHeight: CGFloat = sideInset
|
var contentHeight: CGFloat = sideInset
|
||||||
|
|
||||||
let formattedLabel: String
|
let formattedLabel: String
|
||||||
switch component.currency {
|
if component.isTon {
|
||||||
case .stars:
|
|
||||||
formattedLabel = formatStarsAmountText(component.count, dateTimeFormat: component.dateTimeFormat)
|
|
||||||
case .ton:
|
|
||||||
formattedLabel = formatTonAmountText(component.count.value, dateTimeFormat: component.dateTimeFormat)
|
formattedLabel = formatTonAmountText(component.count.value, dateTimeFormat: component.dateTimeFormat)
|
||||||
|
} else {
|
||||||
|
formattedLabel = formatStarsAmountText(component.count, dateTimeFormat: component.dateTimeFormat)
|
||||||
}
|
}
|
||||||
let labelFont: UIFont
|
let labelFont: UIFont
|
||||||
if formattedLabel.contains(component.dateTimeFormat.decimalSeparator) {
|
if formattedLabel.contains(component.dateTimeFormat.decimalSeparator) {
|
||||||
@ -197,13 +205,13 @@ final class StarsBalanceComponent: Component {
|
|||||||
self.addSubview(titleView)
|
self.addSubview(titleView)
|
||||||
}
|
}
|
||||||
if let icon = self.icon.image {
|
if let icon = self.icon.image {
|
||||||
let spacing: CGFloat = 3.0
|
let spacing: CGFloat = 4.0
|
||||||
let totalWidth = titleSize.width + icon.size.width + spacing
|
let totalWidth = titleSize.width + icon.size.width + spacing
|
||||||
let origin = floorToScreenPixels((availableSize.width - totalWidth) / 2.0)
|
let origin = floorToScreenPixels((availableSize.width - totalWidth) / 2.0)
|
||||||
let titleFrame = CGRect(origin: CGPoint(x: origin + icon.size.width + spacing, y: contentHeight - 3.0), size: titleSize)
|
let titleFrame = CGRect(origin: CGPoint(x: origin + icon.size.width + spacing, y: contentHeight - 3.0), size: titleSize)
|
||||||
titleView.frame = titleFrame
|
titleView.frame = titleFrame
|
||||||
|
|
||||||
self.icon.frame = CGRect(origin: CGPoint(x: origin, y: contentHeight), size: icon.size)
|
self.icon.frame = CGRect(origin: CGPoint(x: origin, y: floorToScreenPixels(titleFrame.midY - icon.size.height / 2.0)), size: icon.size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
contentHeight += titleSize.height
|
contentHeight += titleSize.height
|
||||||
|
@ -21,7 +21,7 @@ import TelegramStringFormatting
|
|||||||
|
|
||||||
private extension StarsContext.State.Transaction {
|
private extension StarsContext.State.Transaction {
|
||||||
var extendedId: String {
|
var extendedId: String {
|
||||||
if self.count > StarsAmount.zero {
|
if self.count.amount > StarsAmount.zero {
|
||||||
return "\(id)_in"
|
return "\(id)_in"
|
||||||
} else {
|
} else {
|
||||||
return "\(id)_out"
|
return "\(id)_out"
|
||||||
@ -320,7 +320,7 @@ final class StarsTransactionsListPanelComponent: Component {
|
|||||||
switch starGift {
|
switch starGift {
|
||||||
case let .generic(gift):
|
case let .generic(gift):
|
||||||
itemFile = gift.file
|
itemFile = gift.file
|
||||||
itemSubtitle = item.count > StarsAmount.zero ? environment.strings.Stars_Intro_Transaction_ConvertedGift : environment.strings.Stars_Intro_Transaction_Gift
|
itemSubtitle = item.count.amount > StarsAmount.zero ? environment.strings.Stars_Intro_Transaction_ConvertedGift : environment.strings.Stars_Intro_Transaction_Gift
|
||||||
case let .unique(gift):
|
case let .unique(gift):
|
||||||
for attribute in gift.attributes {
|
for attribute in gift.attributes {
|
||||||
if case let .model(_, file, _) = attribute {
|
if case let .model(_, file, _) = attribute {
|
||||||
@ -328,7 +328,7 @@ final class StarsTransactionsListPanelComponent: Component {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if item.count > StarsAmount.zero {
|
if item.count.amount > StarsAmount.zero {
|
||||||
itemSubtitle = environment.strings.Stars_Intro_Transaction_GiftSale
|
itemSubtitle = environment.strings.Stars_Intro_Transaction_GiftSale
|
||||||
} else {
|
} else {
|
||||||
if item.flags.contains(.isStarGiftResale) {
|
if item.flags.contains(.isStarGiftResale) {
|
||||||
@ -373,7 +373,7 @@ final class StarsTransactionsListPanelComponent: Component {
|
|||||||
itemSubtitle = environment.strings.Stars_Intro_Transaction_Gift_Title
|
itemSubtitle = environment.strings.Stars_Intro_Transaction_Gift_Title
|
||||||
itemPeer = .fragment
|
itemPeer = .fragment
|
||||||
} else {
|
} else {
|
||||||
if (item.count.value < 0 && !item.flags.contains(.isRefund)) || (item.count.value > 0 && item.flags.contains(.isRefund)) {
|
if (item.count.amount.value < 0 && !item.flags.contains(.isRefund)) || (item.count.amount.value > 0 && item.flags.contains(.isRefund)) {
|
||||||
itemTitle = environment.strings.Stars_Intro_Transaction_FragmentWithdrawal_Title
|
itemTitle = environment.strings.Stars_Intro_Transaction_FragmentWithdrawal_Title
|
||||||
itemSubtitle = environment.strings.Stars_Intro_Transaction_FragmentWithdrawal_Subtitle
|
itemSubtitle = environment.strings.Stars_Intro_Transaction_FragmentWithdrawal_Subtitle
|
||||||
} else {
|
} else {
|
||||||
@ -382,7 +382,7 @@ final class StarsTransactionsListPanelComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if item.count > StarsAmount.zero && !item.flags.contains(.isRefund) {
|
if item.count.amount > StarsAmount.zero && !item.flags.contains(.isRefund) {
|
||||||
itemTitle = environment.strings.Stars_Intro_Transaction_FragmentTopUp_Title
|
itemTitle = environment.strings.Stars_Intro_Transaction_FragmentTopUp_Title
|
||||||
itemSubtitle = environment.strings.Stars_Intro_Transaction_FragmentTopUp_Subtitle
|
itemSubtitle = environment.strings.Stars_Intro_Transaction_FragmentTopUp_Subtitle
|
||||||
} else {
|
} else {
|
||||||
@ -409,19 +409,24 @@ final class StarsTransactionsListPanelComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let itemLabel: NSAttributedString
|
let itemLabel: NSAttributedString
|
||||||
let formattedLabel: String
|
let formattedLabel = formatCurrencyAmountText(item.count, dateTimeFormat: environment.dateTimeFormat, showPlus: true)
|
||||||
switch item.currency {
|
|
||||||
case .stars:
|
|
||||||
formattedLabel = formatStarsAmountText(item.count, dateTimeFormat: environment.dateTimeFormat, showPlus: true)
|
|
||||||
case .ton:
|
|
||||||
formattedLabel = formatTonAmountText(item.count.value, dateTimeFormat: environment.dateTimeFormat, showPlus: true)
|
|
||||||
}
|
|
||||||
|
|
||||||
let smallLabelFont = Font.with(size: floor(fontBaseDisplaySize / 17.0 * 13.0))
|
let smallLabelFont = Font.with(size: floor(fontBaseDisplaySize / 17.0 * 13.0))
|
||||||
let labelFont = Font.medium(fontBaseDisplaySize)
|
let labelFont = Font.medium(fontBaseDisplaySize)
|
||||||
let labelColor = formattedLabel.hasPrefix("-") ? environment.theme.list.itemDestructiveColor : environment.theme.list.itemDisclosureActions.constructive.fillColor
|
let labelColor = formattedLabel.hasPrefix("-") ? environment.theme.list.itemDestructiveColor : environment.theme.list.itemDisclosureActions.constructive.fillColor
|
||||||
itemLabel = tonAmountAttributedString(formattedLabel, integralFont: labelFont, fractionalFont: smallLabelFont, color: labelColor, decimalSeparator: environment.dateTimeFormat.decimalSeparator)
|
itemLabel = tonAmountAttributedString(formattedLabel, integralFont: labelFont, fractionalFont: smallLabelFont, color: labelColor, decimalSeparator: environment.dateTimeFormat.decimalSeparator)
|
||||||
|
|
||||||
|
let itemIconName: String
|
||||||
|
let itemIconColor: UIColor?
|
||||||
|
switch item.count.currency {
|
||||||
|
case .stars:
|
||||||
|
itemIconName = "Premium/Stars/StarMedium"
|
||||||
|
itemIconColor = nil
|
||||||
|
case .ton:
|
||||||
|
itemIconName = "Ads/TonAbout"
|
||||||
|
itemIconColor = labelColor
|
||||||
|
}
|
||||||
|
|
||||||
var itemDateColor = environment.theme.list.itemSecondaryTextColor
|
var itemDateColor = environment.theme.list.itemSecondaryTextColor
|
||||||
itemDate = stringForMediumCompactDate(timestamp: item.date, strings: environment.strings, dateTimeFormat: environment.dateTimeFormat)
|
itemDate = stringForMediumCompactDate(timestamp: item.date, strings: environment.strings, dateTimeFormat: environment.dateTimeFormat)
|
||||||
if item.flags.contains(.isRefund) {
|
if item.flags.contains(.isRefund) {
|
||||||
@ -502,7 +507,7 @@ final class StarsTransactionsListPanelComponent: Component {
|
|||||||
contentInsets: UIEdgeInsets(top: 9.0, left: environment.containerInsets.left, bottom: 8.0, right: environment.containerInsets.right),
|
contentInsets: UIEdgeInsets(top: 9.0, left: environment.containerInsets.left, bottom: 8.0, right: environment.containerInsets.right),
|
||||||
leftIcon: .custom(AnyComponentWithIdentity(id: "avatar", component: AnyComponent(StarsAvatarComponent(context: component.context, theme: environment.theme, peer: itemPeer, photo: item.photo, media: item.media, uniqueGift: uniqueGift, backgroundColor: environment.theme.list.plainBackgroundColor))), false),
|
leftIcon: .custom(AnyComponentWithIdentity(id: "avatar", component: AnyComponent(StarsAvatarComponent(context: component.context, theme: environment.theme, peer: itemPeer, photo: item.photo, media: item.media, uniqueGift: uniqueGift, backgroundColor: environment.theme.list.plainBackgroundColor))), false),
|
||||||
icon: nil,
|
icon: nil,
|
||||||
accessory: .custom(ListActionItemComponent.CustomAccessory(component: AnyComponentWithIdentity(id: "label", component: AnyComponent(StarsLabelComponent(theme: environment.theme, currency: item.currency, textColor: labelColor, text: itemLabel))), insets: UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 16.0))),
|
accessory: .custom(ListActionItemComponent.CustomAccessory(component: AnyComponentWithIdentity(id: "label", component: AnyComponent(StarsLabelComponent(text: itemLabel, iconName: itemIconName, iconColor: itemIconColor))), insets: UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 16.0))),
|
||||||
action: { [weak self] _ in
|
action: { [weak self] _ in
|
||||||
guard let self, let component = self.component else {
|
guard let self, let component = self.component else {
|
||||||
return
|
return
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -29,6 +29,11 @@ func openWebAppImpl(
|
|||||||
skipTermsOfService: Bool,
|
skipTermsOfService: Bool,
|
||||||
payload: String?
|
payload: String?
|
||||||
) {
|
) {
|
||||||
|
if context.isFrozen {
|
||||||
|
parentController.push(context.sharedContext.makeAccountFreezeInfoScreen(context: context))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let presentationData: PresentationData
|
let presentationData: PresentationData
|
||||||
if let parentController = parentController as? ChatControllerImpl {
|
if let parentController = parentController as? ChatControllerImpl {
|
||||||
presentationData = parentController.presentationData
|
presentationData = parentController.presentationData
|
||||||
|
@ -3687,6 +3687,10 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
return StarsTransactionsScreen(context: context, starsContext: starsContext)
|
return StarsTransactionsScreen(context: context, starsContext: starsContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func makeTonTransactionsScreen(context: AccountContext, tonContext: StarsContext) -> ViewController {
|
||||||
|
return TonTransactionsScreen(context: context, tonContext: tonContext)
|
||||||
|
}
|
||||||
|
|
||||||
public func makeStarsPurchaseScreen(context: AccountContext, starsContext: StarsContext, options: [Any], purpose: StarsPurchasePurpose, completion: @escaping (Int64) -> Void) -> ViewController {
|
public func makeStarsPurchaseScreen(context: AccountContext, starsContext: StarsContext, options: [Any], purpose: StarsPurchasePurpose, completion: @escaping (Int64) -> Void) -> ViewController {
|
||||||
return StarsPurchaseScreen(context: context, starsContext: starsContext, options: options, purpose: purpose, completion: completion)
|
return StarsPurchaseScreen(context: context, starsContext: starsContext, options: options, purpose: purpose, completion: completion)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user