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
b2351194d4
commit
4aeab37c70
@ -13876,3 +13876,11 @@ Sorry for the inconvenience.";
|
|||||||
"Chat.PanelCustomStatusShortInfo" = "%@ is a mark for [Premium subscribers >]()";
|
"Chat.PanelCustomStatusShortInfo" = "%@ is a mark for [Premium subscribers >]()";
|
||||||
|
|
||||||
"Chat.InputTextPaidMessagePlaceholder" = "Message for %@";
|
"Chat.InputTextPaidMessagePlaceholder" = "Message for %@";
|
||||||
|
|
||||||
|
"Privacy.Messages.Stars_1" = "%@ Star";
|
||||||
|
"Privacy.Messages.Stars_any" = "%@ Stars";
|
||||||
|
"Privacy.Messages.Unlock" = "Unlock with Telegram Premium";
|
||||||
|
|
||||||
|
"Premium.PaidMessages" = "Paid Messages";
|
||||||
|
"Premium.PaidMessagesInfo" = "Charge a fee for messages from non-contacts or new senders.";
|
||||||
|
"Premium.PaidMessages.Proceed" = "About Telegram Premium";
|
||||||
|
@ -1357,25 +1357,29 @@ public struct StarsSubscriptionConfiguration {
|
|||||||
maxFee: 2500,
|
maxFee: 2500,
|
||||||
usdWithdrawRate: 1200,
|
usdWithdrawRate: 1200,
|
||||||
paidMessageMaxAmount: 10000,
|
paidMessageMaxAmount: 10000,
|
||||||
paidMessageCommissionPermille: 850
|
paidMessageCommissionPermille: 850,
|
||||||
|
paidMessagesAvailable: false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public let maxFee: Int64
|
public let maxFee: Int64
|
||||||
public let usdWithdrawRate: Int64
|
public let usdWithdrawRate: Int64
|
||||||
public let paidMessageMaxAmount: Int64
|
public let paidMessageMaxAmount: Int64
|
||||||
public let paidMessageCommissionPermille: Int32
|
public let paidMessageCommissionPermille: Int32
|
||||||
|
public let paidMessagesAvailable: Bool
|
||||||
|
|
||||||
fileprivate init(
|
fileprivate init(
|
||||||
maxFee: Int64,
|
maxFee: Int64,
|
||||||
usdWithdrawRate: Int64,
|
usdWithdrawRate: Int64,
|
||||||
paidMessageMaxAmount: Int64,
|
paidMessageMaxAmount: Int64,
|
||||||
paidMessageCommissionPermille: Int32
|
paidMessageCommissionPermille: Int32,
|
||||||
|
paidMessagesAvailable: Bool
|
||||||
) {
|
) {
|
||||||
self.maxFee = maxFee
|
self.maxFee = maxFee
|
||||||
self.usdWithdrawRate = usdWithdrawRate
|
self.usdWithdrawRate = usdWithdrawRate
|
||||||
self.paidMessageMaxAmount = paidMessageMaxAmount
|
self.paidMessageMaxAmount = paidMessageMaxAmount
|
||||||
self.paidMessageCommissionPermille = paidMessageCommissionPermille
|
self.paidMessageCommissionPermille = paidMessageCommissionPermille
|
||||||
|
self.paidMessagesAvailable = paidMessagesAvailable
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func with(appConfiguration: AppConfiguration) -> StarsSubscriptionConfiguration {
|
public static func with(appConfiguration: AppConfiguration) -> StarsSubscriptionConfiguration {
|
||||||
@ -1384,11 +1388,14 @@ public struct StarsSubscriptionConfiguration {
|
|||||||
let usdWithdrawRate = (data["stars_usd_withdraw_rate_x1000"] as? Double).flatMap(Int64.init) ?? StarsSubscriptionConfiguration.defaultValue.usdWithdrawRate
|
let usdWithdrawRate = (data["stars_usd_withdraw_rate_x1000"] as? Double).flatMap(Int64.init) ?? StarsSubscriptionConfiguration.defaultValue.usdWithdrawRate
|
||||||
let paidMessageMaxAmount = (data["stars_paid_message_amount_max"] as? Double).flatMap(Int64.init) ?? StarsSubscriptionConfiguration.defaultValue.paidMessageMaxAmount
|
let paidMessageMaxAmount = (data["stars_paid_message_amount_max"] as? Double).flatMap(Int64.init) ?? StarsSubscriptionConfiguration.defaultValue.paidMessageMaxAmount
|
||||||
let paidMessageCommissionPermille = (data["stars_paid_message_commission_permille"] as? Double).flatMap(Int32.init) ?? StarsSubscriptionConfiguration.defaultValue.paidMessageCommissionPermille
|
let paidMessageCommissionPermille = (data["stars_paid_message_commission_permille"] as? Double).flatMap(Int32.init) ?? StarsSubscriptionConfiguration.defaultValue.paidMessageCommissionPermille
|
||||||
|
let paidMessagesAvailable = (data["stars_paid_messages_available"] as? Bool) ?? StarsSubscriptionConfiguration.defaultValue.paidMessagesAvailable
|
||||||
|
|
||||||
return StarsSubscriptionConfiguration(
|
return StarsSubscriptionConfiguration(
|
||||||
maxFee: maxFee,
|
maxFee: maxFee,
|
||||||
usdWithdrawRate: usdWithdrawRate,
|
usdWithdrawRate: usdWithdrawRate,
|
||||||
paidMessageMaxAmount: paidMessageMaxAmount,
|
paidMessageMaxAmount: paidMessageMaxAmount,
|
||||||
paidMessageCommissionPermille: paidMessageCommissionPermille
|
paidMessageCommissionPermille: paidMessageCommissionPermille,
|
||||||
|
paidMessagesAvailable: paidMessagesAvailable
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return .defaultValue
|
return .defaultValue
|
||||||
|
@ -42,6 +42,7 @@ public enum PremiumIntroSource {
|
|||||||
case folderTags
|
case folderTags
|
||||||
case animatedEmoji
|
case animatedEmoji
|
||||||
case messageEffects
|
case messageEffects
|
||||||
|
case paidMessages
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum PremiumGiftSource: Equatable {
|
public enum PremiumGiftSource: Equatable {
|
||||||
@ -79,6 +80,7 @@ public enum PremiumDemoSubject {
|
|||||||
case folderTags
|
case folderTags
|
||||||
case business
|
case business
|
||||||
case messageEffects
|
case messageEffects
|
||||||
|
case paidMessages
|
||||||
|
|
||||||
case businessLocation
|
case businessLocation
|
||||||
case businessHours
|
case businessHours
|
||||||
|
@ -347,6 +347,8 @@ public class ItemListCheckboxItemNode: ItemListRevealOptionsItemNode {
|
|||||||
iconFrame = CGRect(origin: CGPoint(x: params.leftInset + floor((leftInset - params.leftInset - iconSize.width) / 2.0), y: floor((contentSize.height - iconSize.height) / 2.0)), size: iconSize)
|
iconFrame = CGRect(origin: CGPoint(x: params.leftInset + floor((leftInset - params.leftInset - iconSize.width) / 2.0), y: floor((contentSize.height - iconSize.height) / 2.0)), size: iconSize)
|
||||||
}
|
}
|
||||||
strongSelf.imageNode.frame = iconFrame
|
strongSelf.imageNode.frame = iconFrame
|
||||||
|
} else {
|
||||||
|
strongSelf.imageNode.image = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: strongSelf.backgroundNode.frame.height + UIScreenPixel + UIScreenPixel))
|
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: strongSelf.backgroundNode.frame.height + UIScreenPixel + UIScreenPixel))
|
||||||
|
@ -141,7 +141,7 @@ const CGFloat TGPhotoEditorSliderViewInternalMargin = 7.0f;
|
|||||||
if (vertical)
|
if (vertical)
|
||||||
startPosition = 2 * visualMargin + visualTotalLength - startPosition;
|
startPosition = 2 * visualMargin + visualTotalLength - startPosition;
|
||||||
|
|
||||||
CGFloat endPosition = visualMargin + visualTotalLength / (_maximumValue - _minimumValue) * (ABS(_minimumValue) + 1.0);
|
CGFloat endPosition = visualMargin + visualTotalLength / (_maximumValue - _minimumValue) * (ABS(_minimumValue) + _maximumValue);
|
||||||
if (vertical)
|
if (vertical)
|
||||||
endPosition = 2 * visualMargin + visualTotalLength - endPosition;
|
endPosition = 2 * visualMargin + visualTotalLength - endPosition;
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ private enum ChannelPermissionsEntry: ItemListNodeEntry {
|
|||||||
case chargeForMessagesInfo(PresentationTheme, String)
|
case chargeForMessagesInfo(PresentationTheme, String)
|
||||||
|
|
||||||
case messagePriceHeader(PresentationTheme, String)
|
case messagePriceHeader(PresentationTheme, String)
|
||||||
case messagePrice(PresentationTheme, Int64, String)
|
case messagePrice(PresentationTheme, Int64, Int64, String)
|
||||||
case messagePriceInfo(PresentationTheme, String)
|
case messagePriceInfo(PresentationTheme, String)
|
||||||
|
|
||||||
case unrestrictBoostersSwitch(PresentationTheme, String, Bool)
|
case unrestrictBoostersSwitch(PresentationTheme, String, Bool)
|
||||||
@ -241,8 +241,8 @@ private enum ChannelPermissionsEntry: ItemListNodeEntry {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case let .messagePrice(lhsTheme, lhsValue, lhsPrice):
|
case let .messagePrice(lhsTheme, lhsValue, lhsMaxValue, lhsPrice):
|
||||||
if case let .messagePrice(rhsTheme, rhsValue, rhsPrice) = rhs, lhsTheme === rhsTheme, lhsValue == rhsValue, lhsPrice == rhsPrice {
|
if case let .messagePrice(rhsTheme, rhsValue, rhsMaxValue, rhsPrice) = rhs, lhsTheme === rhsTheme, lhsValue == rhsValue, lhsMaxValue == rhsMaxValue, lhsPrice == rhsPrice {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
@ -424,8 +424,8 @@ private enum ChannelPermissionsEntry: ItemListNodeEntry {
|
|||||||
return ItemListTextItem(presentationData: presentationData, text: .plain(value), sectionId: self.section)
|
return ItemListTextItem(presentationData: presentationData, text: .plain(value), sectionId: self.section)
|
||||||
case let .messagePriceHeader(_, value):
|
case let .messagePriceHeader(_, value):
|
||||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: value, sectionId: self.section)
|
return ItemListSectionHeaderItem(presentationData: presentationData, text: value, sectionId: self.section)
|
||||||
case let .messagePrice(_, value, price):
|
case let .messagePrice(_, value, maxValue, price):
|
||||||
return MessagePriceItem(theme: presentationData.theme, strings: presentationData.strings, minValue: 1, maxValue: 10000, value: value, price: price, sectionId: self.section, updated: { value in
|
return MessagePriceItem(theme: presentationData.theme, strings: presentationData.strings, isEnabled: true, minValue: 1, maxValue: maxValue, value: value, price: price, sectionId: self.section, updated: { value in
|
||||||
arguments.updateStarsAmount(StarsAmount(value: value, nanos: 0))
|
arguments.updateStarsAmount(StarsAmount(value: value, nanos: 0))
|
||||||
})
|
})
|
||||||
case let .messagePriceInfo(_, value):
|
case let .messagePriceInfo(_, value):
|
||||||
@ -733,7 +733,7 @@ private func channelPermissionsControllerEntries(context: AccountContext, presen
|
|||||||
price = "≈\(formatTonUsdValue(sendPaidMessageStars, divide: false, rate: usdRate, dateTimeFormat: presentationData.dateTimeFormat))"
|
price = "≈\(formatTonUsdValue(sendPaidMessageStars, divide: false, rate: usdRate, dateTimeFormat: presentationData.dateTimeFormat))"
|
||||||
|
|
||||||
entries.append(.messagePriceHeader(presentationData.theme, presentationData.strings.GroupInfo_Permissions_MessagePrice))
|
entries.append(.messagePriceHeader(presentationData.theme, presentationData.strings.GroupInfo_Permissions_MessagePrice))
|
||||||
entries.append(.messagePrice(presentationData.theme, sendPaidMessageStars, price))
|
entries.append(.messagePrice(presentationData.theme, sendPaidMessageStars, configuration.paidMessageMaxAmount, price))
|
||||||
entries.append(.messagePriceInfo(presentationData.theme, presentationData.strings.GroupInfo_Permissions_MessagePriceInfo("\(configuration.paidMessageCommissionPermille / 10)", price).string))
|
entries.append(.messagePriceInfo(presentationData.theme, presentationData.strings.GroupInfo_Permissions_MessagePriceInfo("\(configuration.paidMessageCommissionPermille / 10)", price).string))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1099,6 +1099,25 @@ private final class DemoSheetContent: CombinedComponent {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
availableItems[.paidMessages] = DemoPagerComponent.Item(
|
||||||
|
AnyComponentWithIdentity(
|
||||||
|
id: PremiumDemoScreen.Subject.paidMessages,
|
||||||
|
component: AnyComponent(
|
||||||
|
PageComponent(
|
||||||
|
content: AnyComponent(PhoneDemoComponent(
|
||||||
|
context: component.context,
|
||||||
|
position: .top,
|
||||||
|
videoFile: configuration.videos["paid_messages"],
|
||||||
|
decoration: .badgeStars
|
||||||
|
)),
|
||||||
|
title: strings.Premium_PaidMessages,
|
||||||
|
text: strings.Premium_PaidMessagesInfo,
|
||||||
|
textColor: textColor
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
let index: Int = 0
|
let index: Int = 0
|
||||||
var items: [DemoPagerComponent.Item] = []
|
var items: [DemoPagerComponent.Item] = []
|
||||||
if let item = availableItems.first(where: { $0.value.content.id == component.subject as AnyHashable }) {
|
if let item = availableItems.first(where: { $0.value.content.id == component.subject as AnyHashable }) {
|
||||||
@ -1195,6 +1214,8 @@ private final class DemoSheetContent: CombinedComponent {
|
|||||||
text = strings.Premium_FolderTagsStandaloneInfo
|
text = strings.Premium_FolderTagsStandaloneInfo
|
||||||
case .messageEffects:
|
case .messageEffects:
|
||||||
text = strings.Premium_MessageEffectsInfo
|
text = strings.Premium_MessageEffectsInfo
|
||||||
|
case .paidMessages:
|
||||||
|
text = strings.Premium_PaidMessagesInfo
|
||||||
default:
|
default:
|
||||||
text = ""
|
text = ""
|
||||||
}
|
}
|
||||||
@ -1279,6 +1300,9 @@ private final class DemoSheetContent: CombinedComponent {
|
|||||||
case .emojiStatus:
|
case .emojiStatus:
|
||||||
buttonText = strings.Premium_EmojiStatus_Proceed
|
buttonText = strings.Premium_EmojiStatus_Proceed
|
||||||
buttonAnimationName = "premium_unlock"
|
buttonAnimationName = "premium_unlock"
|
||||||
|
case .paidMessages:
|
||||||
|
buttonText = strings.Premium_PaidMessages_Proceed
|
||||||
|
buttonAnimationName = "premium_unlock"
|
||||||
default:
|
default:
|
||||||
buttonText = strings.Common_OK
|
buttonText = strings.Common_OK
|
||||||
}
|
}
|
||||||
@ -1468,6 +1492,7 @@ public class PremiumDemoScreen: ViewControllerComponentContainer {
|
|||||||
case business
|
case business
|
||||||
case folderTags
|
case folderTags
|
||||||
case messageEffects
|
case messageEffects
|
||||||
|
case paidMessages
|
||||||
|
|
||||||
case businessLocation
|
case businessLocation
|
||||||
case businessHours
|
case businessHours
|
||||||
@ -1526,6 +1551,8 @@ public class PremiumDemoScreen: ViewControllerComponentContainer {
|
|||||||
return .folderTags
|
return .folderTags
|
||||||
case .messageEffects:
|
case .messageEffects:
|
||||||
return .messageEffects
|
return .messageEffects
|
||||||
|
case .paidMessages:
|
||||||
|
return .paidMessages
|
||||||
case .businessLocation:
|
case .businessLocation:
|
||||||
return .businessLocation
|
return .businessLocation
|
||||||
case .businessHours:
|
case .businessHours:
|
||||||
|
@ -433,6 +433,7 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
|
|||||||
UIColor(rgb: 0xdb374b),
|
UIColor(rgb: 0xdb374b),
|
||||||
UIColor(rgb: 0xcb3e6d),
|
UIColor(rgb: 0xcb3e6d),
|
||||||
UIColor(rgb: 0xbc4395),
|
UIColor(rgb: 0xbc4395),
|
||||||
|
UIColor(rgb: 0xbc4395),
|
||||||
UIColor(rgb: 0xab4ac4),
|
UIColor(rgb: 0xab4ac4),
|
||||||
UIColor(rgb: 0xab4ac4),
|
UIColor(rgb: 0xab4ac4),
|
||||||
UIColor(rgb: 0xa34cd7),
|
UIColor(rgb: 0xa34cd7),
|
||||||
@ -538,6 +539,8 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
|
|||||||
demoSubject = .messagePrivacy
|
demoSubject = .messagePrivacy
|
||||||
case .messageEffects:
|
case .messageEffects:
|
||||||
demoSubject = .messageEffects
|
demoSubject = .messageEffects
|
||||||
|
case .paidMessages:
|
||||||
|
demoSubject = .paidMessages
|
||||||
case .business:
|
case .business:
|
||||||
demoSubject = .business
|
demoSubject = .business
|
||||||
default:
|
default:
|
||||||
|
@ -302,6 +302,12 @@ public enum PremiumSource: Equatable {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
case .paidMessages:
|
||||||
|
if case .messageEffects = rhs {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,6 +355,7 @@ public enum PremiumSource: Equatable {
|
|||||||
case messageTags
|
case messageTags
|
||||||
case folderTags
|
case folderTags
|
||||||
case messageEffects
|
case messageEffects
|
||||||
|
case paidMessages
|
||||||
|
|
||||||
var identifier: String? {
|
var identifier: String? {
|
||||||
switch self {
|
switch self {
|
||||||
@ -442,6 +449,8 @@ public enum PremiumSource: Equatable {
|
|||||||
return "folder_tags"
|
return "folder_tags"
|
||||||
case .messageEffects:
|
case .messageEffects:
|
||||||
return "effects"
|
return "effects"
|
||||||
|
case .paidMessages:
|
||||||
|
return "paid_messages"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -470,6 +479,7 @@ public enum PremiumPerk: CaseIterable {
|
|||||||
case business
|
case business
|
||||||
case folderTags
|
case folderTags
|
||||||
case messageEffects
|
case messageEffects
|
||||||
|
case paidMessages
|
||||||
|
|
||||||
case businessLocation
|
case businessLocation
|
||||||
case businessHours
|
case businessHours
|
||||||
@ -504,7 +514,8 @@ public enum PremiumPerk: CaseIterable {
|
|||||||
.messagePrivacy,
|
.messagePrivacy,
|
||||||
.folderTags,
|
.folderTags,
|
||||||
.business,
|
.business,
|
||||||
.messageEffects
|
.messageEffects,
|
||||||
|
.paidMessages
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -578,6 +589,8 @@ public enum PremiumPerk: CaseIterable {
|
|||||||
return "folder_tags"
|
return "folder_tags"
|
||||||
case .messageEffects:
|
case .messageEffects:
|
||||||
return "effects"
|
return "effects"
|
||||||
|
case .paidMessages:
|
||||||
|
return "paid_messages"
|
||||||
case .business:
|
case .business:
|
||||||
return "business"
|
return "business"
|
||||||
case .businessLocation:
|
case .businessLocation:
|
||||||
@ -647,6 +660,8 @@ public enum PremiumPerk: CaseIterable {
|
|||||||
return strings.Premium_Business
|
return strings.Premium_Business
|
||||||
case .messageEffects:
|
case .messageEffects:
|
||||||
return strings.Premium_MessageEffects
|
return strings.Premium_MessageEffects
|
||||||
|
case .paidMessages:
|
||||||
|
return strings.Premium_PaidMessages
|
||||||
case .businessLocation:
|
case .businessLocation:
|
||||||
return strings.Business_Location
|
return strings.Business_Location
|
||||||
case .businessHours:
|
case .businessHours:
|
||||||
@ -714,6 +729,8 @@ public enum PremiumPerk: CaseIterable {
|
|||||||
return strings.Premium_BusinessInfo
|
return strings.Premium_BusinessInfo
|
||||||
case .messageEffects:
|
case .messageEffects:
|
||||||
return strings.Premium_MessageEffectsInfo
|
return strings.Premium_MessageEffectsInfo
|
||||||
|
case .paidMessages:
|
||||||
|
return strings.Premium_PaidMessagesInfo
|
||||||
case .businessLocation:
|
case .businessLocation:
|
||||||
return strings.Business_LocationInfo
|
return strings.Business_LocationInfo
|
||||||
case .businessHours:
|
case .businessHours:
|
||||||
@ -781,7 +798,8 @@ public enum PremiumPerk: CaseIterable {
|
|||||||
return "Premium/Perk/Business"
|
return "Premium/Perk/Business"
|
||||||
case .messageEffects:
|
case .messageEffects:
|
||||||
return "Premium/Perk/MessageEffects"
|
return "Premium/Perk/MessageEffects"
|
||||||
|
case .paidMessages:
|
||||||
|
return "Premium/Perk/PaidMessages"
|
||||||
case .businessLocation:
|
case .businessLocation:
|
||||||
return "Premium/BusinessPerk/Location"
|
return "Premium/BusinessPerk/Location"
|
||||||
case .businessHours:
|
case .businessHours:
|
||||||
@ -819,6 +837,7 @@ struct PremiumIntroConfiguration {
|
|||||||
.colors,
|
.colors,
|
||||||
.wallpapers,
|
.wallpapers,
|
||||||
.profileBadge,
|
.profileBadge,
|
||||||
|
.paidMessages,
|
||||||
.messagePrivacy,
|
.messagePrivacy,
|
||||||
.advancedChatManagement,
|
.advancedChatManagement,
|
||||||
.noAds,
|
.noAds,
|
||||||
@ -867,6 +886,12 @@ struct PremiumIntroConfiguration {
|
|||||||
perks = PremiumIntroConfiguration.defaultValue.perks
|
perks = PremiumIntroConfiguration.defaultValue.perks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
if !perks.contains(.paidMessages) {
|
||||||
|
perks.append(.paidMessages)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
var businessPerks: [PremiumPerk] = []
|
var businessPerks: [PremiumPerk] = []
|
||||||
if let values = data["business_promo_order"] as? [String] {
|
if let values = data["business_promo_order"] as? [String] {
|
||||||
for value in values {
|
for value in values {
|
||||||
@ -1859,6 +1884,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
|
|||||||
UIColor(rgb: 0xdb374b),
|
UIColor(rgb: 0xdb374b),
|
||||||
UIColor(rgb: 0xcb3e6d),
|
UIColor(rgb: 0xcb3e6d),
|
||||||
UIColor(rgb: 0xbc4395),
|
UIColor(rgb: 0xbc4395),
|
||||||
|
UIColor(rgb: 0xbc4395),
|
||||||
UIColor(rgb: 0xab4ac4),
|
UIColor(rgb: 0xab4ac4),
|
||||||
UIColor(rgb: 0xab4ac4),
|
UIColor(rgb: 0xab4ac4),
|
||||||
UIColor(rgb: 0xa34cd7),
|
UIColor(rgb: 0xa34cd7),
|
||||||
@ -2092,6 +2118,8 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
|
|||||||
demoSubject = .messagePrivacy
|
demoSubject = .messagePrivacy
|
||||||
case .messageEffects:
|
case .messageEffects:
|
||||||
demoSubject = .messageEffects
|
demoSubject = .messageEffects
|
||||||
|
case .paidMessages:
|
||||||
|
demoSubject = .paidMessages
|
||||||
case .business:
|
case .business:
|
||||||
demoSubject = .business
|
demoSubject = .business
|
||||||
let _ = ApplicationSpecificNotice.setDismissedBusinessBadge(accountManager: accountContext.sharedContext.accountManager).startStandalone()
|
let _ = ApplicationSpecificNotice.setDismissedBusinessBadge(accountManager: accountContext.sharedContext.accountManager).startStandalone()
|
||||||
|
@ -842,6 +842,24 @@ public class PremiumLimitsListScreen: ViewController {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
availableItems[.paidMessages] = DemoPagerComponent.Item(
|
||||||
|
AnyComponentWithIdentity(
|
||||||
|
id: PremiumDemoScreen.Subject.paidMessages,
|
||||||
|
component: AnyComponent(
|
||||||
|
PageComponent(
|
||||||
|
content: AnyComponent(PhoneDemoComponent(
|
||||||
|
context: context,
|
||||||
|
position: .top,
|
||||||
|
videoFile: videos["paid_messages"],
|
||||||
|
decoration: .badgeStars
|
||||||
|
)),
|
||||||
|
title: strings.Premium_PaidMessages,
|
||||||
|
text: strings.Premium_PaidMessagesInfo,
|
||||||
|
textColor: textColor
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
availableItems[.business] = DemoPagerComponent.Item(
|
availableItems[.business] = DemoPagerComponent.Item(
|
||||||
AnyComponentWithIdentity(
|
AnyComponentWithIdentity(
|
||||||
id: PremiumDemoScreen.Subject.business,
|
id: PremiumDemoScreen.Subject.business,
|
||||||
|
@ -19,19 +19,22 @@ private final class IncomingMessagePrivacyScreenArguments {
|
|||||||
let disabledValuePressed: () -> Void
|
let disabledValuePressed: () -> Void
|
||||||
let infoLinkAction: () -> Void
|
let infoLinkAction: () -> Void
|
||||||
let openExceptions: () -> Void
|
let openExceptions: () -> Void
|
||||||
|
let openPremiumInfo: () -> Void
|
||||||
|
|
||||||
init(
|
init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
updateValue: @escaping (GlobalPrivacySettings.NonContactChatsPrivacy) -> Void,
|
updateValue: @escaping (GlobalPrivacySettings.NonContactChatsPrivacy) -> Void,
|
||||||
disabledValuePressed: @escaping () -> Void,
|
disabledValuePressed: @escaping () -> Void,
|
||||||
infoLinkAction: @escaping () -> Void,
|
infoLinkAction: @escaping () -> Void,
|
||||||
openExceptions: @escaping () -> Void
|
openExceptions: @escaping () -> Void,
|
||||||
|
openPremiumInfo: @escaping () -> Void
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.updateValue = updateValue
|
self.updateValue = updateValue
|
||||||
self.disabledValuePressed = disabledValuePressed
|
self.disabledValuePressed = disabledValuePressed
|
||||||
self.infoLinkAction = infoLinkAction
|
self.infoLinkAction = infoLinkAction
|
||||||
self.openExceptions = openExceptions
|
self.openExceptions = openExceptions
|
||||||
|
self.openPremiumInfo = openPremiumInfo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +52,7 @@ private enum GlobalAutoremoveEntry: ItemListNodeEntry {
|
|||||||
case optionChargeForMessages(value: GlobalPrivacySettings.NonContactChatsPrivacy, isEnabled: Bool)
|
case optionChargeForMessages(value: GlobalPrivacySettings.NonContactChatsPrivacy, isEnabled: Bool)
|
||||||
case footer(value: GlobalPrivacySettings.NonContactChatsPrivacy)
|
case footer(value: GlobalPrivacySettings.NonContactChatsPrivacy)
|
||||||
case priceHeader
|
case priceHeader
|
||||||
case price(value: Int64, price: String)
|
case price(value: Int64, maxValue: Int64, price: String, isEnabled: Bool)
|
||||||
case priceInfo(commission: Int32, value: String)
|
case priceInfo(commission: Int32, value: String)
|
||||||
case exceptionsHeader
|
case exceptionsHeader
|
||||||
case exceptions(count: Int)
|
case exceptions(count: Int)
|
||||||
@ -128,12 +131,8 @@ private enum GlobalAutoremoveEntry: ItemListNodeEntry {
|
|||||||
if case .paidMessages = value {
|
if case .paidMessages = value {
|
||||||
isChecked = true
|
isChecked = true
|
||||||
}
|
}
|
||||||
return ItemListCheckboxItem(presentationData: presentationData, icon: isEnabled ? nil : generateTintedImage(image: UIImage(bundleImageName: "Chat/Stickers/Lock"), color: presentationData.theme.list.itemSecondaryTextColor), iconPlacement: .check, title: presentationData.strings.Privacy_Messages_ChargeForMessages, style: .left, checked: isChecked, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
return ItemListCheckboxItem(presentationData: presentationData, icon: isEnabled || isChecked ? nil : generateTintedImage(image: UIImage(bundleImageName: "Chat/Stickers/Lock"), color: presentationData.theme.list.itemSecondaryTextColor), iconPlacement: .check, title: presentationData.strings.Privacy_Messages_ChargeForMessages, style: .left, checked: isChecked, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||||
if isEnabled {
|
arguments.updateValue(.paidMessages(StarsAmount(value: 400, nanos: 0)))
|
||||||
arguments.updateValue(.paidMessages(StarsAmount(value: 400, nanos: 0)))
|
|
||||||
} else {
|
|
||||||
arguments.disabledValuePressed()
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
case let .footer(value):
|
case let .footer(value):
|
||||||
let text: String
|
let text: String
|
||||||
@ -149,9 +148,11 @@ private enum GlobalAutoremoveEntry: ItemListNodeEntry {
|
|||||||
})
|
})
|
||||||
case .priceHeader:
|
case .priceHeader:
|
||||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: presentationData.strings.Privacy_Messages_MessagePrice, sectionId: self.section)
|
return ItemListSectionHeaderItem(presentationData: presentationData, text: presentationData.strings.Privacy_Messages_MessagePrice, sectionId: self.section)
|
||||||
case let .price(value, price):
|
case let .price(value, maxValue, price, isEnabled):
|
||||||
return MessagePriceItem(theme: presentationData.theme, strings: presentationData.strings, minValue: 1, maxValue: 10000, value: value, price: price, sectionId: self.section, updated: { value in
|
return MessagePriceItem(theme: presentationData.theme, strings: presentationData.strings, isEnabled: isEnabled, minValue: 1, maxValue: maxValue, value: value, price: price, sectionId: self.section, updated: { value in
|
||||||
arguments.updateValue(.paidMessages(StarsAmount(value: value, nanos: 0)))
|
arguments.updateValue(.paidMessages(StarsAmount(value: value, nanos: 0)))
|
||||||
|
}, openPremiumInfo: {
|
||||||
|
arguments.openPremiumInfo()
|
||||||
})
|
})
|
||||||
case let .priceInfo(commission, value):
|
case let .priceInfo(commission, value):
|
||||||
return ItemListTextItem(presentationData: presentationData, text: .markdown(presentationData.strings.Privacy_Messages_MessagePriceInfo("\(commission)", value).string), sectionId: self.section)
|
return ItemListTextItem(presentationData: presentationData, text: .markdown(presentationData.strings.Privacy_Messages_MessagePriceInfo("\(commission)", value).string), sectionId: self.section)
|
||||||
@ -178,7 +179,9 @@ private func incomingMessagePrivacyScreenEntries(presentationData: PresentationD
|
|||||||
entries.append(.header)
|
entries.append(.header)
|
||||||
entries.append(.optionEverybody(value: state.updatedValue))
|
entries.append(.optionEverybody(value: state.updatedValue))
|
||||||
entries.append(.optionPremium(value: state.updatedValue, isEnabled: enableSetting))
|
entries.append(.optionPremium(value: state.updatedValue, isEnabled: enableSetting))
|
||||||
entries.append(.optionChargeForMessages(value: state.updatedValue, isEnabled: isPremium))
|
if configuration.paidMessagesAvailable {
|
||||||
|
entries.append(.optionChargeForMessages(value: state.updatedValue, isEnabled: isPremium))
|
||||||
|
}
|
||||||
|
|
||||||
if case let .paidMessages(amount) = state.updatedValue {
|
if case let .paidMessages(amount) = state.updatedValue {
|
||||||
entries.append(.footer(value: state.updatedValue))
|
entries.append(.footer(value: state.updatedValue))
|
||||||
@ -188,11 +191,14 @@ private func incomingMessagePrivacyScreenEntries(presentationData: PresentationD
|
|||||||
|
|
||||||
let price = "≈\(formatTonUsdValue(amount.value, divide: false, rate: usdRate, dateTimeFormat: presentationData.dateTimeFormat))"
|
let price = "≈\(formatTonUsdValue(amount.value, divide: false, rate: usdRate, dateTimeFormat: presentationData.dateTimeFormat))"
|
||||||
|
|
||||||
entries.append(.price(value: amount.value, price: price))
|
entries.append(.price(value: amount.value, maxValue: configuration.paidMessageMaxAmount, price: price, isEnabled: isPremium))
|
||||||
entries.append(.priceInfo(commission: configuration.paidMessageCommissionPermille / 10, value: price))
|
entries.append(.priceInfo(commission: configuration.paidMessageCommissionPermille / 10, value: price))
|
||||||
entries.append(.exceptionsHeader)
|
|
||||||
entries.append(.exceptions(count: state.disableFor.count))
|
if isPremium {
|
||||||
entries.append(.exceptionsInfo)
|
entries.append(.exceptionsHeader)
|
||||||
|
entries.append(.exceptions(count: state.disableFor.count))
|
||||||
|
entries.append(.exceptionsInfo)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
entries.append(.footer(value: state.updatedValue))
|
entries.append(.footer(value: state.updatedValue))
|
||||||
entries.append(.info)
|
entries.append(.info)
|
||||||
@ -347,6 +353,17 @@ public func incomingMessagePrivacyScreen(context: AccountContext, value: GlobalP
|
|||||||
})
|
})
|
||||||
pushControllerImpl?(controller)
|
pushControllerImpl?(controller)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
openPremiumInfo: {
|
||||||
|
var replaceImpl: ((ViewController) -> Void)?
|
||||||
|
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .paidMessages, forceDark: false, action: {
|
||||||
|
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .paidMessages, forceDark: false, dismissed: nil)
|
||||||
|
replaceImpl?(controller)
|
||||||
|
}, dismissed: nil)
|
||||||
|
replaceImpl = { [weak controller] c in
|
||||||
|
controller?.replace(with: c)
|
||||||
|
}
|
||||||
|
pushControllerImpl?(controller)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -414,7 +431,12 @@ public func incomingMessagePrivacyScreen(context: AccountContext, value: GlobalP
|
|||||||
controller?.push(c)
|
controller?.push(c)
|
||||||
}
|
}
|
||||||
controller.attemptNavigation = { _ in
|
controller.attemptNavigation = { _ in
|
||||||
update(stateValue.with({ $0 }).updatedValue)
|
let updatedValue = stateValue.with({ $0 }).updatedValue
|
||||||
|
if !context.isPremium, case .paidMessages = updatedValue {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
update(updatedValue)
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
dismissImpl = { [weak controller] in
|
dismissImpl = { [weak controller] in
|
||||||
|
@ -19,6 +19,10 @@ swift_library(
|
|||||||
"//submodules/TelegramPresentationData",
|
"//submodules/TelegramPresentationData",
|
||||||
"//submodules/ItemListUI",
|
"//submodules/ItemListUI",
|
||||||
"//submodules/LegacyComponents",
|
"//submodules/LegacyComponents",
|
||||||
|
"//submodules/ComponentFlow",
|
||||||
|
"//submodules/TelegramUI/Components/ButtonComponent",
|
||||||
|
"//submodules/Components/BundleIconComponent",
|
||||||
|
"//submodules/Components/MultilineTextComponent",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
@ -8,6 +8,10 @@ import TelegramPresentationData
|
|||||||
import LegacyComponents
|
import LegacyComponents
|
||||||
import ItemListUI
|
import ItemListUI
|
||||||
import PresentationDataUtils
|
import PresentationDataUtils
|
||||||
|
import ComponentFlow
|
||||||
|
import ButtonComponent
|
||||||
|
import BundleIconComponent
|
||||||
|
import MultilineTextComponent
|
||||||
|
|
||||||
private let textFont = Font.with(size: 17.0, traits: .monospacedNumbers)
|
private let textFont = Font.with(size: 17.0, traits: .monospacedNumbers)
|
||||||
private let smallTextFont = Font.with(size: 13.0, traits: .monospacedNumbers)
|
private let smallTextFont = Font.with(size: 13.0, traits: .monospacedNumbers)
|
||||||
@ -15,22 +19,26 @@ private let smallTextFont = Font.with(size: 13.0, traits: .monospacedNumbers)
|
|||||||
public final class MessagePriceItem: ListViewItem, ItemListItem {
|
public final class MessagePriceItem: ListViewItem, ItemListItem {
|
||||||
let theme: PresentationTheme
|
let theme: PresentationTheme
|
||||||
let strings: PresentationStrings
|
let strings: PresentationStrings
|
||||||
|
let isEnabled: Bool
|
||||||
let minValue: Int64
|
let minValue: Int64
|
||||||
let maxValue: Int64
|
let maxValue: Int64
|
||||||
let value: Int64
|
let value: Int64
|
||||||
let price: String
|
let price: String
|
||||||
public let sectionId: ItemListSectionId
|
public let sectionId: ItemListSectionId
|
||||||
let updated: (Int64) -> Void
|
let updated: (Int64) -> Void
|
||||||
|
let openPremiumInfo: (() -> Void)?
|
||||||
|
|
||||||
public init(theme: PresentationTheme, strings: PresentationStrings, minValue: Int64, maxValue: Int64, value: Int64, price: String, sectionId: ItemListSectionId, updated: @escaping (Int64) -> Void) {
|
public init(theme: PresentationTheme, strings: PresentationStrings, isEnabled: Bool, minValue: Int64, maxValue: Int64, value: Int64, price: String, sectionId: ItemListSectionId, updated: @escaping (Int64) -> Void, openPremiumInfo: (() -> Void)? = nil) {
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
self.strings = strings
|
self.strings = strings
|
||||||
|
self.isEnabled = isEnabled
|
||||||
self.minValue = minValue
|
self.minValue = minValue
|
||||||
self.maxValue = maxValue
|
self.maxValue = maxValue
|
||||||
self.value = value
|
self.value = value
|
||||||
self.price = price
|
self.price = price
|
||||||
self.sectionId = sectionId
|
self.sectionId = sectionId
|
||||||
self.updated = updated
|
self.updated = updated
|
||||||
|
self.openPremiumInfo = openPremiumInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
public func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void)) -> Void) {
|
public func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void)) -> Void) {
|
||||||
@ -155,6 +163,9 @@ private class MessagePriceItemNode: ListViewItemNode {
|
|||||||
private let rightTextNode: ImmediateTextNode
|
private let rightTextNode: ImmediateTextNode
|
||||||
private let centerLeftTextNode: ImmediateTextNode
|
private let centerLeftTextNode: ImmediateTextNode
|
||||||
private let centerRightTextNode: ImmediateTextNode
|
private let centerRightTextNode: ImmediateTextNode
|
||||||
|
private let lockIconNode: ASImageNode
|
||||||
|
|
||||||
|
private let button: ComponentView<Empty>
|
||||||
|
|
||||||
private var amount: Amount = Amount(realValue: 1, maxRealValue: 1000, maxSliderValue: 1000, isLogarithmic: true)
|
private var amount: Amount = Amount(realValue: 1, maxRealValue: 1000, maxSliderValue: 1000, isLogarithmic: true)
|
||||||
|
|
||||||
@ -178,12 +189,18 @@ private class MessagePriceItemNode: ListViewItemNode {
|
|||||||
self.centerLeftTextNode = ImmediateTextNode()
|
self.centerLeftTextNode = ImmediateTextNode()
|
||||||
self.centerRightTextNode = ImmediateTextNode()
|
self.centerRightTextNode = ImmediateTextNode()
|
||||||
|
|
||||||
|
self.lockIconNode = ASImageNode()
|
||||||
|
self.lockIconNode.displaysAsynchronously = false
|
||||||
|
|
||||||
|
self.button = ComponentView<Empty>()
|
||||||
|
|
||||||
super.init(layerBacked: false, dynamicBounce: false)
|
super.init(layerBacked: false, dynamicBounce: false)
|
||||||
|
|
||||||
self.addSubnode(self.leftTextNode)
|
self.addSubnode(self.leftTextNode)
|
||||||
self.addSubnode(self.rightTextNode)
|
self.addSubnode(self.rightTextNode)
|
||||||
self.addSubnode(self.centerLeftTextNode)
|
self.addSubnode(self.centerLeftTextNode)
|
||||||
self.addSubnode(self.centerRightTextNode)
|
self.addSubnode(self.centerRightTextNode)
|
||||||
|
self.addSubnode(self.lockIconNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func didLoad() {
|
override func didLoad() {
|
||||||
@ -224,11 +241,15 @@ private class MessagePriceItemNode: ListViewItemNode {
|
|||||||
themeUpdated = true
|
themeUpdated = true
|
||||||
}
|
}
|
||||||
|
|
||||||
let contentSize: CGSize
|
var contentSize: CGSize
|
||||||
let insets: UIEdgeInsets
|
let insets: UIEdgeInsets
|
||||||
let separatorHeight = UIScreenPixel
|
let separatorHeight = UIScreenPixel
|
||||||
|
|
||||||
contentSize = CGSize(width: params.width, height: 88.0)
|
contentSize = CGSize(width: params.width, height: 88.0)
|
||||||
|
if !item.isEnabled {
|
||||||
|
contentSize.height = 166.0
|
||||||
|
}
|
||||||
|
|
||||||
insets = itemListNeighborsGroupedInsets(neighbors, params)
|
insets = itemListNeighborsGroupedInsets(neighbors, params)
|
||||||
|
|
||||||
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
|
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
|
||||||
@ -290,8 +311,7 @@ private class MessagePriceItemNode: ListViewItemNode {
|
|||||||
strongSelf.leftTextNode.attributedText = NSAttributedString(string: "\(item.minValue)", font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor)
|
strongSelf.leftTextNode.attributedText = NSAttributedString(string: "\(item.minValue)", font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor)
|
||||||
strongSelf.rightTextNode.attributedText = NSAttributedString(string: "\(item.maxValue)", font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor)
|
strongSelf.rightTextNode.attributedText = NSAttributedString(string: "\(item.maxValue)", font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor)
|
||||||
|
|
||||||
//TODO:localize
|
let centralLeftText = item.strings.Privacy_Messages_Stars(Int32(item.value))
|
||||||
let centralLeftText = "\(item.value) Stars"
|
|
||||||
strongSelf.centerLeftTextNode.attributedText = NSAttributedString(string: centralLeftText, font: textFont, textColor: item.theme.list.itemPrimaryTextColor)
|
strongSelf.centerLeftTextNode.attributedText = NSAttributedString(string: centralLeftText, font: textFont, textColor: item.theme.list.itemPrimaryTextColor)
|
||||||
strongSelf.centerRightTextNode.attributedText = NSAttributedString(string: item.price, font: smallTextFont, textColor: item.theme.list.itemSecondaryTextColor)
|
strongSelf.centerRightTextNode.attributedText = NSAttributedString(string: item.price, font: smallTextFont, textColor: item.theme.list.itemSecondaryTextColor)
|
||||||
|
|
||||||
@ -323,6 +343,66 @@ private class MessagePriceItemNode: ListViewItemNode {
|
|||||||
|
|
||||||
sliderView.frame = CGRect(origin: CGPoint(x: params.leftInset + 18.0, y: 36.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - 18.0 * 2.0, height: 44.0))
|
sliderView.frame = CGRect(origin: CGPoint(x: params.leftInset + 18.0, y: 36.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - 18.0 * 2.0, height: 44.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
strongSelf.lockIconNode.isHidden = item.isEnabled
|
||||||
|
if !item.isEnabled {
|
||||||
|
if themeUpdated {
|
||||||
|
strongSelf.lockIconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Stickers/SmallLock"), color: item.theme.list.itemSecondaryTextColor.withMultipliedAlpha(0.5))
|
||||||
|
}
|
||||||
|
if let image = strongSelf.lockIconNode.image {
|
||||||
|
strongSelf.lockIconNode.frame = CGRect(origin: CGPoint(x: centerLeftFrame.minX - image.size.width - 1.0, y: 12.0 + UIScreenPixel), size: image.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
let sideInset: CGFloat = 16.0
|
||||||
|
let buttonSize = CGSize(width: params.width - params.leftInset - params.rightInset - sideInset * 2.0, height: 50.0)
|
||||||
|
let _ = strongSelf.button.update(
|
||||||
|
transition: .immediate,
|
||||||
|
component: AnyComponent(
|
||||||
|
ButtonComponent(
|
||||||
|
background: ButtonComponent.Background(
|
||||||
|
color: item.theme.list.itemCheckColors.fillColor,
|
||||||
|
foreground: item.theme.list.itemCheckColors.foregroundColor,
|
||||||
|
pressedColor: item.theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.9)
|
||||||
|
),
|
||||||
|
content: AnyComponentWithIdentity(
|
||||||
|
id: AnyHashable("unlock"),
|
||||||
|
component: AnyComponent(
|
||||||
|
HStack([
|
||||||
|
AnyComponentWithIdentity(
|
||||||
|
id: AnyHashable("icon"),
|
||||||
|
component: AnyComponent(BundleIconComponent(name: "Chat/Stickers/Lock", tintColor: item.theme.list.itemCheckColors.foregroundColor))
|
||||||
|
),
|
||||||
|
AnyComponentWithIdentity(
|
||||||
|
id: AnyHashable("label"),
|
||||||
|
component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: item.strings.Privacy_Messages_Unlock, font: Font.semibold(17.0), textColor: item.theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center))))
|
||||||
|
)
|
||||||
|
], spacing: 3.0)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
isEnabled: true,
|
||||||
|
tintWhenDisabled: false,
|
||||||
|
allowActionWhenDisabled: false,
|
||||||
|
displaysProgress: false,
|
||||||
|
action: { [weak self] in
|
||||||
|
guard let self, let item = self.item else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
item.openPremiumInfo?()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
),
|
||||||
|
environment: {},
|
||||||
|
containerSize: buttonSize
|
||||||
|
)
|
||||||
|
if let buttonView = strongSelf.button.view {
|
||||||
|
if buttonView.superview == nil {
|
||||||
|
strongSelf.view.addSubview(buttonView)
|
||||||
|
}
|
||||||
|
buttonView.frame = CGRect(origin: CGPoint(x: params.leftInset + sideInset, y: contentSize.height - buttonSize.height - sideInset), size: buttonSize)
|
||||||
|
}
|
||||||
|
} else if let buttonView = strongSelf.button.view, buttonView.superview != nil {
|
||||||
|
buttonView.removeFromSuperview()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
12
submodules/TelegramUI/Images.xcassets/Premium/Perk/PaidMessages.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Premium/Perk/PaidMessages.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "paidmessages.pdf",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
submodules/TelegramUI/Images.xcassets/Premium/Perk/PaidMessages.imageset/paidmessages.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Premium/Perk/PaidMessages.imageset/paidmessages.pdf
vendored
Normal file
Binary file not shown.
@ -2486,6 +2486,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
mappedSource = .messageEffects
|
mappedSource = .messageEffects
|
||||||
case .animatedEmoji:
|
case .animatedEmoji:
|
||||||
mappedSource = .animatedEmoji
|
mappedSource = .animatedEmoji
|
||||||
|
case .paidMessages:
|
||||||
|
mappedSource = .paidMessages
|
||||||
}
|
}
|
||||||
let controller = PremiumIntroScreen(context: context, source: mappedSource, modal: modal, forceDark: forceDark)
|
let controller = PremiumIntroScreen(context: context, source: mappedSource, modal: modal, forceDark: forceDark)
|
||||||
controller.wasDismissed = dismissed
|
controller.wasDismissed = dismissed
|
||||||
@ -2542,6 +2544,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
mappedSubject = .folderTags
|
mappedSubject = .folderTags
|
||||||
case .messageEffects:
|
case .messageEffects:
|
||||||
mappedSubject = .messageEffects
|
mappedSubject = .messageEffects
|
||||||
|
case .paidMessages:
|
||||||
|
mappedSubject = .paidMessages
|
||||||
case .business:
|
case .business:
|
||||||
mappedSubject = .business
|
mappedSubject = .business
|
||||||
buttonText = presentationData.strings.Chat_EmptyStateIntroFooterPremiumActionButton
|
buttonText = presentationData.strings.Chat_EmptyStateIntroFooterPremiumActionButton
|
||||||
|
Loading…
x
Reference in New Issue
Block a user