mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various improvements
This commit is contained in:
parent
a5aac7fcd7
commit
e27bb3a220
@ -5633,6 +5633,8 @@ Sorry for the inconvenience.";
|
||||
|
||||
"Settings.RemoveConfirmation" = "Remove";
|
||||
|
||||
"Conversation.ContextMenuOpenInfo" = "Open Info";
|
||||
|
||||
"Conversation.ContextMenuOpenProfile" = "Open Profile";
|
||||
"Conversation.ContextMenuSendMessage" = "Send Message";
|
||||
"Conversation.ContextMenuMention" = "Mention";
|
||||
@ -12883,3 +12885,22 @@ Sorry for the inconvenience.";
|
||||
|
||||
"WebBrowser.ShowInstantView" = "Show Instant View";
|
||||
"WebBrowser.HideInstantView" = "Hide Instant View";
|
||||
|
||||
"Stats.Boosts.Stars_1" = "%@ Star";
|
||||
"Stats.Boosts.Stars_any" = "%@ Stars";
|
||||
"Stats.Boosts.StarsBoosts" = "12-month boosts";
|
||||
|
||||
"BoostGift.PrepaidGiveaway.StarsCount_1" = "%@ Star";
|
||||
"BoostGift.PrepaidGiveaway.StarsCount_any" = "%@ Stars";
|
||||
"BoostGift.PrepaidGiveaway.StarsBoosts" = "12-month boosts";
|
||||
|
||||
"Stars.Transaction.Giveaway.Boost.Stars_1" = "%@ Star";
|
||||
"Stars.Transaction.Giveaway.Boost.Stars_any" = "%@ Stars";
|
||||
"Stars.Transaction.Giveaway.Boost.Boosts_1" = "%@ Boost";
|
||||
"Stars.Transaction.Giveaway.Boost.Boosts_any" = "%@ Boosts";
|
||||
"Stars.Transaction.Giveaway.Boost.Members_1" = "%@ Member";
|
||||
"Stars.Transaction.Giveaway.Boost.Members_any" = "%@ Members";
|
||||
"Stars.Transaction.Giveaway.Boost.Subscriber_1" = "%@ Subscriber";
|
||||
"Stars.Transaction.Giveaway.Boost.Subscriber_any" = "%@ Subscribers";
|
||||
|
||||
"Conversation.ContextMenuCopyEmail" = "Copy Email";
|
||||
|
@ -1016,6 +1016,7 @@ public protocol SharedAccountContext: AnyObject {
|
||||
func makeStarsAmountScreen(context: AccountContext, initialValue: Int64?, completion: @escaping (Int64) -> Void) -> ViewController
|
||||
func makeStarsWithdrawalScreen(context: AccountContext, stats: StarsRevenueStats, completion: @escaping (Int64) -> Void) -> ViewController
|
||||
func makeStarsGiftScreen(context: AccountContext, message: EngineMessage) -> ViewController
|
||||
func makeStarsGiveawayBoostScreen(context: AccountContext, peerId: EnginePeer.Id, boost: ChannelBoostersContext.State.Boost) -> ViewController
|
||||
|
||||
func makeMiniAppListScreenInitialData(context: AccountContext) -> Signal<MiniAppListScreenInitialData, NoError>
|
||||
func makeMiniAppListScreen(context: AccountContext, initialData: MiniAppListScreenInitialData) -> ViewController
|
||||
|
@ -459,6 +459,8 @@ private enum CreateGiveawayEntry: ItemListNodeEntry {
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .prepaid(_, title, subtitle, prepaidGiveaway):
|
||||
let color: GiftOptionItem.Icon.Color
|
||||
let icon: String
|
||||
let boosts: Int32
|
||||
switch prepaidGiveaway.prize {
|
||||
case let .premium(months):
|
||||
switch months {
|
||||
@ -471,16 +473,14 @@ private enum CreateGiveawayEntry: ItemListNodeEntry {
|
||||
default:
|
||||
color = .blue
|
||||
}
|
||||
case let .stars(amount, _):
|
||||
if amount <= 1000 {
|
||||
color = .green
|
||||
} else if amount < 2500 {
|
||||
color = .blue
|
||||
} else {
|
||||
color = .red
|
||||
}
|
||||
icon = "Premium/Giveaway"
|
||||
boosts = prepaidGiveaway.quantity * 4
|
||||
case let .stars(_, boostCount):
|
||||
color = .stars
|
||||
icon = "Premium/PremiumStar"
|
||||
boosts = boostCount
|
||||
}
|
||||
return GiftOptionItem(presentationData: presentationData, context: arguments.context, icon: .image(color: color, name: "Premium/Giveaway"), title: title, titleFont: .bold, titleBadge: "\(prepaidGiveaway.quantity * 4)", subtitle: subtitle, sectionId: self.section, action: nil)
|
||||
return GiftOptionItem(presentationData: presentationData, context: arguments.context, icon: .image(color: color, name: icon), title: title, titleFont: .bold, titleBadge: "\(boosts)", subtitle: subtitle, sectionId: self.section, action: nil)
|
||||
case let .starsHeader(_, text, additionalText):
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, accessoryText: ItemListSectionHeaderAccessoryText(value: additionalText, color: .generic), sectionId: self.section)
|
||||
case let .stars(_, _, stars, title, subtitle, label, isSelected, maxWinners):
|
||||
@ -778,9 +778,8 @@ private func createGiveawayControllerEntries(
|
||||
title = presentationData.strings.BoostGift_PrepaidGiveawayCount(prepaidGiveaway.quantity)
|
||||
text = presentationData.strings.BoostGift_PrepaidGiveawayMonths("\(months)").string
|
||||
case let .stars(stars, _):
|
||||
//TODO:localize
|
||||
title = "\(stars) Telegram Stars"
|
||||
text = "among \(prepaidGiveaway.quantity) winners"
|
||||
title = presentationData.strings.BoostGift_PrepaidGiveaway_StarsCount(Int32(stars))
|
||||
text = presentationData.strings.BoostGift_PrepaidGiveaway_StarsBoosts
|
||||
}
|
||||
entries.append(.prepaid(presentationData.theme, title, text, prepaidGiveaway))
|
||||
}
|
||||
|
@ -223,7 +223,9 @@ class CreateGiveawayHeaderItemNode: ItemListControllerHeaderItemNode {
|
||||
isVisible: true,
|
||||
hasIdleAnimations: true,
|
||||
colors: colors,
|
||||
particleColor: particleColor
|
||||
particleColor: particleColor,
|
||||
backgroundColor: self.item.theme.list.blocksBackgroundColor
|
||||
|
||||
))
|
||||
let containerSize = CGSize(width: min(414.0, layout.size.width), height: 220.0)
|
||||
|
||||
|
@ -614,6 +614,7 @@ private final class PremiumGiftCodeSheetComponent: CombinedComponent {
|
||||
)),
|
||||
backgroundColor: .color(environment.theme.actionSheet.opaqueItemBackgroundColor),
|
||||
followContentSizeChanges: true,
|
||||
clipsContent: true,
|
||||
animateOut: animateOut
|
||||
),
|
||||
environment: {
|
||||
|
@ -682,7 +682,8 @@ private func privacyAndSecurityControllerEntries(
|
||||
} else {
|
||||
value = privacySettings.accountRemovalTimeout
|
||||
}
|
||||
entries.append(.accountTimeout(presentationData.theme, presentationData.strings.PrivacySettings_DeleteAccountIfAwayFor, timeIntervalString(strings: presentationData.strings, value: value)))
|
||||
|
||||
entries.append(.accountTimeout(presentationData.theme, presentationData.strings.PrivacySettings_DeleteAccountIfAwayFor, presentationData.strings.MessageTimer_Months(max(1, value / (60 * 60 * 24 * 30)))))
|
||||
} else {
|
||||
entries.append(.accountTimeout(presentationData.theme, presentationData.strings.PrivacySettings_DeleteAccountIfAwayFor, presentationData.strings.Channel_NotificationLoading))
|
||||
}
|
||||
@ -1174,10 +1175,11 @@ public func privacyAndSecurityController(
|
||||
1 * 30 * 24 * 60 * 60,
|
||||
3 * 30 * 24 * 60 * 60,
|
||||
6 * 30 * 24 * 60 * 60,
|
||||
365 * 24 * 60 * 60
|
||||
365 * 24 * 60 * 60,
|
||||
548 * 24 * 60 * 60
|
||||
]
|
||||
var timeoutItems: [ActionSheetItem] = timeoutValues.map { value in
|
||||
return ActionSheetButtonItem(title: timeIntervalString(strings: presentationData.strings, value: value), action: {
|
||||
return ActionSheetButtonItem(title: presentationData.strings.MessageTimer_Months(max(1, value / (60 * 60 * 24 * 30))), action: {
|
||||
dismissAction()
|
||||
timeoutAction(value)
|
||||
})
|
||||
|
@ -962,7 +962,7 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
case let .booster(_, _, _, boost):
|
||||
let count = boost.multiplier
|
||||
let expiresValue = stringForDate(timestamp: boost.expires, strings: presentationData.strings)
|
||||
let expiresString: String
|
||||
var expiresString: String
|
||||
|
||||
let durationMonths = Int32(round(Float(boost.expires - boost.date) / (86400.0 * 30.0)))
|
||||
let durationString = presentationData.strings.Stats_Boosts_ShortMonth("\(durationMonths)").string
|
||||
@ -998,17 +998,23 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
expiresString = presentationData.strings.Stats_Boosts_ExpiresOn(expiresValue).string
|
||||
}
|
||||
} else {
|
||||
expiresString = "\(durationString) • \(expiresValue)"
|
||||
if boost.flags.contains(.isUnclaimed) {
|
||||
title = presentationData.strings.Stats_Boosts_Unclaimed
|
||||
icon = .image(color: color, name: "Premium/Unclaimed")
|
||||
} else if boost.flags.contains(.isGiveaway) {
|
||||
title = presentationData.strings.Stats_Boosts_ToBeDistributed
|
||||
icon = .image(color: color, name: "Premium/ToBeDistributed")
|
||||
if let stars = boost.stars {
|
||||
title = presentationData.strings.Stats_Boosts_Stars(Int32(stars))
|
||||
icon = .image(color: .stars, name: "Premium/PremiumStar")
|
||||
expiresString = expiresValue
|
||||
} else {
|
||||
title = presentationData.strings.Stats_Boosts_ToBeDistributed
|
||||
icon = .image(color: color, name: "Premium/ToBeDistributed")
|
||||
}
|
||||
} else {
|
||||
title = "Unknown"
|
||||
icon = .image(color: color, name: "Premium/ToBeDistributed")
|
||||
}
|
||||
expiresString = "\(durationString) • \(expiresValue)"
|
||||
}
|
||||
return GiftOptionItem(presentationData: presentationData, context: arguments.context, icon: icon, title: title, titleFont: .bold, titleBadge: count > 1 ? "\(count)" : nil, subtitle: expiresString, label: label.flatMap { .semitransparent($0) }, sectionId: self.section, action: {
|
||||
arguments.openBoost(boost)
|
||||
@ -1038,6 +1044,8 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
})
|
||||
case let .boostPrepaid(_, _, title, subtitle, prepaidGiveaway):
|
||||
let color: GiftOptionItem.Icon.Color
|
||||
let icon: String
|
||||
var boosts: Int32
|
||||
switch prepaidGiveaway.prize {
|
||||
case let .premium(months):
|
||||
switch months {
|
||||
@ -1050,16 +1058,14 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
default:
|
||||
color = .blue
|
||||
}
|
||||
case let .stars(amount, _):
|
||||
if amount <= 1000 {
|
||||
color = .green
|
||||
} else if amount < 2500 {
|
||||
color = .blue
|
||||
} else {
|
||||
color = .red
|
||||
}
|
||||
icon = "Premium/Giveaway"
|
||||
boosts = prepaidGiveaway.quantity * 4
|
||||
case let .stars(_, boostCount):
|
||||
color = .stars
|
||||
icon = "Premium/PremiumStar"
|
||||
boosts = boostCount
|
||||
}
|
||||
return GiftOptionItem(presentationData: presentationData, context: arguments.context, icon: .image(color: color, name: "Premium/Giveaway"), title: title, titleFont: .bold, titleBadge: "\(prepaidGiveaway.quantity * 4)", subtitle: subtitle, label: nil, sectionId: self.section, action: {
|
||||
return GiftOptionItem(presentationData: presentationData, context: arguments.context, icon: .image(color: color, name: icon), title: title, titleFont: .bold, titleBadge: "\(boosts)", subtitle: subtitle, label: nil, sectionId: self.section, action: {
|
||||
arguments.createPrepaidGiveaway(prepaidGiveaway)
|
||||
})
|
||||
case let .adsHeader(_, text):
|
||||
@ -1441,8 +1447,8 @@ private func boostsEntries(
|
||||
title = presentationData.strings.Stats_Boosts_PrepaidGiveawayCount(giveaway.quantity)
|
||||
text = presentationData.strings.Stats_Boosts_PrepaidGiveawayMonths("\(months)").string
|
||||
case let .stars(stars, _):
|
||||
title = "\(stars) Telegram Stars"
|
||||
text = "among \(giveaway.quantity) winners"
|
||||
title = presentationData.strings.Stats_Boosts_Stars(Int32(stars))
|
||||
text = presentationData.strings.Stats_Boosts_StarsBoosts
|
||||
}
|
||||
entries.append(.boostPrepaid(i, presentationData.theme, title, text, giveaway))
|
||||
i += 1
|
||||
@ -1942,8 +1948,13 @@ public func channelStatsController(context: AccountContext, updatedPresentationD
|
||||
}
|
||||
|
||||
if boost.peer == nil, boost.flags.contains(.isGiveaway) && !boost.flags.contains(.isUnclaimed) {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
presentImpl?(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.Stats_Boosts_TooltipToBeDistributed, timeout: nil, customUndoText: nil), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }))
|
||||
if let _ = boost.stars {
|
||||
let controller = context.sharedContext.makeStarsGiveawayBoostScreen(context: context, peerId: peerId, boost: boost)
|
||||
pushImpl?(controller)
|
||||
} else {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
presentImpl?(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.Stats_Boosts_TooltipToBeDistributed, timeout: nil, customUndoText: nil), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,7 @@ private final class ChannelBoostersContextImpl {
|
||||
var result: [ChannelBoostersContext.State.Boost] = []
|
||||
for boost in cachedResult.boosts {
|
||||
let peer = boost.peerId.flatMap { transaction.getPeer($0) }
|
||||
result.append(ChannelBoostersContext.State.Boost(flags: ChannelBoostersContext.State.Boost.Flags(rawValue: boost.flags), id: boost.id, peer: peer.flatMap { EnginePeer($0) }, date: boost.date, expires: boost.expires, multiplier: boost.multiplier, slug: boost.slug))
|
||||
result.append(ChannelBoostersContext.State.Boost(flags: ChannelBoostersContext.State.Boost.Flags(rawValue: boost.flags), id: boost.id, peer: peer.flatMap { EnginePeer($0) }, date: boost.date, expires: boost.expires, multiplier: boost.multiplier, stars: boost.stars, slug: boost.slug, giveawayMessageId: boost.giveawayMessageId))
|
||||
}
|
||||
return (result, cachedResult.count, true)
|
||||
} else {
|
||||
@ -452,6 +452,7 @@ private final class CachedChannelBoosters: Codable {
|
||||
case date
|
||||
case expires
|
||||
case multiplier
|
||||
case stars
|
||||
case slug
|
||||
case channelPeerId
|
||||
case giveawayMessageId
|
||||
@ -463,17 +464,19 @@ private final class CachedChannelBoosters: Codable {
|
||||
var date: Int32
|
||||
var expires: Int32
|
||||
var multiplier: Int32
|
||||
var stars: Int64?
|
||||
var slug: String?
|
||||
var channelPeerId: EnginePeer.Id
|
||||
var giveawayMessageId: EngineMessage.Id?
|
||||
|
||||
init(flags: Int32, id: String, peerId: EnginePeer.Id?, date: Int32, expires: Int32, multiplier: Int32, slug: String?, channelPeerId: EnginePeer.Id, giveawayMessageId: EngineMessage.Id?) {
|
||||
init(flags: Int32, id: String, peerId: EnginePeer.Id?, date: Int32, expires: Int32, multiplier: Int32, stars: Int64?, slug: String?, channelPeerId: EnginePeer.Id, giveawayMessageId: EngineMessage.Id?) {
|
||||
self.flags = flags
|
||||
self.id = id
|
||||
self.peerId = peerId
|
||||
self.date = date
|
||||
self.expires = expires
|
||||
self.multiplier = multiplier
|
||||
self.stars = stars
|
||||
self.slug = slug
|
||||
self.channelPeerId = channelPeerId
|
||||
self.giveawayMessageId = giveawayMessageId
|
||||
@ -488,6 +491,7 @@ private final class CachedChannelBoosters: Codable {
|
||||
self.date = try container.decode(Int32.self, forKey: .date)
|
||||
self.expires = try container.decode(Int32.self, forKey: .expires)
|
||||
self.multiplier = try container.decode(Int32.self, forKey: .multiplier)
|
||||
self.stars = try container.decodeIfPresent(Int64.self, forKey: .stars)
|
||||
self.slug = try container.decodeIfPresent(String.self, forKey: .slug)
|
||||
self.channelPeerId = EnginePeer.Id(try container.decode(Int64.self, forKey: .channelPeerId))
|
||||
self.giveawayMessageId = try container.decodeIfPresent(Int32.self, forKey: .giveawayMessageId).flatMap { EngineMessage.Id(peerId: self.channelPeerId, namespace: Namespaces.Message.Cloud, id: $0) }
|
||||
@ -502,6 +506,7 @@ private final class CachedChannelBoosters: Codable {
|
||||
try container.encode(self.date, forKey: .date)
|
||||
try container.encode(self.expires, forKey: .expires)
|
||||
try container.encode(self.multiplier, forKey: .multiplier)
|
||||
try container.encodeIfPresent(self.stars, forKey: .stars)
|
||||
try container.encodeIfPresent(self.slug, forKey: .slug)
|
||||
try container.encode(self.channelPeerId.toInt64(), forKey: .channelPeerId)
|
||||
try container.encodeIfPresent(self.giveawayMessageId?.id, forKey: .giveawayMessageId)
|
||||
@ -518,7 +523,7 @@ private final class CachedChannelBoosters: Codable {
|
||||
}
|
||||
|
||||
init(channelPeerId: EnginePeer.Id, boosts: [ChannelBoostersContext.State.Boost], count: Int32) {
|
||||
self.boosts = boosts.map { CachedBoost(flags: $0.flags.rawValue, id: $0.id, peerId: $0.peer?.id, date: $0.date, expires: $0.expires, multiplier: $0.multiplier, slug: $0.slug, channelPeerId: channelPeerId, giveawayMessageId: $0.giveawayMessageId) }
|
||||
self.boosts = boosts.map { CachedBoost(flags: $0.flags.rawValue, id: $0.id, peerId: $0.peer?.id, date: $0.date, expires: $0.expires, multiplier: $0.multiplier, stars: $0.stars, slug: $0.slug, channelPeerId: channelPeerId, giveawayMessageId: $0.giveawayMessageId) }
|
||||
self.count = count
|
||||
}
|
||||
|
||||
|
@ -76,6 +76,7 @@ public final class PremiumStarComponent: Component {
|
||||
let hasIdleAnimations: Bool
|
||||
let colors: [UIColor]?
|
||||
let particleColor: UIColor?
|
||||
let backgroundColor: UIColor?
|
||||
|
||||
public init(
|
||||
theme: PresentationTheme,
|
||||
@ -83,7 +84,8 @@ public final class PremiumStarComponent: Component {
|
||||
isVisible: Bool,
|
||||
hasIdleAnimations: Bool,
|
||||
colors: [UIColor]? = nil,
|
||||
particleColor: UIColor? = nil
|
||||
particleColor: UIColor? = nil,
|
||||
backgroundColor: UIColor? = nil
|
||||
) {
|
||||
self.theme = theme
|
||||
self.isIntro = isIntro
|
||||
@ -91,10 +93,11 @@ public final class PremiumStarComponent: Component {
|
||||
self.hasIdleAnimations = hasIdleAnimations
|
||||
self.colors = colors
|
||||
self.particleColor = particleColor
|
||||
self.backgroundColor = backgroundColor
|
||||
}
|
||||
|
||||
public static func ==(lhs: PremiumStarComponent, rhs: PremiumStarComponent) -> Bool {
|
||||
return lhs.theme === rhs.theme && lhs.isIntro == rhs.isIntro && lhs.isVisible == rhs.isVisible && lhs.hasIdleAnimations == rhs.hasIdleAnimations && lhs.colors == rhs.colors && lhs.particleColor == rhs.particleColor
|
||||
return lhs.theme === rhs.theme && lhs.isIntro == rhs.isIntro && lhs.isVisible == rhs.isVisible && lhs.hasIdleAnimations == rhs.hasIdleAnimations && lhs.colors == rhs.colors && lhs.particleColor == rhs.particleColor && lhs.backgroundColor == rhs.backgroundColor
|
||||
}
|
||||
|
||||
public final class View: UIView, SCNSceneRendererDelegate, ComponentTaggedView {
|
||||
@ -694,8 +697,10 @@ public final class PremiumStarComponent: Component {
|
||||
self.playAppearanceAnimation(velocity: nil, mirror: component.colors?.contains(UIColor(rgb: 0xe57d02)) == true, explode: true, force: true)
|
||||
}
|
||||
|
||||
if let _ = component.particleColor {
|
||||
self.sceneView.backgroundColor = component.theme.list.blocksBackgroundColor
|
||||
if let backgroundColor = component.backgroundColor {
|
||||
self.sceneView.backgroundColor = backgroundColor
|
||||
} else {
|
||||
self.sceneView.backgroundColor = .clear
|
||||
}
|
||||
|
||||
self.sceneView.bounds = CGRect(origin: .zero, size: CGSize(width: availableSize.width * 2.0, height: availableSize.height * 2.0))
|
||||
|
@ -707,7 +707,11 @@ public final class StarsImageComponent: Component {
|
||||
} else {
|
||||
avatarNode = ImageNode()
|
||||
avatarNode.displaysAsynchronously = false
|
||||
containerNode.view.addSubview(avatarNode.view)
|
||||
if let smallIconOutlineView = self.smallIconOutlineView {
|
||||
containerNode.view.insertSubview(avatarNode.view, belowSubview: smallIconOutlineView)
|
||||
} else {
|
||||
containerNode.view.addSubview(avatarNode.view)
|
||||
}
|
||||
self.avatarNode = avatarNode
|
||||
|
||||
avatarNode.setSignal(peerAvatarCompleteImage(account: component.context.account, peer: peer, size: imageSize, font: avatarPlaceholderFont(size: 43.0), fullSize: true))
|
||||
|
@ -786,7 +786,8 @@ private final class StarsPurchaseScreenComponent: CombinedComponent {
|
||||
UIColor(rgb: 0xf9b004),
|
||||
UIColor(rgb: 0xfdd219)
|
||||
],
|
||||
particleColor: UIColor(rgb: 0xf9b004)
|
||||
particleColor: UIColor(rgb: 0xf9b004),
|
||||
backgroundColor: environment.theme.list.blocksBackgroundColor
|
||||
),
|
||||
availableSize: CGSize(width: min(414.0, context.availableSize.width), height: 220.0),
|
||||
transition: context.transition
|
||||
|
@ -35,6 +35,7 @@ swift_library(
|
||||
"//submodules/TelegramUI/Components/Stars/StarsAvatarComponent",
|
||||
"//submodules/GalleryUI",
|
||||
"//submodules/TelegramUI/Components/MiniAppListScreen",
|
||||
"//submodules/TelegramUI/Components/Premium/PremiumStarComponent",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -24,6 +24,7 @@ import StarsImageComponent
|
||||
import GalleryUI
|
||||
import StarsAvatarComponent
|
||||
import MiniAppListScreen
|
||||
import PremiumStarComponent
|
||||
|
||||
private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
||||
@ -104,6 +105,8 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
peerIds.append(subscription.peer.id)
|
||||
case let .importer(_, _, importer, _):
|
||||
peerIds.append(importer.peer.peerId)
|
||||
case let .boost(peerId, _):
|
||||
peerIds.append(peerId)
|
||||
}
|
||||
|
||||
self.disposable = (context.engine.data.get(
|
||||
@ -141,6 +144,8 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
let closeButton = Child(Button.self)
|
||||
let title = Child(MultilineTextComponent.self)
|
||||
let star = Child(StarsImageComponent.self)
|
||||
let activeStar = Child(PremiumStarComponent.self)
|
||||
let amountBackground = Child(RoundedRectangle.self)
|
||||
let amount = Child(BalancedTextComponent.self)
|
||||
let amountStar = Child(BundleIconComponent.self)
|
||||
let description = Child(MultilineTextComponent.self)
|
||||
@ -191,6 +196,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
let titleText: String
|
||||
let amountText: String
|
||||
var descriptionText: String
|
||||
var boostsText: String?
|
||||
let additionalText = strings.Stars_Transaction_Terms
|
||||
var buttonText: String? = strings.Common_OK
|
||||
var buttonIsDestructive = false
|
||||
@ -206,6 +212,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
var via: String?
|
||||
var messageId: EngineMessage.Id?
|
||||
var toPeer: EnginePeer?
|
||||
// var toString: String?
|
||||
var transactionPeer: StarsContext.State.Transaction.Peer?
|
||||
var media: [AnyMediaReference] = []
|
||||
var photo: TelegramMediaWebFile?
|
||||
@ -217,9 +224,24 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
var isCancelled = false
|
||||
var isReaction = false
|
||||
var giveawayMessageId: MessageId?
|
||||
var isBoost = false
|
||||
|
||||
var delayedCloseOnOpenPeer = true
|
||||
switch subject {
|
||||
case let .boost(peerId, boost):
|
||||
guard let stars = boost.stars else {
|
||||
fatalError()
|
||||
}
|
||||
let boosts = boost.multiplier
|
||||
titleText = strings.Stars_Transaction_Giveaway_Boost_Stars(Int32(stars))
|
||||
descriptionText = ""
|
||||
boostsText = strings.Stars_Transaction_Giveaway_Boost_Boosts(boosts)
|
||||
count = stars
|
||||
date = boost.date
|
||||
toPeer = state.peerMap[peerId]
|
||||
// toString = strings.Stars_Transaction_Giveaway_Boost_Subscribers(boost.quantity)
|
||||
giveawayMessageId = boost.giveawayMessageId
|
||||
isBoost = true
|
||||
case let .importer(peer, pricing, importer, usdRate):
|
||||
let usdValue = formatTonUsdValue(pricing.amount, divide: false, rate: usdRate, dateTimeFormat: environment.dateTimeFormat)
|
||||
titleText = strings.Stars_Transaction_Subscription_Title
|
||||
@ -493,7 +515,14 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
|
||||
let formattedAmount = presentationStringsFormattedNumber(abs(Int32(count)), dateTimeFormat.groupingSeparator)
|
||||
let countColor: UIColor
|
||||
if isSubscription || isSubscriber {
|
||||
var countFont: UIFont = isSubscription || isSubscriber ? Font.regular(17.0) : Font.semibold(17.0)
|
||||
var countBackgroundColor: UIColor?
|
||||
if let boostsText {
|
||||
amountText = boostsText
|
||||
countColor = .white
|
||||
countBackgroundColor = UIColor(rgb: 0x9671ff)
|
||||
countFont = Font.with(size: 14.0, design: .round, weight: .semibold)
|
||||
} else if isSubscription || isSubscriber {
|
||||
amountText = strings.Stars_Transaction_Subscription_PerMonth(formattedAmount).string
|
||||
countColor = theme.list.itemSecondaryTextColor
|
||||
} else if countIsGeneric {
|
||||
@ -542,23 +571,45 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
} else {
|
||||
imageIcon = nil
|
||||
}
|
||||
let star = star.update(
|
||||
component: StarsImageComponent(
|
||||
context: component.context,
|
||||
subject: imageSubject,
|
||||
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
|
||||
),
|
||||
availableSize: CGSize(width: context.availableSize.width, height: 200.0),
|
||||
transition: .immediate
|
||||
)
|
||||
|
||||
let amountAttributedText = NSMutableAttributedString(string: amountText, font: isSubscription || isSubscriber ? Font.regular(17.0) : Font.semibold(17.0), textColor: countColor)
|
||||
var starChild: _UpdatedChildComponent
|
||||
if isBoost {
|
||||
starChild = activeStar.update(
|
||||
component: PremiumStarComponent(
|
||||
theme: theme,
|
||||
isIntro: false,
|
||||
isVisible: true,
|
||||
hasIdleAnimations: true,
|
||||
colors: [
|
||||
UIColor(rgb: 0xe57d02),
|
||||
UIColor(rgb: 0xf09903),
|
||||
UIColor(rgb: 0xf9b004),
|
||||
UIColor(rgb: 0xfdd219)
|
||||
],
|
||||
particleColor: UIColor(rgb: 0xf9b004),
|
||||
backgroundColor: theme.actionSheet.opaqueItemBackgroundColor
|
||||
),
|
||||
availableSize: CGSize(width: context.availableSize.width, height: 200.0),
|
||||
transition: .immediate
|
||||
)
|
||||
} else {
|
||||
starChild = star.update(
|
||||
component: StarsImageComponent(
|
||||
context: component.context,
|
||||
subject: imageSubject,
|
||||
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
|
||||
),
|
||||
availableSize: CGSize(width: context.availableSize.width, height: 200.0),
|
||||
transition: .immediate
|
||||
)
|
||||
}
|
||||
|
||||
let amountAttributedText = NSMutableAttributedString(string: amountText, font: countFont, textColor: countColor)
|
||||
let amount = amount.update(
|
||||
component: BalancedTextComponent(
|
||||
text: .plain(amountAttributedText),
|
||||
@ -572,7 +623,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
|
||||
let amountStar = amountStar.update(
|
||||
component: BundleIconComponent(
|
||||
name: "Premium/Stars/StarMedium",
|
||||
name: boostsText != nil ? "Premium/BoostButtonIcon" : "Premium/Stars/StarMedium",
|
||||
tintColor: nil
|
||||
),
|
||||
availableSize: context.availableSize,
|
||||
@ -824,17 +875,17 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
availableSize: CGSize(width: context.availableSize.width - textSideInset * 2.0, height: context.availableSize.height),
|
||||
transition: .immediate
|
||||
)
|
||||
|
||||
context.add(starChild
|
||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: starChild.size.height / 2.0 - 19.0))
|
||||
)
|
||||
|
||||
context.add(title
|
||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: 31.0 + 125.0))
|
||||
)
|
||||
|
||||
context.add(star
|
||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: star.size.height / 2.0 - 19.0))
|
||||
)
|
||||
|
||||
var originY: CGFloat = 0.0
|
||||
originY += star.size.height - 23.0
|
||||
originY += starChild.size.height - 23.0
|
||||
|
||||
var descriptionSize: CGSize = .zero
|
||||
if !descriptionText.isEmpty {
|
||||
@ -884,7 +935,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
originY += description.size.height + 10.0
|
||||
}
|
||||
|
||||
let amountSpacing: CGFloat = 1.0
|
||||
let amountSpacing: CGFloat = countBackgroundColor != nil ? 4.0 : 1.0
|
||||
var totalAmountWidth: CGFloat = amount.size.width + amountSpacing + amountStar.size.width
|
||||
var amountOriginX: CGFloat = floor(context.availableSize.width - totalAmountWidth) / 2.0
|
||||
if let (statusText, statusColor) = transactionStatus {
|
||||
@ -928,7 +979,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
|
||||
let amountLabelOriginX: CGFloat
|
||||
let amountStarOriginX: CGFloat
|
||||
if isSubscription || isSubscriber {
|
||||
if isSubscription || isSubscriber || boostsText != nil {
|
||||
amountStarOriginX = amountOriginX + amountStar.size.width / 2.0
|
||||
amountLabelOriginX = amountOriginX + amountStar.size.width + amountSpacing + amount.size.width / 2.0
|
||||
} else {
|
||||
@ -936,11 +987,26 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
amountStarOriginX = amountOriginX + amount.size.width + amountSpacing + amountStar.size.width / 2.0
|
||||
}
|
||||
|
||||
var amountLabelOffsetY: CGFloat = 0.0
|
||||
var amountStarOffsetY: CGFloat = 0.0
|
||||
if let countBackgroundColor {
|
||||
let amountBackground = amountBackground.update(
|
||||
component: RoundedRectangle(color: countBackgroundColor, cornerRadius: 23 / 2.0),
|
||||
availableSize: CGSize(width: totalAmountWidth + 14.0, height: 23.0),
|
||||
transition: .immediate
|
||||
)
|
||||
context.add(amountBackground
|
||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: amountOrigin + amount.size.height / 2.0 + 1.0))
|
||||
)
|
||||
amountLabelOffsetY = 2.0
|
||||
amountStarOffsetY = 5.0
|
||||
}
|
||||
|
||||
context.add(amount
|
||||
.position(CGPoint(x: amountLabelOriginX, y: amountOrigin + amount.size.height / 2.0))
|
||||
.position(CGPoint(x: amountLabelOriginX, y: amountOrigin + amount.size.height / 2.0 + amountLabelOffsetY))
|
||||
)
|
||||
context.add(amountStar
|
||||
.position(CGPoint(x: amountStarOriginX, y: amountOrigin + amountStar.size.height / 2.0 - UIScreenPixel))
|
||||
.position(CGPoint(x: amountStarOriginX, y: amountOrigin + amountStar.size.height / 2.0 - UIScreenPixel + amountStarOffsetY))
|
||||
)
|
||||
|
||||
context.add(table
|
||||
@ -1166,6 +1232,7 @@ public class StarsTransactionScreen: ViewControllerComponentContainer {
|
||||
case gift(EngineMessage)
|
||||
case subscription(StarsContext.State.Subscription)
|
||||
case importer(EnginePeer, StarsSubscriptionPricing, PeerInvitationImportersState.Importer, Double)
|
||||
case boost(EnginePeer.Id, ChannelBoostersContext.State.Boost)
|
||||
}
|
||||
|
||||
private let context: AccountContext
|
||||
|
@ -424,7 +424,8 @@ final class StarsTransactionsScreenComponent: Component {
|
||||
UIColor(rgb: 0xf9b004),
|
||||
UIColor(rgb: 0xfdd219)
|
||||
],
|
||||
particleColor: UIColor(rgb: 0xf9b004)
|
||||
particleColor: UIColor(rgb: 0xf9b004),
|
||||
backgroundColor: environment.theme.list.blocksBackgroundColor
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: min(414.0, availableSize.width), height: 220.0)
|
||||
|
12
submodules/TelegramUI/Images.xcassets/Premium/PremiumStar.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Premium/PremiumStar.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "premium_30.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Premium/PremiumStar.imageset/premium_30.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Premium/PremiumStar.imageset/premium_30.pdf
vendored
Normal file
Binary file not shown.
@ -128,13 +128,15 @@ extension ChatControllerImpl {
|
||||
var canAddToReadingList = true
|
||||
let canOpenIn = availableOpenInOptions(context: self.context, item: .url(url: url)).count > 1
|
||||
|
||||
var isEmail = false
|
||||
let mailtoString = "mailto:"
|
||||
var openText = self.presentationData.strings.Conversation_LinkDialogOpen
|
||||
|
||||
var copyText = self.presentationData.strings.Conversation_ContextMenuCopyLink
|
||||
if cleanUrl.hasPrefix(mailtoString) {
|
||||
canAddToReadingList = false
|
||||
cleanUrl = String(cleanUrl[cleanUrl.index(cleanUrl.startIndex, offsetBy: mailtoString.distance(from: mailtoString.startIndex, to: mailtoString.endIndex))...])
|
||||
// isEmail = true
|
||||
copyText = self.presentationData.strings.Conversation_ContextMenuCopyEmail
|
||||
isEmail = true
|
||||
} else if canOpenIn {
|
||||
openText = self.presentationData.strings.Conversation_FileOpenIn
|
||||
}
|
||||
@ -168,16 +170,16 @@ extension ChatControllerImpl {
|
||||
)
|
||||
|
||||
items.append(
|
||||
.action(ContextMenuActionItem(text: self.presentationData.strings.Conversation_ContextMenuCopyLink, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Copy"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in
|
||||
.action(ContextMenuActionItem(text: copyText, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Copy"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in
|
||||
f(.default)
|
||||
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
UIPasteboard.general.string = url
|
||||
UIPasteboard.general.string = cleanUrl
|
||||
|
||||
self.present(UndoOverlayController(presentationData: self.presentationData, content: .copy(text: presentationData.strings.Conversation_LinkCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
|
||||
self.present(UndoOverlayController(presentationData: self.presentationData, content: .copy(text: isEmail ? presentationData.strings.Conversation_EmailCopied : presentationData.strings.Conversation_LinkCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
|
||||
}))
|
||||
)
|
||||
|
||||
|
@ -2791,6 +2791,10 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
return StarsTransactionScreen(context: context, subject: .gift(message))
|
||||
}
|
||||
|
||||
public func makeStarsGiveawayBoostScreen(context: AccountContext, peerId: EnginePeer.Id, boost: ChannelBoostersContext.State.Boost) -> ViewController {
|
||||
return StarsTransactionScreen(context: context, subject: .boost(peerId, boost))
|
||||
}
|
||||
|
||||
public func makeMiniAppListScreenInitialData(context: AccountContext) -> Signal<MiniAppListScreenInitialData, NoError> {
|
||||
return MiniAppListScreen.initialData(context: context)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user