mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-25 17:43:18 +00:00
Stars subscriptions
This commit is contained in:
parent
5145337d87
commit
cf28e1b651
@ -12674,3 +12674,5 @@ Sorry for the inconvenience.";
|
||||
"MediaPicker.CreateSticker" = "Create a sticker from a photo";
|
||||
|
||||
"Stickers.CreateSticker" = "Create\nSticker";
|
||||
|
||||
"InviteLink.CreateNewInfo" = "You can create additional invite links that are limited by time, number of users, or require a paid subscription.";
|
||||
|
||||
@ -351,7 +351,7 @@ private func inviteLinkListControllerEntries(presentationData: PresentationData,
|
||||
}
|
||||
}
|
||||
if admin == nil {
|
||||
entries.append(.linksInfo(presentationData.theme, presentationData.strings.InviteLink_CreateInfo))
|
||||
entries.append(.linksInfo(presentationData.theme, presentationData.strings.InviteLink_CreateNewInfo))
|
||||
}
|
||||
|
||||
if let revokedInvites = revokedInvites {
|
||||
|
||||
@ -798,7 +798,13 @@ public final class InviteLinkViewController: ViewController {
|
||||
if let pricing = invite.pricing {
|
||||
//TODO:localize
|
||||
entries.append(.subscriptionHeader(presentationData.theme, "SUBSCRIPTION FEE"))
|
||||
entries.append(.subscriptionPricing(presentationData.theme, "⭐️\(pricing.amount) / month x \(state.count)", "You get approximately $\(Float(pricing.amount * Int64(state.count)) * 0.01) monthly"))
|
||||
var title = "⭐️\(pricing.amount) / month"
|
||||
var subtitle = "No one joined yet"
|
||||
if state.count > 0 {
|
||||
title += " x \(state.count)"
|
||||
subtitle = "You get approximately $\(Float(pricing.amount * Int64(state.count)) * 0.01) monthly"
|
||||
}
|
||||
entries.append(.subscriptionPricing(presentationData.theme, title, subtitle))
|
||||
}
|
||||
|
||||
entries.append(.creatorHeader(presentationData.theme, presentationData.strings.InviteLink_CreatedBy.uppercased()))
|
||||
|
||||
@ -238,9 +238,13 @@ final class StarsTransactionItemNode: ListViewItemNode, ItemListItemNode {
|
||||
itemTitle = title
|
||||
itemSubtitle = peer.displayTitle(strings: item.presentationData.strings, displayOrder: .firstLast)
|
||||
} else {
|
||||
itemTitle = peer.displayTitle(strings: item.presentationData.strings, displayOrder: .firstLast)
|
||||
if let _ = item.transaction.subscriptionPeriod {
|
||||
itemSubtitle = "Monthly subscription fee"
|
||||
} else {
|
||||
itemSubtitle = nil
|
||||
}
|
||||
itemTitle = peer.displayTitle(strings: item.presentationData.strings, displayOrder: .firstLast)
|
||||
}
|
||||
case .appStore:
|
||||
itemTitle = item.presentationData.strings.Stars_Intro_Transaction_AppleTopUp_Title
|
||||
itemSubtitle = item.presentationData.strings.Stars_Intro_Transaction_AppleTopUp_Subtitle
|
||||
|
||||
@ -297,11 +297,16 @@ public final class StarsImageComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
public enum Icon {
|
||||
case star
|
||||
}
|
||||
|
||||
public let context: AccountContext
|
||||
public let subject: Subject
|
||||
public let theme: PresentationTheme
|
||||
public let diameter: CGFloat
|
||||
public let backgroundColor: UIColor
|
||||
public let icon: Icon?
|
||||
public let action: ((@escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void)?
|
||||
|
||||
public init(
|
||||
@ -310,6 +315,7 @@ public final class StarsImageComponent: Component {
|
||||
theme: PresentationTheme,
|
||||
diameter: CGFloat,
|
||||
backgroundColor: UIColor,
|
||||
icon: Icon? = nil,
|
||||
action: ((@escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void)? = nil
|
||||
) {
|
||||
self.context = context
|
||||
@ -317,6 +323,7 @@ public final class StarsImageComponent: Component {
|
||||
self.theme = theme
|
||||
self.diameter = diameter
|
||||
self.backgroundColor = backgroundColor
|
||||
self.icon = icon
|
||||
self.action = action
|
||||
}
|
||||
|
||||
@ -336,6 +343,9 @@ public final class StarsImageComponent: Component {
|
||||
if lhs.backgroundColor != rhs.backgroundColor {
|
||||
return false
|
||||
}
|
||||
if lhs.icon != rhs.icon {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@ -353,6 +363,8 @@ public final class StarsImageComponent: Component {
|
||||
private var avatarNode: ImageNode?
|
||||
private var iconBackgroundView: UIImageView?
|
||||
private var iconView: UIImageView?
|
||||
private var smallIconOutlineView: UIImageView?
|
||||
private var smallIconView: UIImageView?
|
||||
private var dustNode: MediaDustNode?
|
||||
private var button: UIControl?
|
||||
|
||||
@ -814,6 +826,36 @@ public final class StarsImageComponent: Component {
|
||||
animationNode.updateLayout(size: animationFrame.size)
|
||||
}
|
||||
|
||||
if let _ = component.icon {
|
||||
let smallIconView: UIImageView
|
||||
let smallIconOutlineView: UIImageView
|
||||
if let current = self.smallIconView, let currentOutline = self.smallIconOutlineView {
|
||||
smallIconView = current
|
||||
smallIconOutlineView = currentOutline
|
||||
} else {
|
||||
smallIconOutlineView = UIImageView()
|
||||
containerNode.view.addSubview(smallIconOutlineView)
|
||||
|
||||
smallIconView = UIImageView()
|
||||
containerNode.view.addSubview(smallIconView)
|
||||
}
|
||||
|
||||
smallIconView.image = UIImage(bundleImageName: "Premium/Stars/BalanceStar")
|
||||
if smallIconOutlineView.image == nil {
|
||||
smallIconOutlineView.image = generateTintedImage(image: smallIconView.image, color: .white)?.withRenderingMode(.alwaysTemplate)
|
||||
}
|
||||
smallIconOutlineView.tintColor = component.backgroundColor
|
||||
|
||||
if let icon = smallIconView.image {
|
||||
let smallIconFrame = CGRect(origin: CGPoint(x: imageFrame.maxX - icon.size.width - 5.0, y: imageFrame.maxY - icon.size.height - 5.0), size: icon.size)
|
||||
smallIconView.frame = smallIconFrame
|
||||
smallIconOutlineView.frame = smallIconFrame.insetBy(dx: -3.0 + UIScreenPixel, dy: -3.0 + UIScreenPixel)
|
||||
}
|
||||
} else if let smallIconView = self.smallIconView {
|
||||
self.smallIconView = nil
|
||||
smallIconView.removeFromSuperview()
|
||||
}
|
||||
|
||||
if let _ = component.action {
|
||||
if self.button == nil {
|
||||
let button = UIControl(frame: imageFrame)
|
||||
|
||||
@ -97,6 +97,8 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
peerIds.append(receipt.botPaymentId)
|
||||
case let .gift(message):
|
||||
peerIds.append(message.id.peerId)
|
||||
case let .subscription(subscription):
|
||||
peerIds.append(subscription.peer.id)
|
||||
}
|
||||
|
||||
self.disposable = (context.engine.data.get(
|
||||
@ -195,17 +197,30 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
let messageId: EngineMessage.Id?
|
||||
let toPeer: EnginePeer?
|
||||
let transactionPeer: StarsContext.State.Transaction.Peer?
|
||||
let media: [AnyMediaReference]
|
||||
let photo: TelegramMediaWebFile?
|
||||
let isRefund: Bool
|
||||
let isGift: Bool
|
||||
var media: [AnyMediaReference] = []
|
||||
var photo: TelegramMediaWebFile?
|
||||
var isRefund = false
|
||||
var isGift = false
|
||||
var isSubscription = false
|
||||
var isSubscriptionFee = false
|
||||
|
||||
var delayedCloseOnOpenPeer = true
|
||||
switch subject {
|
||||
case let .subscription(subscription):
|
||||
titleText = "Subscription"
|
||||
descriptionText = ""
|
||||
count = subscription.pricing.amount
|
||||
transactionId = nil
|
||||
date = subscription.untilDate
|
||||
via = nil
|
||||
messageId = nil
|
||||
toPeer = subscription.peer
|
||||
transactionPeer = .peer(subscription.peer)
|
||||
isSubscription = true
|
||||
case let .transaction(transaction, parentPeer):
|
||||
if let _ = transaction.subscriptionPeriod {
|
||||
//TODO:localize
|
||||
titleText = "Monthly Subscription Fee"
|
||||
titleText = "Monthly subscription fee"
|
||||
descriptionText = ""
|
||||
count = transaction.count
|
||||
countOnTop = false
|
||||
@ -219,10 +234,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
toPeer = nil
|
||||
}
|
||||
transactionPeer = transaction.peer
|
||||
media = []
|
||||
photo = nil
|
||||
isRefund = false
|
||||
isGift = false
|
||||
isSubscriptionFee = true
|
||||
} else if transaction.flags.contains(.isGift) {
|
||||
titleText = strings.Stars_Gift_Received_Title
|
||||
descriptionText = strings.Stars_Gift_Received_Text
|
||||
@ -238,9 +250,6 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
toPeer = nil
|
||||
}
|
||||
transactionPeer = transaction.peer
|
||||
media = []
|
||||
photo = nil
|
||||
isRefund = false
|
||||
isGift = true
|
||||
} else {
|
||||
switch transaction.peer {
|
||||
@ -319,7 +328,6 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
transactionPeer = transaction.peer
|
||||
media = transaction.media.map { AnyMediaReference.starsTransaction(transaction: StarsTransactionReference(peerId: parentPeer.id, id: transaction.id, isRefund: transaction.flags.contains(.isRefund)), media: $0) }
|
||||
photo = transaction.photo
|
||||
isGift = false
|
||||
isRefund = transaction.flags.contains(.isRefund)
|
||||
}
|
||||
case let .receipt(receipt):
|
||||
@ -336,10 +344,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
toPeer = nil
|
||||
}
|
||||
transactionPeer = nil
|
||||
media = []
|
||||
photo = receipt.invoiceMedia.photo
|
||||
isRefund = false
|
||||
isGift = false
|
||||
delayedCloseOnOpenPeer = false
|
||||
case let .gift(message):
|
||||
let incoming = message.flags.contains(.Incoming)
|
||||
@ -365,9 +370,6 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
toPeer = state.peerMap[message.id.peerId]
|
||||
}
|
||||
transactionPeer = nil
|
||||
media = []
|
||||
photo = nil
|
||||
isRefund = false
|
||||
isGift = true
|
||||
delayedCloseOnOpenPeer = false
|
||||
}
|
||||
@ -416,6 +418,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
)
|
||||
|
||||
let imageSubject: StarsImageComponent.Subject
|
||||
let imageIcon: StarsImageComponent.Icon?
|
||||
if isGift {
|
||||
imageSubject = .gift(count)
|
||||
} else if !media.isEmpty {
|
||||
@ -429,6 +432,11 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
} else {
|
||||
imageSubject = .none
|
||||
}
|
||||
if isSubscription || isSubscriptionFee {
|
||||
imageIcon = .star
|
||||
} else {
|
||||
imageIcon = nil
|
||||
}
|
||||
let star = star.update(
|
||||
component: StarsImageComponent(
|
||||
context: component.context,
|
||||
@ -436,6 +444,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
theme: theme,
|
||||
diameter: 90.0,
|
||||
backgroundColor: theme.actionSheet.opaqueItemBackgroundColor,
|
||||
icon: imageIcon,
|
||||
action: !media.isEmpty ? { transitionNode, addToTransitionSurface in
|
||||
component.openMedia(media.map { $0.media }, transitionNode, addToTransitionSurface)
|
||||
} : nil
|
||||
@ -939,6 +948,7 @@ public class StarsTransactionScreen: ViewControllerComponentContainer {
|
||||
case transaction(StarsContext.State.Transaction, EnginePeer)
|
||||
case receipt(BotPaymentReceipt)
|
||||
case gift(EngineMessage)
|
||||
case subscription(StarsContext.State.Subscription)
|
||||
}
|
||||
|
||||
private let context: AccountContext
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user