From 8f51eec89b641c640b05000f967e0491908a1fdc Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sun, 17 Dec 2023 14:07:31 +0400 Subject: [PATCH] Various improvements --- .../Telegram-iOS/en.lproj/Localizable.strings | 51 +- .../Sources/AccountContext.swift | 79 +- .../AvatarNode/Sources/AvatarNode.swift | 2 - .../ChatMessageInteractiveMediaBadge.swift | 4 +- submodules/Display/Source/TextNode.swift | 10 +- .../Sources/DrawingStickerEntityView.swift | 14 +- .../Sources/PremiumBoostLevelsScreen.swift | 1617 +++++++++++++++++ .../Sources/PremiumBoostScreen.swift | 8 +- .../Sources/PremiumLimitScreen.swift | 4 - .../ChatMessageAttachedContentNode.swift | 8 +- .../StringForMessageTimestampStatus.swift | 2 +- ...ChatMessageGiveawayBubbleContentNode.swift | 9 +- .../ChatMessageInteractiveFileNode.swift | 7 +- .../ChatMessageInteractiveMediaNode.swift | 4 + .../Sources/ChatMessageDateHeader.swift | 1 + .../ChatMessageTextBubbleContentNode.swift | 4 +- .../Sources/DrawingMessageRenderer.swift | 61 +- .../Sources/MediaEditorScreen.swift | 1 + .../Sources/PeerInfoScreen.swift | 400 ++-- .../Sources/ChannelAppearanceScreen.swift | 95 +- .../Sources/EditableTokenListNode.swift | 1 + .../Premium/BoostPerk/Contents.json | 9 + .../CoverColor.imageset/Contents.json | 12 + .../CoverColor.imageset/covercolor_30.pdf | 298 +++ .../CoverLogo.imageset/Contents.json | 12 + .../CoverLogo.imageset/coverlogo_30.pdf | 246 +++ .../CustomWallpaper.imageset/Contents.json | 12 + .../backgroundphoto_30.pdf | 261 +++ .../EmojiStatus.imageset/Contents.json | 12 + .../EmojiStatus.imageset/status_30.pdf | 132 ++ .../LinkColor.imageset/Contents.json | 12 + .../LinkColor.imageset/linkcolor_30.pdf | 219 +++ .../BoostPerk/LinkLogo.imageset/Contents.json | 12 + .../LinkLogo.imageset/linkicon_30.pdf | 218 +++ .../NameColor.imageset/Contents.json | 12 + .../NameColor.imageset/namecolor_30.pdf | 290 +++ .../BoostPerk/Reaction.imageset/Contents.json | 12 + .../Reaction.imageset/reaction_30.pdf | 95 + .../BoostPerk/Story.imageset/Contents.json | 12 + .../Story.imageset/storiescircle_30.pdf | 149 ++ .../Wallpaper.imageset/Contents.json | 12 + .../Wallpaper.imageset/background_30.pdf | 239 +++ .../TelegramUI/Sources/ChatController.swift | 39 +- .../Sources/SharedAccountContext.swift | 67 + 44 files changed, 4381 insertions(+), 383 deletions(-) create mode 100644 submodules/PremiumUI/Sources/PremiumBoostLevelsScreen.swift create mode 100644 submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CoverColor.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CoverColor.imageset/covercolor_30.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CoverLogo.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CoverLogo.imageset/coverlogo_30.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CustomWallpaper.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CustomWallpaper.imageset/backgroundphoto_30.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/EmojiStatus.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/EmojiStatus.imageset/status_30.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/LinkColor.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/LinkColor.imageset/linkcolor_30.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/LinkLogo.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/LinkLogo.imageset/linkicon_30.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/NameColor.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/NameColor.imageset/namecolor_30.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Reaction.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Reaction.imageset/reaction_30.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Story.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Story.imageset/storiescircle_30.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Wallpaper.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Wallpaper.imageset/background_30.pdf diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 6bf77be31e..02f74c54cc 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -10226,6 +10226,7 @@ Sorry for the inconvenience."; "ChannelBoost.MoreBoosts.Title" = "More Boosts Needed"; "ChannelBoost.MoreBoosts.Text" = "To boost **%1$@** again, gift **Telegram Premium** to a friend and get **%2$@** additional boosts."; +"ChannelBoost.MoreBoosts.Gift" = "Gift Premium"; "BoostGift.Title" = "Boosts via Gifts"; "BoostGift.Description" = "Get more boosts for your channel by gifting\nPremium to your subscribers."; @@ -10658,9 +10659,6 @@ Sorry for the inconvenience."; "Chat.Giveaway.Message.WinnersInfo.One" = "The winner received their gift link in a private message."; "Chat.Giveaway.Message.WinnersInfo.Many" = "All winners received gift links in private messages."; -"ChannelBoost.Wallpaper" = "Set Wallpaper"; -"ChannelBoost.WallpaperText" = "Your channel needs **Level %1$@** to set custom wallpaper.\n\nAsk your **Premium** subscribers to boost your channel with this link:"; - "Settings.PremiumGift" = "Premium Gifting"; "Story.ViewList.ContextSortChannelInfo" = "Choose the order for the list of reactions."; @@ -10706,3 +10704,50 @@ Sorry for the inconvenience."; "Premium.Gift.UsedLink.Text" = "This link was used to activate a **Telegram Premium** subscription."; "Premium.WhatsIncluded" = "WHAT'S INCLUDED"; + + +"ChannelBoost.Table.Level_1" = "Level %@"; +"ChannelBoost.Table.Level_any" = "Level %@"; + +"ChannelBoost.Table.LevelUnlocks_1" = "Level %@ Unlocks:"; +"ChannelBoost.Table.LevelUnlocks_any" = "Level %@ Unlocks:"; + +"ChannelBoost.Table.StoriesPerDay_1" = "%@ Story Per Day"; +"ChannelBoost.Table.StoriesPerDay_any" = "%@ Stories Per Day"; +"ChannelBoost.Table.CustomReactions_1" = "%@ Custom Reaction"; +"ChannelBoost.Table.CustomReactions_any" = "%@ Custom Reactions"; +"ChannelBoost.Table.NameColor_1" = "%@ Channel Name Color"; +"ChannelBoost.Table.NameColor_any" = "%@ Channel Name Colors"; +"ChannelBoost.Table.ProfileColor_1" = "%@ Color for Channel Cover"; +"ChannelBoost.Table.ProfileColor_any" = "%@ Colors for Channel Cover"; +"ChannelBoost.Table.ProfileLogo" = "Custom Logo for Channel Cover"; +"ChannelBoost.Table.StyleForHeaders_1" = "%@ Style for Links and Quotes"; +"ChannelBoost.Table.StyleForHeaders_any" = "%@ Styles for Links and Quotes"; +"ChannelBoost.Table.HeadersLogo" = "Custom Logo for Links and Quotes"; +"ChannelBoost.Table.EmojiStatus" = "1000+ Emoji Statuses"; +"ChannelBoost.Table.Wallpaper_1" = "%@ Channel Background"; +"ChannelBoost.Table.Wallpaper_any" = "%@ Channel Backgrounds"; +"ChannelBoost.Table.CustomWallpaper" = "Custom Channel Background"; + +"ChannelBoost.AskToBoost" = "Ask your **Premium** subscribers to boost your channel with this link:"; + +"ChannelBoost.NameColor" = "Enable Colors"; +"ChannelBoost.EnableNameColorLevelText" = "Your channel needs **Level %1$@** to change channel color."; + +"ChannelBoost.NameIcon" = "Set Link Icon"; +"ChannelBoost.EnableNameIconLevelText" = "Your channel needs **Level %1$@** to change link icon."; + +"ChannelBoost.ProfileColor" = "Set Cover Color"; +"ChannelBoost.EnableProfileColorLevelText" = "Your channel needs **Level %1$@** to change channel cover color."; + +"ChannelBoost.ProfileIcon" = "Set Cover Icon"; +"ChannelBoost.EnableProfileIconLevelText" = "Your channel needs **Level %1$@** to change channel cover icon."; + +"ChannelBoost.EmojiStatus" = "Use Emoji Statuses"; +"ChannelBoost.EnableEmojiStatusLevelText" = "Your channel needs **Level %1$@** to use emoji statuses."; + +"ChannelBoost.Wallpaper" = "Set Channel Background"; +"ChannelBoost.EnableWallpaperLevelText" = "Your channel needs **Level %1$@** to set channel background."; + +"ChannelBoost.CustomWallpaper" = "Set Custom Channel Background"; +"ChannelBoost.EnableCustomWallpaperLevelText" = "Your channel needs **Level %1$@** to set custom channel background."; diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index c8ceda7e02..c1e128e786 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -941,6 +941,7 @@ public protocol SharedAccountContext: AnyObject { func makePremiumIntroController(context: AccountContext, source: PremiumIntroSource, forceDark: Bool, dismissed: (() -> Void)?) -> ViewController func makePremiumDemoController(context: AccountContext, subject: PremiumDemoSubject, action: @escaping () -> Void) -> ViewController func makePremiumLimitController(context: AccountContext, subject: PremiumLimitSubject, count: Int32, forceDark: Bool, cancel: @escaping () -> Void, action: @escaping () -> Bool) -> ViewController + func makePremiumGiftController(context: AccountContext) -> ViewController func makeStickerPackScreen(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)?, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], loadedStickerPacks: [LoadedStickerPack], parentNavigationController: NavigationController?, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?) -> ViewController @@ -1102,7 +1103,22 @@ public protocol AccountContext: AnyObject { public struct PremiumConfiguration { public static var defaultValue: PremiumConfiguration { - return PremiumConfiguration(isPremiumDisabled: false, showPremiumGiftInAttachMenu: false, showPremiumGiftInTextField: false, giveawayGiftsPurchaseAvailable: false, boostsPerGiftCount: 3, minChannelNameColorLevel: 5, audioTransciptionTrialMaxDuration: 300, audioTransciptionTrialCount: 2, minChannelWallpaperLevel: 5) + return PremiumConfiguration( + isPremiumDisabled: false, + showPremiumGiftInAttachMenu: false, + showPremiumGiftInTextField: false, + giveawayGiftsPurchaseAvailable: false, + boostsPerGiftCount: 3, + audioTransciptionTrialMaxDuration: 300, + audioTransciptionTrialCount: 2, + minChannelNameColorLevel: 1, + minChannelNameIconLevel: 4, + minChannelProfileColorLevel: 5, + minChannelProfileIconLevel: 7, + minChannelEmojiStatusLevel: 8, + minChannelWallpaperLevel: 9, + minChannelCustomWallpaperLevel: 10 + ) } public let isPremiumDisabled: Bool @@ -1110,38 +1126,73 @@ public struct PremiumConfiguration { public let showPremiumGiftInTextField: Bool public let giveawayGiftsPurchaseAvailable: Bool public let boostsPerGiftCount: Int32 - public let minChannelNameColorLevel: Int32 public let audioTransciptionTrialMaxDuration: Int32 public let audioTransciptionTrialCount: Int32 + public let minChannelNameColorLevel: Int32 + public let minChannelNameIconLevel: Int32 + public let minChannelProfileColorLevel: Int32 + public let minChannelProfileIconLevel: Int32 + public let minChannelEmojiStatusLevel: Int32 public let minChannelWallpaperLevel: Int32 + public let minChannelCustomWallpaperLevel: Int32 - fileprivate init(isPremiumDisabled: Bool, showPremiumGiftInAttachMenu: Bool, showPremiumGiftInTextField: Bool, giveawayGiftsPurchaseAvailable: Bool, boostsPerGiftCount: Int32, minChannelNameColorLevel: Int32, audioTransciptionTrialMaxDuration: Int32, audioTransciptionTrialCount: Int32, minChannelWallpaperLevel: Int32) { + fileprivate init( + isPremiumDisabled: Bool, + showPremiumGiftInAttachMenu: Bool, + showPremiumGiftInTextField: Bool, + giveawayGiftsPurchaseAvailable: Bool, + boostsPerGiftCount: Int32, + audioTransciptionTrialMaxDuration: Int32, + audioTransciptionTrialCount: Int32, + minChannelNameColorLevel: Int32, + minChannelNameIconLevel: Int32, + minChannelProfileColorLevel: Int32, + minChannelProfileIconLevel: Int32, + minChannelEmojiStatusLevel: Int32, + minChannelWallpaperLevel: Int32, + minChannelCustomWallpaperLevel: Int32 + + ) { self.isPremiumDisabled = isPremiumDisabled self.showPremiumGiftInAttachMenu = showPremiumGiftInAttachMenu self.showPremiumGiftInTextField = showPremiumGiftInTextField self.giveawayGiftsPurchaseAvailable = giveawayGiftsPurchaseAvailable self.boostsPerGiftCount = boostsPerGiftCount - self.minChannelNameColorLevel = minChannelNameColorLevel self.audioTransciptionTrialMaxDuration = audioTransciptionTrialMaxDuration self.audioTransciptionTrialCount = audioTransciptionTrialCount + self.minChannelNameColorLevel = minChannelNameColorLevel + self.minChannelNameIconLevel = minChannelNameIconLevel + self.minChannelProfileColorLevel = minChannelProfileColorLevel + self.minChannelProfileIconLevel = minChannelProfileIconLevel + self.minChannelEmojiStatusLevel = minChannelEmojiStatusLevel self.minChannelWallpaperLevel = minChannelWallpaperLevel + self.minChannelCustomWallpaperLevel = minChannelCustomWallpaperLevel } public static func with(appConfiguration: AppConfiguration) -> PremiumConfiguration { + let defaultValue = self.defaultValue if let data = appConfiguration.data { + func get(_ value: Any?) -> Int32? { + return (value as? Double).flatMap(Int32.init) + } return PremiumConfiguration( - isPremiumDisabled: data["premium_purchase_blocked"] as? Bool ?? false, - showPremiumGiftInAttachMenu: data["premium_gift_attach_menu_icon"] as? Bool ?? false, - showPremiumGiftInTextField: data["premium_gift_text_field_icon"] as? Bool ?? false, - giveawayGiftsPurchaseAvailable: data["giveaway_gifts_purchase_available"] as? Bool ?? false, - boostsPerGiftCount: Int32(data["boosts_per_sent_gift"] as? Double ?? 3), - minChannelNameColorLevel: Int32(data["channel_color_level_min"] as? Double ?? 5), - audioTransciptionTrialMaxDuration: Int32(data["transcribe_audio_trial_duration_max"] as? Double ?? 300), - audioTransciptionTrialCount: Int32(data["transcribe_audio_trial_weekly_number"] as? Double ?? 2), - minChannelWallpaperLevel: Int32(data["channel_wallpaper_level_min"] as? Double ?? 5) + isPremiumDisabled: data["premium_purchase_blocked"] as? Bool ?? defaultValue.isPremiumDisabled, + showPremiumGiftInAttachMenu: data["premium_gift_attach_menu_icon"] as? Bool ?? defaultValue.showPremiumGiftInAttachMenu, + showPremiumGiftInTextField: data["premium_gift_text_field_icon"] as? Bool ?? defaultValue.showPremiumGiftInTextField, + giveawayGiftsPurchaseAvailable: data["giveaway_gifts_purchase_available"] as? Bool ?? defaultValue.giveawayGiftsPurchaseAvailable, + boostsPerGiftCount: get(data["boosts_per_sent_gift"]) ?? defaultValue.boostsPerGiftCount, + audioTransciptionTrialMaxDuration: get(data["transcribe_audio_trial_duration_max"]) ?? defaultValue.audioTransciptionTrialMaxDuration, + audioTransciptionTrialCount: get(data["transcribe_audio_trial_weekly_number"]) ?? defaultValue.audioTransciptionTrialCount, + minChannelNameColorLevel: get(data["channel_color_level_min"]) ?? defaultValue.minChannelNameColorLevel, + minChannelNameIconLevel: get(data["channel_bg_icon_level_min"]) ?? defaultValue.minChannelNameIconLevel, + minChannelProfileColorLevel: get(data["channel_profile_color_level_min"]) ?? defaultValue.minChannelProfileColorLevel, + minChannelProfileIconLevel: get(data["channel_profile_bg_icon_level_min"]) ?? defaultValue.minChannelProfileIconLevel, + minChannelEmojiStatusLevel: get(data["channel_emoji_status_level_min"]) ?? defaultValue.minChannelEmojiStatusLevel, + minChannelWallpaperLevel: get(data["channel_wallpaper_level_min"]) ?? defaultValue.minChannelWallpaperLevel, + minChannelCustomWallpaperLevel: get(data["channel_custom_wallpaper_level_min"]) ?? defaultValue.minChannelCustomWallpaperLevel ) } else { - return .defaultValue + return defaultValue } } } diff --git a/submodules/AvatarNode/Sources/AvatarNode.swift b/submodules/AvatarNode/Sources/AvatarNode.swift index 805c613410..29a0223254 100644 --- a/submodules/AvatarNode/Sources/AvatarNode.swift +++ b/submodules/AvatarNode/Sources/AvatarNode.swift @@ -773,8 +773,6 @@ public final class AvatarNode: ASDisplayNode { } @objc override public class func draw(_ bounds: CGRect, withParameters parameters: Any?, isCancelled: () -> Bool, isRasterizing: Bool) { - assertNotOnMainThread() - let context = UIGraphicsGetCurrentContext()! if !isRasterizing { diff --git a/submodules/ChatMessageInteractiveMediaBadge/Sources/ChatMessageInteractiveMediaBadge.swift b/submodules/ChatMessageInteractiveMediaBadge/Sources/ChatMessageInteractiveMediaBadge.swift index 611a6966d5..c1f55412ec 100644 --- a/submodules/ChatMessageInteractiveMediaBadge/Sources/ChatMessageInteractiveMediaBadge.swift +++ b/submodules/ChatMessageInteractiveMediaBadge/Sources/ChatMessageInteractiveMediaBadge.swift @@ -51,8 +51,8 @@ public final class ChatMessageInteractiveMediaBadge: ASDisplayNode { private var iconName: String? private let backgroundNode: ASImageNode - private let durationNode: ASTextNode - private var sizeNode: ASTextNode? + public let durationNode: ASTextNode + public private(set) var sizeNode: ASTextNode? private var measureNode: ASTextNode private var iconNode: ASImageNode? private var mediaDownloadStatusNode: RadialStatusNode? diff --git a/submodules/Display/Source/TextNode.swift b/submodules/Display/Source/TextNode.swift index cabd9cb729..387a9ff316 100644 --- a/submodules/Display/Source/TextNode.swift +++ b/submodules/Display/Source/TextNode.swift @@ -1485,7 +1485,7 @@ open class TextNode: ASDisplayNode { var blockQuotes: [TextNodeBlockQuote] = [] - for i in 0 ..< calculatedSegments.count { + loop: for i in 0 ..< calculatedSegments.count { let segment = calculatedSegments[i] if i != 0 { if segment.blockQuote != nil { @@ -1510,6 +1510,10 @@ open class TextNode: ASDisplayNode { } for line in segment.lines { + var isLastLine = false + if maximumNumberOfLines > 0 && lines.count == maximumNumberOfLines - 1 { + isLastLine = true + } line.frame = CGRect(origin: CGPoint(x: line.frame.origin.x, y: -insets.bottom + size.height + line.frame.size.height), size: line.frame.size) line.frame.size.width += max(0.0, segment.additionalWidth - 2.0) //line.frame.size.width = max(blockWidth, line.frame.size.width) @@ -1575,6 +1579,10 @@ open class TextNode: ASDisplayNode { } lines.append(line) + + if isLastLine { + break loop + } } let blockMaxY = size.height - insets.bottom diff --git a/submodules/DrawingUI/Sources/DrawingStickerEntityView.swift b/submodules/DrawingUI/Sources/DrawingStickerEntityView.swift index 28d9f96e93..a2ce71b0a3 100644 --- a/submodules/DrawingUI/Sources/DrawingStickerEntityView.swift +++ b/submodules/DrawingUI/Sources/DrawingStickerEntityView.swift @@ -1021,12 +1021,16 @@ final class DrawingStickerEntititySelectionView: DrawingEntitySelectionView { actualInset = floorToScreenPixels((self.bounds.width - width) / 2.0) var cornerRadius: CGFloat = 12.0 - self.scale + var count = 12 if case .message = entity.content { cornerRadius *= 2.1 + count = 20 + } else if case .image = entity.content { + count = 20 } let perimeter: CGFloat = 2.0 * (width + height - cornerRadius * (4.0 - .pi)) - let count = 12 + let dashLength = perimeter / CGFloat(count) self.border.lineDashPattern = [dashLength * relativeDashLength, dashLength * relativeDashLength] as [NSNumber] @@ -1041,18 +1045,12 @@ final class DrawingStickerEntititySelectionView: DrawingEntitySelectionView { self.border.path = UIBezierPath(ovalIn: CGRect(origin: CGPoint(x: inset, y: inset), size: CGSize(width: self.bounds.width - inset * 2.0, height: self.bounds.height - inset * 2.0))).cgPath } - let handles = [ - self.leftHandle, - self.rightHandle - ] - - for handle in handles { + for handle in [self.leftHandle, self.rightHandle] { handle.path = handlePath handle.bounds = bounds handle.lineWidth = lineWidth } - self.leftHandle.position = CGPoint(x: actualInset, y: self.bounds.midY) self.rightHandle.position = CGPoint(x: self.bounds.maxX - actualInset, y: self.bounds.midY) } diff --git a/submodules/PremiumUI/Sources/PremiumBoostLevelsScreen.swift b/submodules/PremiumUI/Sources/PremiumBoostLevelsScreen.swift new file mode 100644 index 0000000000..392fd6991b --- /dev/null +++ b/submodules/PremiumUI/Sources/PremiumBoostLevelsScreen.swift @@ -0,0 +1,1617 @@ +import Foundation +import UIKit +import Display +import AsyncDisplayKit +import TelegramCore +import Postbox +import SwiftSignalKit +import AccountContext +import TelegramPresentationData +import TelegramUIPreferences +import PresentationDataUtils +import ComponentFlow +import ViewControllerComponent +import MultilineTextComponent +import BalancedTextComponent +import BundleIconComponent +import Markdown +import TextFormat +import SolidRoundedButtonComponent +import BlurredBackgroundComponent +import UndoUI + +public enum BoostSubject: Equatable { + case stories + case channelReactions(reactionCount: Int32) + case nameColors + case nameIcon + case profileColors + case profileIcon + case emojiStatus + case wallpaper + case customWallpaper + + public func requiredLevel(_ configuration: PremiumConfiguration) -> Int32 { + switch self { + case .stories: + return 1 + case let .channelReactions(reactionCount): + return reactionCount + case .nameColors: + return configuration.minChannelNameColorLevel + case .nameIcon: + return configuration.minChannelNameIconLevel + case .profileColors: + return configuration.minChannelProfileColorLevel + case .profileIcon: + return configuration.minChannelProfileIconLevel + case .emojiStatus: + return configuration.minChannelEmojiStatusLevel + case .wallpaper: + return configuration.minChannelWallpaperLevel + case .customWallpaper: + return configuration.minChannelCustomWallpaperLevel + } + } +} + +private final class LevelHeaderComponent: CombinedComponent { + let theme: PresentationTheme + let text: String + + init( + theme: PresentationTheme, + text: String + ) { + self.theme = theme + self.text = text + } + + static func ==(lhs: LevelHeaderComponent, rhs: LevelHeaderComponent) -> Bool { + if lhs.theme !== rhs.theme { + return false + } + if lhs.text != rhs.text { + return false + } + return true + } + + static var body: Body { + let background = Child(RoundedRectangle.self) + let text = Child(MultilineTextComponent.self) + let leftLine = Child(Rectangle.self) + let rightLine = Child(Rectangle.self) + + return { context in + let component = context.component + + let outerInset: CGFloat = 28.0 + let innerInset: CGFloat = 9.0 + + let height: CGFloat = 50.0 + let backgroundHeight: CGFloat = 34.0 + let text = text.update( + component: MultilineTextComponent( + text: .plain(NSAttributedString(string: component.text, font: Font.semibold(15.0), textColor: .white)), + horizontalAlignment: .center + ), + availableSize: context.availableSize, + transition: .immediate + ) + + let backgroundWidth: CGFloat = floor(text.size.width + 21.0) + + let background = background.update( + component: RoundedRectangle(colors: [UIColor(rgb: 0x9076ff), UIColor(rgb: 0xbc6de8)], cornerRadius: backgroundHeight / 2.0, gradientDirection: .horizontal), + availableSize: CGSize(width: backgroundWidth, height: backgroundHeight), + transition: .immediate + ) + context.add(background + .position(CGPoint(x: context.availableSize.width / 2.0, y: height / 2.0)) + ) + context.add(text + .position(CGPoint(x: context.availableSize.width / 2.0, y: height / 2.0)) + ) + + let remainingWidth = (context.availableSize.width - background.size.width) / 2.0 + let lineSize = remainingWidth - outerInset - innerInset + let lineWidth = 1.0 - UIScreenPixel + + let leftLine = leftLine.update( + component: Rectangle( + color: component.theme.actionSheet.secondaryTextColor.withMultipliedAlpha(0.5) + ), + availableSize: CGSize(width: lineSize, height: lineWidth), + transition: .immediate + ) + context.add(leftLine + .position(CGPoint(x: outerInset + lineSize / 2.0, y: height / 2.0)) + ) + + let rightLine = rightLine.update( + component: Rectangle( + color: component.theme.actionSheet.secondaryTextColor.withMultipliedAlpha(0.5) + ), + availableSize: CGSize(width: lineSize, height: lineWidth), + transition: .immediate + ) + context.add(rightLine + .position(CGPoint(x: context.availableSize.width - outerInset - lineSize / 2.0, y: height / 2.0)) + ) + + return CGSize(width: context.availableSize.width, height: height) + } + } +} + +private final class LevelPerkComponent: CombinedComponent { + let theme: PresentationTheme + let iconName: String + let text: String + + init( + theme: PresentationTheme, + iconName: String, + text: String + ) { + self.theme = theme + self.iconName = iconName + self.text = text + } + + static func ==(lhs: LevelPerkComponent, rhs: LevelPerkComponent) -> Bool { + if lhs.theme !== rhs.theme { + return false + } + if lhs.iconName != rhs.iconName { + return false + } + if lhs.text != rhs.text { + return false + } + return true + } + + static var body: Body { + let icon = Child(BundleIconComponent.self) + let text = Child(MultilineTextComponent.self) + + return { context in + let component = context.component + + let outerInset: CGFloat = 28.0 + let height: CGFloat = 44.0 + + let icon = icon.update( + component: BundleIconComponent( + name: component.iconName, + tintColor: component.theme.actionSheet.controlAccentColor + ), + availableSize: context.availableSize, + transition: .immediate + ) + context.add(icon + .position(CGPoint(x: outerInset + icon.size.width / 2.0, y: height / 2.0)) + ) + + let text = text.update( + component: MultilineTextComponent( + text: .plain(NSAttributedString(string: component.text, font: Font.semibold(15.0), textColor: component.theme.actionSheet.primaryTextColor)), + horizontalAlignment: .center + ), + availableSize: CGSize(width: context.availableSize.width, height: context.availableSize.height), + transition: .immediate + ) + context.add(text + .position(CGPoint(x: outerInset * 2.0 + 18.0 + text.size.width / 2.0, y: height / 2.0)) + ) + + return CGSize(width: context.availableSize.width, height: height) + } + } +} + +private final class LevelSectionComponent: CombinedComponent { + enum Perk: Equatable { + case story(Int32) + case reaction(Int32) + case nameColor(Int32) + case profileColor(Int32) + case profileIcon + case linkColor(Int32) + case linkIcon + case emojiStatus + case wallpaper(Int32) + case customWallpaper + + func title(strings: PresentationStrings) -> String { + switch self { + case let .story(value): + return strings.ChannelBoost_Table_StoriesPerDay(value) + case let .reaction(value): + return strings.ChannelBoost_Table_CustomReactions(value) + case let .nameColor(value): + return strings.ChannelBoost_Table_NameColor(value) + case let .profileColor(value): + return strings.ChannelBoost_Table_ProfileColor(value) + case .profileIcon: + return strings.ChannelBoost_Table_ProfileLogo + case let .linkColor(value): + return strings.ChannelBoost_Table_StyleForHeaders(value) + case .linkIcon: + return strings.ChannelBoost_Table_HeadersLogo + case .emojiStatus: + return strings.ChannelBoost_Table_EmojiStatus + case let .wallpaper(value): + return strings.ChannelBoost_Table_Wallpaper(value) + case .customWallpaper: + return strings.ChannelBoost_Table_CustomWallpaper + } + } + + var iconName: String { + switch self { + case .story: + return "Premium/BoostPerk/Story" + case .reaction: + return "Premium/BoostPerk/Reaction" + case .nameColor: + return "Premium/BoostPerk/NameColor" + case .profileColor: + return "Premium/BoostPerk/CoverColor" + case .profileIcon: + return "Premium/BoostPerk/CoverLogo" + case .linkColor: + return "Premium/BoostPerk/LinkColor" + case .linkIcon: + return "Premium/BoostPerk/LinkLogo" + case .emojiStatus: + return "Premium/BoostPerk/EmojiStatus" + case .wallpaper: + return "Premium/BoostPerk/Wallpaper" + case .customWallpaper: + return "Premium/BoostPerk/CustomWallpaper" + } + } + } + + let theme: PresentationTheme + let strings: PresentationStrings + let level: Int32 + let isFirst: Bool + let perks: [Perk] + + init( + theme: PresentationTheme, + strings: PresentationStrings, + level: Int32, + isFirst: Bool, + perks: [Perk] + ) { + self.theme = theme + self.strings = strings + self.level = level + self.isFirst = isFirst + self.perks = perks + } + + static func ==(lhs: LevelSectionComponent, rhs: LevelSectionComponent) -> Bool { + if lhs.theme !== rhs.theme { + return false + } + if lhs.level != rhs.level { + return false + } + if lhs.isFirst != rhs.isFirst { + return false + } + if lhs.perks != rhs.perks { + return false + } + return true + } + + static var body: Body { + let header = Child(LevelHeaderComponent.self) + let list = Child(List.self) + + return { context in + let component = context.component + + let header = header.update( + component: LevelHeaderComponent(theme: component.theme, text: component.isFirst ? component.strings.ChannelBoost_Table_LevelUnlocks(component.level) : component.strings.ChannelBoost_Table_Level(component.level)), + availableSize: context.availableSize, + transition: .immediate + ) + context.add(header + .position(CGPoint(x: context.availableSize.width / 2.0, y: header.size.height / 2.0))) + + let items: [AnyComponentWithIdentity] = component.perks.enumerated().map { index, value in + AnyComponentWithIdentity( + id: index, component: AnyComponent( + LevelPerkComponent( + theme: component.theme, + iconName: value.iconName, + text: value.title(strings: component.strings) + ) + ) + ) + } + + let list = list.update( + component: List(items), + availableSize: CGSize(width: context.availableSize.width, height: 10000.0), + transition: context.transition + ) + context.add(list + .position(CGPoint(x: context.availableSize.width / 2.0, y: header.size.height + list.size.height / 2.0))) + + let height = header.size.height + list.size.height + return CGSize(width: context.availableSize.width, height: height) + } + } +} + + + +private final class LimitSheetContent: CombinedComponent { + typealias EnvironmentType = (Empty, ScrollChildEnvironment) + + let context: AccountContext + let theme: PresentationTheme + let strings: PresentationStrings + let insets: UIEdgeInsets + + let peer: EnginePeer + let subject: BoostSubject + let status: ChannelBoostStatus + + let copyLink: (String) -> Void + let dismiss: () -> Void + let openStats: (() -> Void)? + let openGift: (() -> Void)? + + init(context: AccountContext, + theme: PresentationTheme, + strings: PresentationStrings, + insets: UIEdgeInsets, + peer: EnginePeer, + subject: BoostSubject, + status: ChannelBoostStatus, + copyLink: @escaping (String) -> Void, + dismiss: @escaping () -> Void, + openStats: (() -> Void)?, + openGift: (() -> Void)? + ) { + self.context = context + self.theme = theme + self.strings = strings + self.insets = insets + self.peer = peer + self.subject = subject + self.status = status + self.copyLink = copyLink + self.dismiss = dismiss + self.openStats = openStats + self.openGift = openGift + } + + static func ==(lhs: LimitSheetContent, rhs: LimitSheetContent) -> Bool { + if lhs.context !== rhs.context { + return false + } + if lhs.theme !== rhs.theme { + return false + } + if lhs.insets != rhs.insets { + return false + } + if lhs.peer != rhs.peer { + return false + } + if lhs.subject != rhs.subject { + return false + } + if lhs.status != rhs.status { + return false + } + return true + } + + final class State: ComponentState { + var cachedChevronImage: (UIImage, PresentationTheme)? + } + + func makeState() -> State { + return State() + } + + static var body: Body { + let text = Child(BalancedTextComponent.self) + let limit = Child(PremiumLimitDisplayComponent.self) + let linkButton = Child(SolidRoundedButtonComponent.self) + let button = Child(SolidRoundedButtonComponent.self) + + let orLeftLine = Child(Rectangle.self) + let orRightLine = Child(Rectangle.self) + let orText = Child(MultilineTextComponent.self) + let giftText = Child(BalancedTextComponent.self) + + let levels = Child(List.self) + + return { context in + let component = context.component + let theme = component.theme + let strings = component.strings + + let state = context.state + + let premiumConfiguration = PremiumConfiguration.with(appConfiguration: component.context.currentAppConfiguration.with { $0 }) + let sideInset: CGFloat = 16.0 // + environment.safeInsets.left + let textSideInset: CGFloat = 32.0 // + environment.safeInsets.left + + let iconName = "Premium/Boost" + let badgeText = "\(component.status.boosts)" + + var remaining: Int? + if let nextLevelBoosts = component.status.nextLevelBoosts { + remaining = nextLevelBoosts - component.status.boosts + } + + var textString = "" + let actionButtonText = strings.ChannelBoost_CopyLink + let buttonIconName = "Premium/CopyLink" + + if let remaining { + var needsSecondParagraph = true + let storiesString = strings.ChannelBoost_StoriesPerDay(Int32(component.status.level) + 1) + let valueString = strings.ChannelBoost_MoreBoosts(Int32(remaining)) + switch component.subject { + case .stories: + if component.status.level == 0 { + textString = strings.ChannelBoost_EnableStoriesText(valueString).string + } else { + textString = strings.ChannelBoost_IncreaseLimitText(valueString, storiesString).string + } + needsSecondParagraph = false + case let .channelReactions(reactionCount): + textString = strings.ChannelBoost_CustomReactionsText("\(reactionCount)", "\(reactionCount)").string + needsSecondParagraph = false + case .nameColors: + textString = strings.ChannelBoost_EnableNameColorLevelText("\(premiumConfiguration.minChannelNameColorLevel)").string + case .nameIcon: + textString = strings.ChannelBoost_EnableNameIconLevelText("\(premiumConfiguration.minChannelNameIconLevel)").string + case .profileColors: + textString = strings.ChannelBoost_EnableProfileColorLevelText("\(premiumConfiguration.minChannelProfileColorLevel)").string + case .profileIcon: + textString = strings.ChannelBoost_EnableProfileIconLevelText("\(premiumConfiguration.minChannelProfileIconLevel)").string + case .emojiStatus: + textString = strings.ChannelBoost_EnableEmojiStatusLevelText("\(premiumConfiguration.minChannelEmojiStatusLevel)").string + case .wallpaper: + textString = strings.ChannelBoost_EnableWallpaperLevelText("\(premiumConfiguration.minChannelWallpaperLevel)").string + case .customWallpaper: + textString = strings.ChannelBoost_EnableCustomWallpaperLevelText("\(premiumConfiguration.minChannelCustomWallpaperLevel)").string + } + + if needsSecondParagraph { + textString += "\n\n\(strings.ChannelBoost_AskToBoost)" + } + } else { + let storiesString = strings.ChannelBoost_StoriesPerDay(Int32(component.status.level)) + textString = strings.ChannelBoost_MaxLevelReachedTextAuthor("\(component.status.level)", storiesString).string + } + + let defaultTitle = strings.ChannelBoost_Level("\(component.status.level)").string + let defaultValue = "" + let premiumValue = strings.ChannelBoost_Level("\(component.status.level + 1)").string + let premiumTitle = "" + + let progress: CGFloat + if let nextLevelBoosts = component.status.nextLevelBoosts { + progress = CGFloat(component.status.boosts - component.status.currentLevelBoosts) / CGFloat(nextLevelBoosts - component.status.currentLevelBoosts) + } else { + progress = 1.0 + } + + let contentSize: CGSize + + let textFont = Font.regular(15.0) + let boldTextFont = Font.semibold(15.0) + let textColor = theme.actionSheet.primaryTextColor + let linkColor = theme.actionSheet.controlAccentColor + let markdownAttributes = MarkdownAttributes(body: MarkdownAttributeSet(font: textFont, textColor: textColor), bold: MarkdownAttributeSet(font: boldTextFont, textColor: textColor), link: MarkdownAttributeSet(font: textFont, textColor: linkColor), linkAttribute: { contents in + return (TelegramTextAttributes.URL, contents) + }) + + let textChild = text.update( + component: BalancedTextComponent( + text: .markdown(text: textString, attributes: markdownAttributes), + horizontalAlignment: .center, + maximumNumberOfLines: 0, + lineSpacing: 0.1 + ), + availableSize: CGSize(width: context.availableSize.width - textSideInset * 2.0, height: context.availableSize.height), + transition: .immediate + ) + + let gradientColors = [ + UIColor(rgb: 0x0077ff), + UIColor(rgb: 0x6b93ff), + UIColor(rgb: 0x8878ff), + UIColor(rgb: 0xe46ace) + ] + let buttonGradientColors = [ + UIColor(rgb: 0x007afe), + UIColor(rgb: 0x5494ff) + ] + + let limitTransition: Transition = .immediate + + let button = button.update( + component: SolidRoundedButtonComponent( + title: actionButtonText, + theme: SolidRoundedButtonComponent.Theme( + backgroundColor: .black, + backgroundColors: buttonGradientColors, + foregroundColor: .white + ), + font: .bold, + fontSize: 17.0, + height: 50.0, + cornerRadius: 10.0, + gloss: false, + iconName: buttonIconName, + animationName: nil, + iconPosition: .left, + action: { + component.copyLink(component.status.url) + component.dismiss() + } + ), + availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 50.0), + transition: context.transition + ) + + var buttonOffset: CGFloat = 0.0 + var textOffset: CGFloat = 184.0 + + let linkButton = linkButton.update( + component: SolidRoundedButtonComponent( + title: component.status.url.replacingOccurrences(of: "https://", with: ""), + theme: SolidRoundedButtonComponent.Theme( + backgroundColor: theme.list.itemBlocksSeparatorColor.withAlphaComponent(0.3), + backgroundColors: [], + foregroundColor: theme.list.itemPrimaryTextColor + ), + font: .regular, + fontSize: 17.0, + height: 50.0, + cornerRadius: 10.0, + action: { + component.copyLink(component.status.url) + component.dismiss() + } + ), + availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 50.0), + transition: context.transition + ) + buttonOffset += 66.0 + + let linkFrame = CGRect(origin: CGPoint(x: sideInset, y: textOffset + textChild.size.height + 24.0), size: linkButton.size) + context.add(linkButton + .position(CGPoint(x: linkFrame.midX, y: linkFrame.midY)) + ) + + let textSize = textChild.size + textOffset += textSize.height / 2.0 + + context.add(textChild + .position(CGPoint(x: context.availableSize.width / 2.0, y: textOffset)) + ) + + let limit = limit.update( + component: PremiumLimitDisplayComponent( + inactiveColor: theme.list.itemBlocksSeparatorColor.withAlphaComponent(0.3), + activeColors: gradientColors, + inactiveTitle: defaultTitle, + inactiveValue: defaultValue, + inactiveTitleColor: theme.list.itemPrimaryTextColor, + activeTitle: premiumTitle, + activeValue: premiumValue, + activeTitleColor: .white, + badgeIconName: iconName, + badgeText: badgeText, + badgePosition: progress, + badgeGraphPosition: progress, + invertProgress: true, + isPremiumDisabled: false + ), + availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: context.availableSize.height), + transition: limitTransition + ) + context.add(limit + .position(CGPoint(x: context.availableSize.width / 2.0, y: limit.size.height / 2.0 + 44.0)) + ) + + let buttonFrame = CGRect(origin: CGPoint(x: sideInset, y: textOffset + ceil(textSize.height / 2.0) + buttonOffset + 24.0), size: button.size) + context.add(button + .position(CGPoint(x: buttonFrame.midX, y: buttonFrame.midY)) + ) + + var additionalContentHeight: CGFloat = 0.0 + + if premiumConfiguration.giveawayGiftsPurchaseAvailable { + let orText = orText.update( + component: MultilineTextComponent(text: .plain(NSAttributedString(string: strings.ChannelBoost_Or, font: Font.regular(15.0), textColor: textColor.withAlphaComponent(0.8), paragraphAlignment: .center))), + availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: context.availableSize.height), + transition: .immediate + ) + context.add(orText + .position(CGPoint(x: context.availableSize.width / 2.0, y: buttonFrame.maxY + 27.0)) + ) + + let orLeftLine = orLeftLine.update( + component: Rectangle(color: theme.list.itemBlocksSeparatorColor.withAlphaComponent(0.3)), + availableSize: CGSize(width: 90.0, height: 1.0 - UIScreenPixel), + transition: .immediate + ) + context.add(orLeftLine + .position(CGPoint(x: context.availableSize.width / 2.0 - orText.size.width / 2.0 - 11.0 - 45.0, y: buttonFrame.maxY + 27.0)) + ) + + let orRightLine = orRightLine.update( + component: Rectangle(color: theme.list.itemBlocksSeparatorColor.withAlphaComponent(0.3)), + availableSize: CGSize(width: 90.0, height: 1.0 - UIScreenPixel), + transition: .immediate + ) + context.add(orRightLine + .position(CGPoint(x: context.availableSize.width / 2.0 + orText.size.width / 2.0 + 11.0 + 45.0, y: buttonFrame.maxY + 27.0)) + ) + + if state.cachedChevronImage == nil || state.cachedChevronImage?.1 !== theme { + state.cachedChevronImage = (generateTintedImage(image: UIImage(bundleImageName: "Settings/TextArrowRight"), color: linkColor)!, theme) + } + + + let giftString = strings.Premium_BoostByGiftDescription2 + let giftAttributedString = parseMarkdownIntoAttributedString(giftString, attributes: markdownAttributes).mutableCopy() as! NSMutableAttributedString + + if let range = giftAttributedString.string.range(of: ">"), let chevronImage = state.cachedChevronImage?.0 { + giftAttributedString.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: giftAttributedString.string)) + } + let giftText = giftText.update( + component: BalancedTextComponent( + text: .plain(giftAttributedString), + horizontalAlignment: .center, + maximumNumberOfLines: 0, + lineSpacing: 0.1, + highlightColor: linkColor.withAlphaComponent(0.2), + highlightAction: { _ in + return nil + }, + tapAction: { _, _ in + component.openGift?() + } + ), + availableSize: CGSize(width: context.availableSize.width - textSideInset * 2.0, height: context.availableSize.height), + transition: .immediate + ) + context.add(giftText + .position(CGPoint(x: context.availableSize.width / 2.0, y: buttonFrame.maxY + 50.0 + giftText.size.height / 2.0)) + ) + + additionalContentHeight += giftText.size.height + 50.0 + } + + + var nextLevels: ClosedRange? + if component.status.level < 10 { + nextLevels = Int32(component.status.level) + 1 ... 10 + } + + var levelsHeight: CGFloat = 0.0 + var levelItems: [AnyComponentWithIdentity] = [] + if let nextLevels { + for level in nextLevels { + var perks: [LevelSectionComponent.Perk] = [] + perks.append(.story(level)) + perks.append(.reaction(level)) + + if level >= premiumConfiguration.minChannelNameColorLevel { + perks.append(.nameColor(7)) + } + if level >= premiumConfiguration.minChannelProfileColorLevel { + let delta = min(level - premiumConfiguration.minChannelProfileColorLevel + 1, 2) + perks.append(.profileColor(8 * delta)) + } + if level >= premiumConfiguration.minChannelProfileIconLevel { + perks.append(.profileIcon) + } + if level >= premiumConfiguration.minChannelNameColorLevel { + let delta = min(level - premiumConfiguration.minChannelNameColorLevel + 1, 3) + perks.append(.linkColor(7 * delta)) + } + if level >= premiumConfiguration.minChannelNameIconLevel { + perks.append(.linkIcon) + } + if level >= premiumConfiguration.minChannelEmojiStatusLevel { + perks.append(.emojiStatus) + } + if level >= premiumConfiguration.minChannelWallpaperLevel { + perks.append(.wallpaper(8)) + } + if level >= premiumConfiguration.minChannelCustomWallpaperLevel { + perks.append(.customWallpaper) + } + + levelItems.append( + AnyComponentWithIdentity( + id: level, component: AnyComponent( + LevelSectionComponent( + theme: component.theme, + strings: component.strings, + level: level, + isFirst: levelItems.isEmpty, + perks: perks + ) + ) + ) + ) + } + } + + if !levelItems.isEmpty { + let levels = levels.update( + component: List(levelItems), + availableSize: CGSize(width: context.availableSize.width, height: 100000.0), + transition: context.transition + ) + context.add(levels + .position(CGPoint(x: context.availableSize.width / 2.0, y: buttonFrame.maxY + 23.0 + additionalContentHeight + levels.size.height / 2.0 )) + ) + levelsHeight = levels.size.height + 40.0 + } + + let bottomInset: CGFloat = 0.0 + contentSize = CGSize(width: context.availableSize.width, height: buttonFrame.maxY + additionalContentHeight + 5.0 + bottomInset + levelsHeight) + + return contentSize + } + } +} + + + +private final class BoostLevelsContainerComponent: CombinedComponent { + let context: AccountContext + let theme: PresentationTheme + let strings: PresentationStrings + + let peer: EnginePeer + let subject: BoostSubject + let status: ChannelBoostStatus + let copyLink: (String) -> Void + let dismiss: () -> Void + let openStats: () -> Void + let openGift: () -> Void + + init( + context: AccountContext, + theme: PresentationTheme, + strings: PresentationStrings, + peer: EnginePeer, + subject: BoostSubject, + status: ChannelBoostStatus, + copyLink: @escaping (String) -> Void, + dismiss: @escaping () -> Void, + openStats: @escaping () -> Void, + openGift: @escaping () -> Void + ) { + self.context = context + self.theme = theme + self.strings = strings + self.peer = peer + self.subject = subject + self.status = status + self.copyLink = copyLink + self.dismiss = dismiss + self.openStats = openStats + self.openGift = openGift + } + + static func ==(lhs: BoostLevelsContainerComponent, rhs: BoostLevelsContainerComponent) -> Bool { + if lhs.context !== rhs.context { + return false + } + if lhs.theme !== rhs.theme { + return false + } + if lhs.peer != rhs.peer { + return false + } + if lhs.subject != rhs.subject { + return false + } + if lhs.status != rhs.status { + return false + } + return true + } + + final class State: ComponentState { + var topContentOffset: CGFloat = 0.0 + var cachedStatsImage: (UIImage, PresentationTheme)? + var cachedCloseImage: (UIImage, PresentationTheme)? + } + + func makeState() -> State { + return State() + } + + static var body: Body { + let background = Child(Rectangle.self) + let scroll = Child(ScrollComponent.self) + let topPanel = Child(BlurredBackgroundComponent.self) + let topSeparator = Child(Rectangle.self) + let title = Child(MultilineTextComponent.self) + let statsButton = Child(Button.self) + let closeButton = Child(Button.self) + + return { context in + let state = context.state + + let theme = context.component.theme + let strings = context.component.context.sharedContext.currentPresentationData.with { $0 }.strings + + let topInset: CGFloat = 56.0 + + let component = context.component + + let scroll = scroll.update( + component: ScrollComponent( + content: AnyComponent( + LimitSheetContent( + context: component.context, + theme: component.theme, + strings: component.strings, + insets: .zero, + peer: component.peer, + subject: component.subject, + status: component.status, + copyLink: component.copyLink, + dismiss: component.dismiss, + openStats: component.openStats, + openGift: component.openGift + ) + ), + contentInsets: UIEdgeInsets(top: topInset, left: 0.0, bottom: 34.0, right: 0.0), + contentOffsetUpdated: { [weak state] topContentOffset, _ in + state?.topContentOffset = topContentOffset + Queue.mainQueue().justDispatch { + state?.updated(transition: .immediate) + } + }, + contentOffsetWillCommit: { _ in } + ), + availableSize: context.availableSize, + transition: context.transition + ) + + let background = background.update( + component: Rectangle(color: theme.overallDarkAppearance ? theme.list.blocksBackgroundColor : theme.list.plainBackgroundColor), + availableSize: scroll.size, + transition: context.transition + ) + context.add(background + .position(CGPoint(x: context.availableSize.width / 2.0, y: background.size.height / 2.0)) + ) + + context.add(scroll + .position(CGPoint(x: context.availableSize.width / 2.0, y: scroll.size.height / 2.0)) + ) + + let topPanel = topPanel.update( + component: BlurredBackgroundComponent( + color: theme.rootController.navigationBar.blurredBackgroundColor + ), + availableSize: CGSize(width: context.availableSize.width, height: topInset), + transition: context.transition + ) + + let topSeparator = topSeparator.update( + component: Rectangle( + color: theme.rootController.navigationBar.separatorColor + ), + availableSize: CGSize(width: context.availableSize.width, height: UIScreenPixel), + transition: context.transition + ) + + let titleString: String + if let _ = component.status.nextLevelBoosts { + switch component.subject { + case .stories: + if component.status.level == 0 { + titleString = strings.ChannelBoost_EnableStories + } else { + titleString = strings.ChannelBoost_IncreaseLimit + } + case .nameColors: + titleString = strings.ChannelBoost_NameColor + case .nameIcon: + titleString = strings.ChannelBoost_NameIcon + case .profileColors: + titleString = strings.ChannelBoost_ProfileColor + case .profileIcon: + titleString = strings.ChannelBoost_ProfileIcon + case .channelReactions: + titleString = strings.ChannelBoost_CustomReactions + case .emojiStatus: + titleString = strings.ChannelBoost_EmojiStatus + case .wallpaper: + titleString = strings.ChannelBoost_Wallpaper + case .customWallpaper: + titleString = strings.ChannelBoost_CustomWallpaper + } + } else { + titleString = strings.ChannelBoost_MaxLevelReached + } + + let title = title.update( + component: MultilineTextComponent( + text: .plain(NSAttributedString(string: titleString, font: Font.semibold(17.0), textColor: theme.rootController.navigationBar.primaryTextColor)), + horizontalAlignment: .center, + truncationType: .end, + maximumNumberOfLines: 1 + ), + availableSize: context.availableSize, + transition: context.transition + ) + + let topPanelAlpha: CGFloat = min(30.0, state.topContentOffset) / 30.0 + context.add(topPanel + .position(CGPoint(x: context.availableSize.width / 2.0, y: topPanel.size.height / 2.0)) + .opacity(topPanelAlpha) + ) + context.add(topSeparator + .position(CGPoint(x: context.availableSize.width / 2.0, y: topPanel.size.height)) + .opacity(topPanelAlpha) + ) + context.add(title + .position(CGPoint(x: context.availableSize.width / 2.0, y: topPanel.size.height / 2.0)) + ) + + let statsButton = statsButton.update( + component: Button( + content: AnyComponent( + BundleIconComponent( + name: "Premium/Stats", + tintColor: component.theme.list.itemAccentColor + ) + ), + action: { + component.dismiss() + Queue.mainQueue().after(0.35) { + component.openStats() + } + } + ).minSize(CGSize(width: 44.0, height: 44.0)), + availableSize: context.availableSize, + transition: .immediate + ) + context.add(statsButton + .position(CGPoint(x: 31.0, y: 28.0)) + ) + + let closeImage: UIImage + if let (image, theme) = state.cachedCloseImage, theme === component.theme { + closeImage = image + } else { + closeImage = generateCloseButtonImage(backgroundColor: UIColor(rgb: 0x808084, alpha: 0.1), foregroundColor: theme.actionSheet.inputClearButtonColor)! + state.cachedCloseImage = (closeImage, theme) + } + let closeButton = closeButton.update( + component: Button( + content: AnyComponent(Image(image: closeImage)), + action: { + component.dismiss() + } + ), + availableSize: CGSize(width: 30.0, height: 30.0), + transition: .immediate + ) + context.add(closeButton + .position(CGPoint(x: context.availableSize.width - closeButton.size.width, y: 28.0)) + ) + + return scroll.size + } + } +} + +public class PremiumBoostLevelsScreen: ViewController { + final class Node: ViewControllerTracingNode, UIScrollViewDelegate, UIGestureRecognizerDelegate { + private var presentationData: PresentationData + private weak var controller: PremiumBoostLevelsScreen? + + let dim: ASDisplayNode + let wrappingView: UIView + let containerView: UIView + + let contentView: ComponentHostView + + private(set) var isExpanded = false + private var panGestureRecognizer: UIPanGestureRecognizer? + private var panGestureArguments: (topInset: CGFloat, offset: CGFloat, scrollView: UIScrollView?, listNode: ListView?)? + + private var currentIsVisible: Bool = false + private var currentLayout: ContainerViewLayout? + + var isPremium: Bool? + var disposable: Disposable? + + init(context: AccountContext, controller: PremiumBoostLevelsScreen) { + self.presentationData = context.sharedContext.currentPresentationData.with { $0 } + if controller.forceDark { + self.presentationData = self.presentationData.withUpdated(theme: defaultDarkPresentationTheme) + } + self.presentationData = self.presentationData.withUpdated(theme: self.presentationData.theme.withModalBlocksBackground()) + + self.controller = controller + + self.dim = ASDisplayNode() + self.dim.alpha = 0.0 + self.dim.backgroundColor = UIColor(white: 0.0, alpha: 0.25) + + self.wrappingView = UIView() + self.containerView = UIView() + self.contentView = ComponentHostView() + + super.init() + + self.containerView.clipsToBounds = true + self.containerView.backgroundColor = self.presentationData.theme.overallDarkAppearance ? self.presentationData.theme.list.blocksBackgroundColor : self.presentationData.theme.list.plainBackgroundColor + + self.addSubnode(self.dim) + + self.view.addSubview(self.wrappingView) + self.wrappingView.addSubview(self.containerView) + self.containerView.addSubview(self.contentView) + } + + deinit { + self.disposable?.dispose() + } + + override func didLoad() { + super.didLoad() + + let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) + panRecognizer.delegate = self + panRecognizer.delaysTouchesBegan = false + panRecognizer.cancelsTouchesInView = true + self.panGestureRecognizer = panRecognizer + self.wrappingView.addGestureRecognizer(panRecognizer) + + self.dim.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:)))) + self.controller?.navigationBar?.updateBackgroundAlpha(0.0, transition: .immediate) + } + + @objc func dimTapGesture(_ recognizer: UITapGestureRecognizer) { + if case .ended = recognizer.state { + self.controller?.dismiss(animated: true) + } + } + + override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { + if let layout = self.currentLayout { + if case .regular = layout.metrics.widthClass { + return false + } + } + return true + } + + func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { + if gestureRecognizer is UIPanGestureRecognizer && otherGestureRecognizer is UIPanGestureRecognizer { + if let scrollView = otherGestureRecognizer.view as? UIScrollView { + if scrollView.contentSize.width > scrollView.contentSize.height { + return false + } + } + return true + } + return false + } + + private var isDismissing = false + func animateIn() { + ContainedViewLayoutTransition.animated(duration: 0.3, curve: .linear).updateAlpha(node: self.dim, alpha: 1.0) + + let targetPosition = self.containerView.center + let startPosition = targetPosition.offsetBy(dx: 0.0, dy: self.bounds.height) + + self.containerView.center = startPosition + let transition = ContainedViewLayoutTransition.animated(duration: 0.4, curve: .spring) + transition.animateView(allowUserInteraction: true, { + self.containerView.center = targetPosition + }, completion: { _ in + }) + } + + func animateOut(completion: @escaping () -> Void = {}) { + self.isDismissing = true + + let positionTransition: ContainedViewLayoutTransition = .animated(duration: 0.25, curve: .easeInOut) + positionTransition.updatePosition(layer: self.containerView.layer, position: CGPoint(x: self.containerView.center.x, y: self.bounds.height + self.containerView.bounds.height / 2.0), completion: { [weak self] _ in + self?.controller?.dismiss(animated: false, completion: completion) + }) + let alphaTransition: ContainedViewLayoutTransition = .animated(duration: 0.25, curve: .easeInOut) + alphaTransition.updateAlpha(node: self.dim, alpha: 0.0) + + self.controller?.updateModalStyleOverlayTransitionFactor(0.0, transition: positionTransition) + } + + private var dismissOffset: CGFloat? + func containerLayoutUpdated(layout: ContainerViewLayout, transition: Transition) { + self.currentLayout = layout + + self.dim.frame = CGRect(origin: CGPoint(x: 0.0, y: -layout.size.height), size: CGSize(width: layout.size.width, height: layout.size.height * 3.0)) + + var effectiveExpanded = self.isExpanded + if case .regular = layout.metrics.widthClass { + effectiveExpanded = true + } + + let isLandscape = layout.orientation == .landscape + let edgeTopInset = isLandscape ? 0.0 : self.defaultTopInset + let topInset: CGFloat + if let (panInitialTopInset, panOffset, _, _) = self.panGestureArguments { + if effectiveExpanded { + topInset = min(edgeTopInset, panInitialTopInset + max(0.0, panOffset)) + } else { + topInset = max(0.0, panInitialTopInset + min(0.0, panOffset)) + } + } else if let dismissOffset = self.dismissOffset, !dismissOffset.isZero { + topInset = edgeTopInset * dismissOffset + } else { + topInset = effectiveExpanded ? 0.0 : edgeTopInset + } + transition.setFrame(view: self.wrappingView, frame: CGRect(origin: CGPoint(x: 0.0, y: topInset), size: layout.size), completion: nil) + + let modalProgress = isLandscape ? 0.0 : (1.0 - topInset / self.defaultTopInset) + self.controller?.updateModalStyleOverlayTransitionFactor(modalProgress, transition: transition.containedViewLayoutTransition) + + let clipFrame: CGRect + if layout.metrics.widthClass == .compact { + self.dim.backgroundColor = UIColor(rgb: 0x000000, alpha: 0.25) + if isLandscape { + self.containerView.layer.cornerRadius = 0.0 + } else { + self.containerView.layer.cornerRadius = 10.0 + } + + if #available(iOS 11.0, *) { + if layout.safeInsets.bottom.isZero { + self.containerView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner] + } else { + self.containerView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMaxYCorner] + } + } + + if isLandscape { + clipFrame = CGRect(origin: CGPoint(), size: layout.size) + } else { + let coveredByModalTransition: CGFloat = 0.0 + var containerTopInset: CGFloat = 10.0 + if let statusBarHeight = layout.statusBarHeight { + containerTopInset += statusBarHeight + } + + let unscaledFrame = CGRect(origin: CGPoint(x: 0.0, y: containerTopInset - coveredByModalTransition * 10.0), size: CGSize(width: layout.size.width, height: layout.size.height - containerTopInset)) + let maxScale: CGFloat = (layout.size.width - 16.0 * 2.0) / layout.size.width + let containerScale = 1.0 * (1.0 - coveredByModalTransition) + maxScale * coveredByModalTransition + let maxScaledTopInset: CGFloat = containerTopInset - 10.0 + let scaledTopInset: CGFloat = containerTopInset * (1.0 - coveredByModalTransition) + maxScaledTopInset * coveredByModalTransition + let containerFrame = unscaledFrame.offsetBy(dx: 0.0, dy: scaledTopInset - (unscaledFrame.midY - containerScale * unscaledFrame.height / 2.0)) + + clipFrame = CGRect(x: containerFrame.minX, y: containerFrame.minY, width: containerFrame.width, height: containerFrame.height) + } + } else { + self.dim.backgroundColor = UIColor(rgb: 0x000000, alpha: 0.4) + self.containerView.layer.cornerRadius = 10.0 + + let verticalInset: CGFloat = 44.0 + + let maxSide = max(layout.size.width, layout.size.height) + let minSide = min(layout.size.width, layout.size.height) + let containerSize = CGSize(width: min(layout.size.width - 20.0, floor(maxSide / 2.0)), height: min(layout.size.height, minSide) - verticalInset * 2.0) + clipFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - containerSize.width) / 2.0), y: floor((layout.size.height - containerSize.height) / 2.0)), size: containerSize) + } + + transition.setFrame(view: self.containerView, frame: clipFrame) + + self.updated(transition: transition) + } + + func updated(transition: Transition) { + guard let controller = self.controller else { + return + } + let containerSize = self.containerView.bounds.size + + + let contentSize = self.contentView.update( + transition: .immediate, + component: AnyComponent( + BoostLevelsContainerComponent( + context: controller.context, + theme: self.presentationData.theme, + strings: self.presentationData.strings, + peer: controller.peer, + subject: controller.subject, + status: controller.status, + copyLink: { [weak self, weak controller] link in + guard let self else { + return + } + UIPasteboard.general.string = link + + if let previousController = controller?.navigationController?.viewControllers.reversed().first(where: { $0 !== controller }) as? ViewController { + previousController.present(UndoOverlayController(presentationData: self.presentationData, content: .linkCopied(text: self.presentationData.strings.ChannelBoost_BoostLinkCopied), elevatedLayout: true, position: .top, animateInAsReplacement: false, action: { _ in return false }), in: .current) + } + }, + dismiss: { [weak controller] in + controller?.dismiss(animated: true) + }, + openStats: controller.openStats, + openGift: controller.openGift + ) + ), + environment: {}, + containerSize: CGSize(width: containerSize.width, height: containerSize.height) + ) + self.contentView.frame = CGRect(origin: .zero, size: contentSize) + } + + private var didPlayAppearAnimation = false + func updateIsVisible(isVisible: Bool) { + if self.currentIsVisible == isVisible { + return + } + self.currentIsVisible = isVisible + + guard let layout = self.currentLayout else { + return + } + self.containerLayoutUpdated(layout: layout, transition: .immediate) + + if !self.didPlayAppearAnimation { + self.didPlayAppearAnimation = true + self.animateIn() + } + } + + private var defaultTopInset: CGFloat { + guard let layout = self.currentLayout else { + return 210.0 + } + if case .compact = layout.metrics.widthClass { + let bottomPanelPadding: CGFloat = 12.0 + let bottomInset: CGFloat = layout.intrinsicInsets.bottom > 0.0 ? layout.intrinsicInsets.bottom + 5.0 : bottomPanelPadding + let panelHeight: CGFloat = bottomPanelPadding + 50.0 + bottomInset + 28.0 + + let additionalInset: CGFloat = 0.0 + return layout.size.height - layout.size.width - 181.0 - panelHeight + additionalInset + } else { + return 210.0 + } + } + + private func findVerticalScrollView(view: UIView?) -> (UIScrollView, ListView?)? { + if let view = view { + if let view = view as? UIScrollView, view.contentSize.height > view.contentSize.width { + return (view, nil) + } + return findVerticalScrollView(view: view.superview) + } else { + return nil + } + } + + @objc func panGesture(_ recognizer: UIPanGestureRecognizer) { + guard let layout = self.currentLayout else { + return + } + + let isLandscape = layout.orientation == .landscape + let edgeTopInset = isLandscape ? 0.0 : defaultTopInset + + switch recognizer.state { + case .began: + let point = recognizer.location(in: self.view) + let currentHitView = self.hitTest(point, with: nil) + + var scrollViewAndListNode = self.findVerticalScrollView(view: currentHitView) + if scrollViewAndListNode?.0.frame.height == self.frame.width { + scrollViewAndListNode = nil + } + let scrollView = scrollViewAndListNode?.0 + let listNode = scrollViewAndListNode?.1 + + let topInset: CGFloat + if self.isExpanded { + topInset = 0.0 + } else { + topInset = edgeTopInset + } + + self.panGestureArguments = (topInset, 0.0, scrollView, listNode) + case .changed: + guard let (topInset, panOffset, scrollView, listNode) = self.panGestureArguments else { + return + } + let visibleContentOffset = listNode?.visibleContentOffset() + let contentOffset = scrollView?.contentOffset.y ?? 0.0 + + var translation = recognizer.translation(in: self.view).y + + var currentOffset = topInset + translation + + let epsilon = 1.0 + if case let .known(value) = visibleContentOffset, value <= epsilon { + if let scrollView = scrollView { + scrollView.bounces = false + scrollView.setContentOffset(CGPoint(x: 0.0, y: 0.0), animated: false) + } + } else if let scrollView = scrollView, contentOffset <= -scrollView.contentInset.top + epsilon { + scrollView.bounces = false + scrollView.setContentOffset(CGPoint(x: 0.0, y: -scrollView.contentInset.top), animated: false) + } else if let scrollView = scrollView { + translation = panOffset + currentOffset = topInset + translation + if self.isExpanded { + recognizer.setTranslation(CGPoint(), in: self.view) + } else if currentOffset > 0.0 { + scrollView.setContentOffset(CGPoint(x: 0.0, y: -scrollView.contentInset.top), animated: false) + } + } + + if scrollView == nil { + translation = max(0.0, translation) + } + + self.panGestureArguments = (topInset, translation, scrollView, listNode) + + if !self.isExpanded { + if currentOffset > 0.0, let scrollView = scrollView { + scrollView.panGestureRecognizer.setTranslation(CGPoint(), in: scrollView) + } + } + + var bounds = self.bounds + if self.isExpanded { + bounds.origin.y = -max(0.0, translation - edgeTopInset) + } else { + bounds.origin.y = -translation + } + bounds.origin.y = min(0.0, bounds.origin.y) + self.bounds = bounds + + self.containerLayoutUpdated(layout: layout, transition: .immediate) + case .ended: + guard let (currentTopInset, panOffset, scrollView, listNode) = self.panGestureArguments else { + return + } + self.panGestureArguments = nil + + let visibleContentOffset = listNode?.visibleContentOffset() + let contentOffset = scrollView?.contentOffset.y ?? 0.0 + + let translation = recognizer.translation(in: self.view).y + var velocity = recognizer.velocity(in: self.view) + + if self.isExpanded { + if case let .known(value) = visibleContentOffset, value > 0.1 { + velocity = CGPoint() + } else if case .unknown = visibleContentOffset { + velocity = CGPoint() + } else if contentOffset > 0.1 { + velocity = CGPoint() + } + } + + var bounds = self.bounds + if self.isExpanded { + bounds.origin.y = -max(0.0, translation - edgeTopInset) + } else { + bounds.origin.y = -translation + } + bounds.origin.y = min(0.0, bounds.origin.y) + + scrollView?.bounces = true + + let offset = currentTopInset + panOffset + let topInset: CGFloat = edgeTopInset + + var dismissing = false + if bounds.minY < -60 || (bounds.minY < 0.0 && velocity.y > 300.0) || (self.isExpanded && bounds.minY.isZero && velocity.y > 1800.0) { + self.controller?.dismiss(animated: true, completion: nil) + dismissing = true + } else if self.isExpanded { + if velocity.y > 300.0 || offset > topInset / 2.0 { + self.isExpanded = false + if let listNode = listNode { + listNode.scroller.setContentOffset(CGPoint(), animated: false) + } else if let scrollView = scrollView { + scrollView.setContentOffset(CGPoint(x: 0.0, y: -scrollView.contentInset.top), animated: false) + } + + let distance = topInset - offset + let initialVelocity: CGFloat = distance.isZero ? 0.0 : abs(velocity.y / distance) + let transition = ContainedViewLayoutTransition.animated(duration: 0.45, curve: .customSpring(damping: 124.0, initialVelocity: initialVelocity)) + + self.containerLayoutUpdated(layout: layout, transition: Transition(transition)) + } else { + self.isExpanded = true + + self.containerLayoutUpdated(layout: layout, transition: Transition(.animated(duration: 0.3, curve: .easeInOut))) + } + } else if scrollView != nil, (velocity.y < -300.0 || offset < topInset / 2.0) { + if velocity.y > -2200.0 && velocity.y < -300.0, let listNode = listNode { + DispatchQueue.main.async { + listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Default(duration: nil), directionHint: .Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in }) + } + } + + let initialVelocity: CGFloat = offset.isZero ? 0.0 : abs(velocity.y / offset) + let transition = ContainedViewLayoutTransition.animated(duration: 0.45, curve: .customSpring(damping: 124.0, initialVelocity: initialVelocity)) + self.isExpanded = true + + self.containerLayoutUpdated(layout: layout, transition: Transition(transition)) + } else { + if let listNode = listNode { + listNode.scroller.setContentOffset(CGPoint(), animated: false) + } else if let scrollView = scrollView { + scrollView.setContentOffset(CGPoint(x: 0.0, y: -scrollView.contentInset.top), animated: false) + } + + self.containerLayoutUpdated(layout: layout, transition: Transition(.animated(duration: 0.3, curve: .easeInOut))) + } + + if !dismissing { + var bounds = self.bounds + let previousBounds = bounds + bounds.origin.y = 0.0 + self.bounds = bounds + self.layer.animateBounds(from: previousBounds, to: self.bounds, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue) + } + case .cancelled: + self.panGestureArguments = nil + + self.containerLayoutUpdated(layout: layout, transition: Transition(.animated(duration: 0.3, curve: .easeInOut))) + default: + break + } + } + + func updateDismissOffset(_ offset: CGFloat) { + guard self.isExpanded, let layout = self.currentLayout else { + return + } + + self.dismissOffset = offset + self.containerLayoutUpdated(layout: layout, transition: .immediate) + } + + func update(isExpanded: Bool, transition: ContainedViewLayoutTransition) { + guard isExpanded != self.isExpanded else { + return + } + self.dismissOffset = nil + self.isExpanded = isExpanded + + guard let layout = self.currentLayout else { + return + } + self.containerLayoutUpdated(layout: layout, transition: Transition(transition)) + } + } + + var node: Node { + return self.displayNode as! Node + } + + private let context: AccountContext + private let peer: EnginePeer + private let subject: BoostSubject + private let status: ChannelBoostStatus + private let openStats: () -> Void + private let openGift: () -> Void + private let forceDark: Bool + + private var currentLayout: ContainerViewLayout? + + public var disposed: () -> Void = {} + + public init( + context: AccountContext, + peer: EnginePeer, + subject: BoostSubject, + status: ChannelBoostStatus, + openStats: @escaping () -> Void, + openGift: @escaping () -> Void, + forceDark: Bool = false + ) { + self.context = context + self.peer = peer + self.subject = subject + self.status = status + self.openStats = openStats + self.openGift = openGift + self.forceDark = forceDark + + super.init(navigationBarPresentationData: nil) + + self.navigationPresentation = .flatModal + self.statusBar.statusBarStyle = .Ignore + + self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait) + + +// UIPasteboard.general.string = link +// let presentationData = component.context.sharedContext.currentPresentationData.with { $0 } +// self.environment?.controller()?.present(UndoOverlayController(presentationData: presentationData, content: .linkCopied(text: presentationData.strings.ChannelBoost_BoostLinkCopied), elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { _ in return false }), in: .current) + } + + required public init(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + self.disposed() + } + + @objc private func cancelPressed() { + self.dismiss(animated: true, completion: nil) + } + + override open func loadDisplayNode() { + self.displayNode = Node(context: self.context, controller: self) + self.displayNodeDidLoad() + + self.view.disablesInteractiveModalDismiss = true + } + + public override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) { + self.view.endEditing(true) + if flag { + self.node.animateOut(completion: { + super.dismiss(animated: false, completion: {}) + completion?() + }) + } else { + super.dismiss(animated: false, completion: {}) + completion?() + } + } + + override open func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + self.node.updateIsVisible(isVisible: true) + } + + override open func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + + self.node.updateIsVisible(isVisible: false) + } + + override open func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { + self.currentLayout = layout + super.containerLayoutUpdated(layout, transition: transition) + + self.node.containerLayoutUpdated(layout: layout, transition: Transition(transition)) + } +} diff --git a/submodules/PremiumUI/Sources/PremiumBoostScreen.swift b/submodules/PremiumUI/Sources/PremiumBoostScreen.swift index 2e2ef001cc..32d839a0a7 100644 --- a/submodules/PremiumUI/Sources/PremiumBoostScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumBoostScreen.swift @@ -234,8 +234,14 @@ public func PremiumBoostScreen( title: presentationData.strings.ChannelBoost_MoreBoosts_Title, text: presentationData.strings.ChannelBoost_MoreBoosts_Text(peer.compactDisplayTitle, "\(premiumConfiguration.boostsPerGiftCount)").string, actions: [ - TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {}) + TextAlertAction(type: .defaultAction, title: presentationData.strings.ChannelBoost_MoreBoosts_Gift, action: { + dismissImpl?() + let controller = context.sharedContext.makePremiumGiftController(context: context) + pushController(controller) + }), + TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Close, action: {}) ], + actionLayout: .vertical, parseMarkdown: true ) presentController(controller) diff --git a/submodules/PremiumUI/Sources/PremiumLimitScreen.swift b/submodules/PremiumUI/Sources/PremiumLimitScreen.swift index e086e73e25..29573caeb3 100644 --- a/submodules/PremiumUI/Sources/PremiumLimitScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumLimitScreen.swift @@ -1195,9 +1195,6 @@ private final class LimitSheetContent: CombinedComponent { case let .channelReactions(reactionCount): titleText = strings.ChannelBoost_CustomReactions string = strings.ChannelBoost_CustomReactionsText("\(reactionCount)", "\(reactionCount)").string - case .wallpaper: - titleText = strings.ChannelBoost_Wallpaper - string = strings.ChannelBoost_WallpaperText("\(premiumConfiguration.minChannelWallpaperLevel)").string } } else { let storiesString = strings.ChannelBoost_StoriesPerDay(level) @@ -1783,7 +1780,6 @@ public class PremiumLimitScreen: ViewControllerComponentContainer { case stories case nameColors case channelReactions(reactionCount: Int) - case wallpaper } case storiesChannelBoost(peer: EnginePeer, boostSubject: BoostSubject, isCurrent: Bool, level: Int32, currentLevelBoosts: Int32, nextLevelBoosts: Int32?, link: String?, myBoostCount: Int32, canBoostAgain: Bool) diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/Sources/ChatMessageAttachedContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/Sources/ChatMessageAttachedContentNode.swift index bb36c81e47..b5d9dec5a2 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/Sources/ChatMessageAttachedContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/Sources/ChatMessageAttachedContentNode.swift @@ -595,7 +595,13 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode { } } - let dateText = stringForMessageTimestampStatus(accountPeerId: context.account.peerId, message: message, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, strings: presentationData.strings, associatedData: associatedData) + let dateFormat: MessageTimestampStatusFormat + if presentationData.isPreview { + dateFormat = .full + } else { + dateFormat = .regular + } + let dateText = stringForMessageTimestampStatus(accountPeerId: context.account.peerId, message: message, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, strings: presentationData.strings, format: dateFormat, associatedData: associatedData) let statusType: ChatMessageDateAndStatusType if incoming { diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode/Sources/StringForMessageTimestampStatus.swift b/submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode/Sources/StringForMessageTimestampStatus.swift index b25ae1e776..0a9f6c77ed 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode/Sources/StringForMessageTimestampStatus.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode/Sources/StringForMessageTimestampStatus.swift @@ -83,7 +83,7 @@ public func stringForMessageTimestampStatus(accountPeerId: PeerId, message: Mess } var displayFullDate = false - if case .full = format { + if case .full = format, timestamp > 100000 { displayFullDate = true } else if let _ = message.forwardInfo, message.id.peerId == accountPeerId { displayFullDate = true diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageGiveawayBubbleContentNode/Sources/ChatMessageGiveawayBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageGiveawayBubbleContentNode/Sources/ChatMessageGiveawayBubbleContentNode.swift index 67f20e3b13..0c84e7e7fa 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageGiveawayBubbleContentNode/Sources/ChatMessageGiveawayBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageGiveawayBubbleContentNode/Sources/ChatMessageGiveawayBubbleContentNode.swift @@ -597,7 +597,10 @@ public class ChatMessageGiveawayBubbleContentNode: ChatMessageBubbleContentNode, let smallSpacing: CGFloat = 2.0 let largeSpacing: CGFloat = 14.0 - var layoutSize = CGSize(width: boundingWidth, height: 49.0 + prizeTitleLayout.size.height + prizeTextLayout.size.height + participantsTextLayout.size.height + dateTextLayout.size.height + buttonSize.height + buttonSpacing + 106.0) + var layoutSize = CGSize(width: boundingWidth, height: 49.0 + prizeTitleLayout.size.height + prizeTextLayout.size.height + participantsTextLayout.size.height + dateTextLayout.size.height + 99.0) + if !item.presentationData.isPreview { + layoutSize.height += buttonSize.height + buttonSpacing + 7.0 + } if additionalPrizeTextLayout.size.height > 0.0 { layoutSize.height += additionalPrizeSeparatorLayout.size.height + additionalPrizeTextLayout.size.height + 7.0 @@ -655,6 +658,8 @@ public class ChatMessageGiveawayBubbleContentNode: ChatMessageBubbleContentNode, let _ = dateTextApply() let _ = channelButtonsApply() let _ = buttonApply(animation) + + strongSelf.buttonNode.isHidden = item.presentationData.isPreview var originY: CGFloat = 0.0 @@ -1051,7 +1056,7 @@ private final class PeerButtonNode: HighlightTrackingButtonNode { return (CGSize(width: refinedWidth, height: 24.0), { let _ = textApply() - targetNode.avatarNode.displaysAsynchronously = displayAsynchronously + targetNode.avatarNode.contentNode.displaysAsynchronously = displayAsynchronously targetNode.textNode.displaysAsynchronously = displayAsynchronously let backgroundFrame = CGRect(origin: .zero, size: CGSize(width: refinedWidth, height: 24.0)) diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveFileNode/Sources/ChatMessageInteractiveFileNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveFileNode/Sources/ChatMessageInteractiveFileNode.swift index 22daa4e10d..805eb58882 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveFileNode/Sources/ChatMessageInteractiveFileNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveFileNode/Sources/ChatMessageInteractiveFileNode.swift @@ -1700,7 +1700,10 @@ public final class ChatMessageInteractiveFileNode: ASDisplayNode { image = playerAlbumArt(postbox: context.account.postbox, engine: context.engine, fileReference: .message(message: MessageReference(message), media: file), albumArt: .init(thumbnailResource: ExternalMusicAlbumArtResource(file: .message(message: MessageReference(message), media: file), title: title ?? "", performer: performer ?? "", isThumbnail: true), fullSizeResource: ExternalMusicAlbumArtResource(file: .message(message: MessageReference(message), media: file), title: title ?? "", performer: performer ?? "", isThumbnail: false)), thumbnail: true, overlayColor: UIColor(white: 0.0, alpha: 0.3), drawPlaceholderWhenEmpty: false, attemptSynchronously: !animated) } } - let statusNode = SemanticStatusNode(backgroundNodeColor: backgroundNodeColor, foregroundNodeColor: foregroundNodeColor, image: image, overlayForegroundNodeColor: presentationData.theme.theme.chat.message.mediaOverlayControlColors.foregroundColor) + let statusNode = SemanticStatusNode(backgroundNodeColor: backgroundNodeColor, foregroundNodeColor: foregroundNodeColor, image: image, overlayForegroundNodeColor: presentationData.theme.theme.chat.message.mediaOverlayControlColors.foregroundColor) + if presentationData.isPreview { + statusNode.displaysAsynchronously = false + } self.statusNode = statusNode self.statusContainerNode.contentNode.insertSubnode(statusNode, at: 0) @@ -1787,7 +1790,7 @@ public final class ChatMessageInteractiveFileNode: ASDisplayNode { cutoutFrame.origin.y += 6.0 } - if streamingState == .none && self.selectionNode == nil { + if (streamingState == .none && self.selectionNode == nil) || presentationData.isPreview { self.statusNode?.setCutout(nil, animated: animated) } else if let statusNode = self.statusNode, (self.iconNode?.isHidden ?? true) { statusNode.setCutout(cutoutFrame, animated: true) diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveMediaNode/Sources/ChatMessageInteractiveMediaNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveMediaNode/Sources/ChatMessageInteractiveMediaNode.swift index aebeda84b3..d9e9af0479 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveMediaNode/Sources/ChatMessageInteractiveMediaNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveMediaNode/Sources/ChatMessageInteractiveMediaNode.swift @@ -2122,6 +2122,10 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr if let badgeContent = badgeContent { if self.badgeNode == nil { let badgeNode = ChatMessageInteractiveMediaBadge() + if isPreview { + badgeNode.durationNode.displaysAsynchronously = false + badgeNode.sizeNode?.displaysAsynchronously = false + } var inset: CGFloat = 6.0 if let corners = self.currentImageArguments?.corners, case .Tail = corners.bottomLeft { diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageDateHeader.swift b/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageDateHeader.swift index a11082e091..ae698993b6 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageDateHeader.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageDateHeader.swift @@ -482,6 +482,7 @@ public final class ChatMessageAvatarHeaderNodeImpl: ListViewItemHeaderNode, Chat self.containerNode = ContextControllerSourceNode() self.avatarNode = AvatarNode(font: avatarFont) + self.avatarNode.contentNode.displaysAsynchronously = !presentationData.isPreview super.init(layerBacked: false, dynamicBounce: true, isRotated: true, seeThrough: false) diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift index 37ed248d2d..251411febb 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift @@ -510,11 +510,11 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { let hideAllAdditionalInfo = item.presentationData.isPreview - let (textLayout, textApply) = textLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: hideAllAdditionalInfo ? 12 : 0, truncationType: .end, constrainedSize: textConstrainedSize, alignment: .natural, cutout: cutout, insets: textInsets, lineColor: messageTheme.accentControlColor)) + let (textLayout, textApply) = textLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: hideAllAdditionalInfo ? 10 : 0, truncationType: .end, constrainedSize: textConstrainedSize, alignment: .natural, cutout: cutout, insets: textInsets, lineColor: messageTheme.accentControlColor)) let spoilerTextLayoutAndApply: (TextNodeLayout, (TextNodeWithEntities.Arguments?) -> TextNodeWithEntities)? if !textLayout.spoilers.isEmpty { - spoilerTextLayoutAndApply = spoilerTextLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: hideAllAdditionalInfo ? 12 : 0, truncationType: .end, constrainedSize: textConstrainedSize, alignment: .natural, cutout: cutout, insets: textInsets, lineColor: messageTheme.accentControlColor, displaySpoilers: true, displayEmbeddedItemsUnderSpoilers: true)) + spoilerTextLayoutAndApply = spoilerTextLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: hideAllAdditionalInfo ? 10 : 0, truncationType: .end, constrainedSize: textConstrainedSize, alignment: .natural, cutout: cutout, insets: textInsets, lineColor: messageTheme.accentControlColor, displaySpoilers: true, displayEmbeddedItemsUnderSpoilers: true)) } else { spoilerTextLayoutAndApply = nil } diff --git a/submodules/TelegramUI/Components/MediaEditor/Sources/DrawingMessageRenderer.swift b/submodules/TelegramUI/Components/MediaEditor/Sources/DrawingMessageRenderer.swift index aee8fbd3cc..ad9b53bf06 100644 --- a/submodules/TelegramUI/Components/MediaEditor/Sources/DrawingMessageRenderer.swift +++ b/submodules/TelegramUI/Components/MediaEditor/Sources/DrawingMessageRenderer.swift @@ -11,64 +11,58 @@ import WallpaperBackgroundNode public final class DrawingWallpaperRenderer { private let context: AccountContext - private let presentationData: PresentationData private let customWallpaper: TelegramWallpaper? - private let containerNode: ASDisplayNode private let wallpaperBackgroundNode: WallpaperBackgroundNode + private let darkWallpaperBackgroundNode: WallpaperBackgroundNode public init (context: AccountContext, customWallpaper: TelegramWallpaper?) { self.context = context - self.presentationData = context.sharedContext.currentPresentationData.with { $0 } self.customWallpaper = customWallpaper - self.containerNode = ASDisplayNode() self.wallpaperBackgroundNode = createWallpaperBackgroundNode(context: context, forChatDisplay: true, useSharedAnimationPhase: false) self.wallpaperBackgroundNode.displaysAsynchronously = false - self.containerNode.addSubnode(self.wallpaperBackgroundNode) - } - - public func render(completion: @escaping (CGSize, UIImage?, UIImage?) -> Void) { let wallpaper = self.customWallpaper ?? context.sharedContext.currentPresentationData.with { $0 }.chatWallpaper self.wallpaperBackgroundNode.update(wallpaper: wallpaper, animated: false) - let size = CGSize(width: 360.0, height: 640.0) - self.updateLayout(size: size) + self.darkWallpaperBackgroundNode = createWallpaperBackgroundNode(context: context, forChatDisplay: true, useSharedAnimationPhase: false) + self.darkWallpaperBackgroundNode.displaysAsynchronously = false - Queue.mainQueue().after(0.03, { - let resultSize = CGSize(width: 1080, height: 1920) - self.generate { dayImage in - if self.customWallpaper != nil { - completion(resultSize, dayImage, nil) - } else { - let darkTheme = defaultDarkColorPresentationTheme - let wallpaper = darkTheme.chat.defaultWallpaper - self.wallpaperBackgroundNode.update(wallpaper: wallpaper, animated: false) - self.wallpaperBackgroundNode.updateLayout(size: size, displayMode: .aspectFill, transition: .immediate) - Queue.mainQueue().after(0.03, { - self.generate { nightImage in - completion(resultSize, dayImage, nightImage) - } - }) - } - } - }) + let darkTheme = defaultDarkColorPresentationTheme + let darkWallpaper = darkTheme.chat.defaultWallpaper + self.darkWallpaperBackgroundNode.update(wallpaper: darkWallpaper, animated: false) } - private func generate(completion: @escaping (UIImage) -> Void) { + public func render(completion: @escaping (CGSize, UIImage?, UIImage?) -> Void) { + self.updateLayout(size: CGSize(width: 360.0, height: 640.0)) + + let resultSize = CGSize(width: 1080, height: 1920) + self.generate(view: self.wallpaperBackgroundNode.view) { dayImage in + if self.customWallpaper != nil { + completion(resultSize, dayImage, nil) + } else { + Queue.mainQueue().justDispatch { + self.generate(view: self.darkWallpaperBackgroundNode.view) { nightImage in + completion(resultSize, dayImage, nightImage) + } + } + } + } + } + + private func generate(view: UIView, completion: @escaping (UIImage) -> Void) { let size = CGSize(width: 360.0, height: 640.0) UIGraphicsBeginImageContextWithOptions(size, false, 3.0) - self.containerNode.view.drawHierarchy(in: CGRect(origin: CGPoint(), size: size), afterScreenUpdates: true) + view.drawHierarchy(in: CGRect(origin: CGPoint(), size: size), afterScreenUpdates: true) let img = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() let finalImage = generateImage(CGSize(width: size.width * 3.0, height: size.height * 3.0), contextGenerator: { size, context in - context.clear(CGRect(origin: .zero, size: size)) if let cgImage = img?.cgImage { context.draw(cgImage, in: CGRect(origin: .zero, size: size), byTiling: false) } - }, opaque: false, scale: 1.0) + }, opaque: true, scale: 1.0) if let finalImage { completion(finalImage) } @@ -77,7 +71,8 @@ public final class DrawingWallpaperRenderer { private func updateLayout(size: CGSize) { self.wallpaperBackgroundNode.updateLayout(size: size, displayMode: .aspectFill, transition: .immediate) self.wallpaperBackgroundNode.frame = CGRect(origin: .zero, size: size) - self.containerNode.frame = CGRect(origin: .zero, size: size) + self.darkWallpaperBackgroundNode.updateLayout(size: size, displayMode: .aspectFill, transition: .immediate) + self.darkWallpaperBackgroundNode.frame = CGRect(origin: .zero, size: size) } } diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift index b946c9d4a7..a4f584668e 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift @@ -2922,6 +2922,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate } else { if case .message = self.subject, let layout = self.validLayout { self.layer.animatePosition(from: CGPoint(x: 0.0, y: layout.size.height), to: .zero, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, additive: true) + completion() } else if let view = self.componentHost.view as? MediaEditorScreenComponent.View { view.animateIn(from: .camera, completion: completion) } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift index cd230137fd..cfe0a75408 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift @@ -8639,172 +8639,114 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro navigationController.setViewControllers(updatedControllers, animated: animated) } switch section { - case .avatar: - self.openAvatarForEditing() - case .edit: - self.headerNode.navigationButtonContainer.performAction?(.edit, nil, nil) - case .proxy: - self.controller?.push(proxySettingsController(context: self.context)) - case .stories: - push(PeerInfoStoryGridScreen(context: self.context, peerId: self.context.account.peerId, scope: .saved)) - case .savedMessages: - let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.context.account.peerId)) - |> deliverOnMainQueue).startStandalone(next: { [weak self] peer in - guard let self, let peer = peer else { - return - } - if let controller = self.controller, let navigationController = controller.navigationController as? NavigationController { - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peer))) - } - }) - case .recentCalls: - push(CallListController(context: context, mode: .navigation)) - case .devices: - let _ = (self.activeSessionsContextAndCount.get() + case .avatar: + self.openAvatarForEditing() + case .edit: + self.headerNode.navigationButtonContainer.performAction?(.edit, nil, nil) + case .proxy: + self.controller?.push(proxySettingsController(context: self.context)) + case .stories: + push(PeerInfoStoryGridScreen(context: self.context, peerId: self.context.account.peerId, scope: .saved)) + case .savedMessages: + let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.context.account.peerId)) + |> deliverOnMainQueue).startStandalone(next: { [weak self] peer in + guard let self, let peer = peer else { + return + } + if let controller = self.controller, let navigationController = controller.navigationController as? NavigationController { + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peer))) + } + }) + case .recentCalls: + push(CallListController(context: context, mode: .navigation)) + case .devices: + let _ = (self.activeSessionsContextAndCount.get() + |> take(1) + |> deliverOnMainQueue).startStandalone(next: { [weak self] activeSessionsContextAndCount in + if let strongSelf = self, let activeSessionsContextAndCount = activeSessionsContextAndCount { + let (activeSessionsContext, _, webSessionsContext) = activeSessionsContextAndCount + push(recentSessionsController(context: strongSelf.context, activeSessionsContext: activeSessionsContext, webSessionsContext: webSessionsContext, websitesOnly: false)) + } + }) + case .chatFolders: + push(chatListFilterPresetListController(context: self.context, mode: .default)) + case .notificationsAndSounds: + if let settings = self.data?.globalSettings { + push(notificationsAndSoundsController(context: self.context, exceptionsList: settings.notificationExceptions)) + } + case .privacyAndSecurity: + if let settings = self.data?.globalSettings { + let _ = (combineLatest(self.blockedPeers.get(), self.hasTwoStepAuth.get()) |> take(1) - |> deliverOnMainQueue).startStandalone(next: { [weak self] activeSessionsContextAndCount in - if let strongSelf = self, let activeSessionsContextAndCount = activeSessionsContextAndCount { - let (activeSessionsContext, _, webSessionsContext) = activeSessionsContextAndCount - push(recentSessionsController(context: strongSelf.context, activeSessionsContext: activeSessionsContext, webSessionsContext: webSessionsContext, websitesOnly: false)) + |> deliverOnMainQueue).startStandalone(next: { [weak self] blockedPeersContext, hasTwoStepAuth in + if let strongSelf = self { + let loginEmailPattern = strongSelf.twoStepAuthData.get() |> map { data -> String? in + return data?.loginEmailPattern + } + push(privacyAndSecurityController(context: strongSelf.context, initialSettings: settings.privacySettings, updatedSettings: { [weak self] settings in + self?.privacySettings.set(.single(settings)) + }, updatedBlockedPeers: { [weak self] blockedPeersContext in + self?.blockedPeers.set(.single(blockedPeersContext)) + }, updatedHasTwoStepAuth: { [weak self] hasTwoStepAuthValue in + self?.hasTwoStepAuth.set(.single(hasTwoStepAuthValue)) + }, focusOnItemTag: nil, activeSessionsContext: settings.activeSessionsContext, webSessionsContext: settings.webSessionsContext, blockedPeersContext: blockedPeersContext, hasTwoStepAuth: hasTwoStepAuth, loginEmailPattern: loginEmailPattern, updatedTwoStepAuthData: { [weak self] in + if let strongSelf = self { + strongSelf.twoStepAuthData.set( + strongSelf.context.engine.auth.twoStepAuthData() + |> map(Optional.init) + |> `catch` { _ -> Signal in + return .single(nil) + } + ) + } + }, requestPublicPhotoSetup: { [weak self] completion in + if let strongSelf = self { + strongSelf.openAvatarForEditing(mode: .fallback, completion: completion) + } + }, requestPublicPhotoRemove: { [weak self] completion in + if let strongSelf = self { + strongSelf.openAvatarRemoval(mode: .fallback, completion: completion) + } + })) } }) - case .chatFolders: - push(chatListFilterPresetListController(context: self.context, mode: .default)) - case .notificationsAndSounds: - if let settings = self.data?.globalSettings { - push(notificationsAndSoundsController(context: self.context, exceptionsList: settings.notificationExceptions)) + } + case .passwordSetup: + DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.6, execute: { [weak self] in + guard let self else { + return } - case .privacyAndSecurity: - if let settings = self.data?.globalSettings { - let _ = (combineLatest(self.blockedPeers.get(), self.hasTwoStepAuth.get()) - |> take(1) - |> deliverOnMainQueue).startStandalone(next: { [weak self] blockedPeersContext, hasTwoStepAuth in - if let strongSelf = self { - let loginEmailPattern = strongSelf.twoStepAuthData.get() |> map { data -> String? in - return data?.loginEmailPattern - } - push(privacyAndSecurityController(context: strongSelf.context, initialSettings: settings.privacySettings, updatedSettings: { [weak self] settings in - self?.privacySettings.set(.single(settings)) - }, updatedBlockedPeers: { [weak self] blockedPeersContext in - self?.blockedPeers.set(.single(blockedPeersContext)) - }, updatedHasTwoStepAuth: { [weak self] hasTwoStepAuthValue in - self?.hasTwoStepAuth.set(.single(hasTwoStepAuthValue)) - }, focusOnItemTag: nil, activeSessionsContext: settings.activeSessionsContext, webSessionsContext: settings.webSessionsContext, blockedPeersContext: blockedPeersContext, hasTwoStepAuth: hasTwoStepAuth, loginEmailPattern: loginEmailPattern, updatedTwoStepAuthData: { [weak self] in - if let strongSelf = self { - strongSelf.twoStepAuthData.set( - strongSelf.context.engine.auth.twoStepAuthData() - |> map(Optional.init) - |> `catch` { _ -> Signal in - return .single(nil) - } - ) - } - }, requestPublicPhotoSetup: { [weak self] completion in - if let strongSelf = self { - strongSelf.openAvatarForEditing(mode: .fallback, completion: completion) - } - }, requestPublicPhotoRemove: { [weak self] completion in - if let strongSelf = self { - strongSelf.openAvatarRemoval(mode: .fallback, completion: completion) - } - })) - } - }) - } - case .passwordSetup: - DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.6, execute: { [weak self] in - guard let self else { - return - } - let _ = dismissServerProvidedSuggestion(account: self.context.account, suggestion: .setupPassword).startStandalone() - }) - - let controller = self.context.sharedContext.makeSetupTwoFactorAuthController(context: self.context) - push(controller) - case .dataAndStorage: - push(dataAndStorageController(context: self.context)) - case .appearance: - push(themeSettingsController(context: self.context)) - case .language: - push(LocalizationListController(context: self.context)) - case .premium: - self.controller?.push(PremiumIntroScreen(context: self.context, modal: false, source: .settings)) - case .premiumGift: - let options = Promise<[PremiumGiftCodeOption]>() - options.set(self.context.engine.payments.premiumGiftCodeOptions(peerId: nil)) - - var reachedLimitImpl: ((Int32) -> Void)? - let controller = self.context.sharedContext.makeContactMultiselectionController(ContactMultiselectionControllerParams(context: self.context, mode: .premiumGifting, options: [], isPeerEnabled: { peer in - if case let .user(user) = peer, user.botInfo == nil { - return true - } else { - return false - } - }, limit: 10, reachedLimit: { limit in - reachedLimitImpl?(limit) - })) - self.controller?.push(controller) + let _ = dismissServerProvidedSuggestion(account: self.context.account, suggestion: .setupPassword).startStandalone() + }) - reachedLimitImpl = { [weak self, weak controller] limit in - guard let self, let controller else { - return - } - self.hapticFeedback.error() - controller.present(UndoOverlayController(presentationData: self.presentationData, content: .info(title: nil, text: self.presentationData.strings.Premium_Gift_ContactSelection_MaximumReached("\(limit)").string, timeout: nil, customUndoText: nil), elevatedLayout: true, position: .bottom, animateInAsReplacement: false, action: { _ in return false }), in: .current) - } - - self.activeActionDisposable.set(combineLatest(queue: Queue.mainQueue(), controller.result, options.get()) - .startStrict(next: { [weak self, weak controller] result, options in - guard let self, let controller else { - return - } - var peerIds: [PeerId] = [] - if case let .result(peerIdsValue, _) = result { - peerIds = peerIdsValue.compactMap({ peerId in - if case let .peer(peerId) = peerId { - return peerId - } else { - return nil - } - }) - } - - let maxCount = 10 - if peerIds.count > maxCount { - self.hapticFeedback.error() - - controller.present(UndoOverlayController(presentationData: self.presentationData, content: .info(title: nil, text: self.presentationData.strings.Premium_Gift_ContactSelection_MaximumReached("\(maxCount)").string, timeout: nil, customUndoText: nil), elevatedLayout: true, position: .bottom, animateInAsReplacement: false, action: { _ in return false }), in: .current) - return - } - - let mappedOptions = options.filter { $0.users == 1 }.map { CachedPremiumGiftOption(months: $0.months, currency: $0.currency, amount: $0.amount, botUrl: "", storeProductId: $0.storeProductId) } - - let giftController = PremiumGiftScreen(context: self.context, peerIds: peerIds, options: mappedOptions, source: .settings, pushController: { [weak self] c in - self?.controller?.push(c) - }, completion: { [weak self] in - if let self, let navigationController = self.controller?.navigationController as? NavigationController { - var controllers = navigationController.viewControllers - controllers = controllers.filter { !($0 is ContactMultiselectionController) } - navigationController.setViewControllers(controllers, animated: true) - } - }) - controller.push(giftController) + let controller = self.context.sharedContext.makeSetupTwoFactorAuthController(context: self.context) + push(controller) + case .dataAndStorage: + push(dataAndStorageController(context: self.context)) + case .appearance: + push(themeSettingsController(context: self.context)) + case .language: + push(LocalizationListController(context: self.context)) + case .premium: + self.controller?.push(PremiumIntroScreen(context: self.context, modal: false, source: .settings)) + case .premiumGift: + let controller = self.context.sharedContext.makePremiumGiftController(context: self.context) + self.controller?.push(controller) + case .stickers: + if let settings = self.data?.globalSettings { + push(installedStickerPacksController(context: self.context, mode: .general, archivedPacks: settings.archivedStickerPacks, updatedPacks: { [weak self] packs in + self?.archivedPacks.set(.single(packs)) })) - case .stickers: - if let settings = self.data?.globalSettings { - push(installedStickerPacksController(context: self.context, mode: .general, archivedPacks: settings.archivedStickerPacks, updatedPacks: { [weak self] packs in - self?.archivedPacks.set(.single(packs)) - })) - } - case .passport: - self.controller?.push(SecureIdAuthController(context: self.context, mode: .list)) - case .watch: - push(watchSettingsController(context: self.context)) - case .support: - let supportPeer = Promise() - supportPeer.set(context.engine.peers.supportPeerId()) - - self.controller?.present(textAlertController(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, title: nil, text: self.presentationData.strings.Settings_FAQ_Intro, actions: [ + } + case .passport: + self.controller?.push(SecureIdAuthController(context: self.context, mode: .list)) + case .watch: + push(watchSettingsController(context: self.context)) + case .support: + let supportPeer = Promise() + supportPeer.set(context.engine.peers.supportPeerId()) + + self.controller?.present(textAlertController(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, title: nil, text: self.presentationData.strings.Settings_FAQ_Intro, actions: [ TextAlertAction(type: .genericAction, title: presentationData.strings.Settings_FAQ_Button, action: { [weak self] in self?.openFaq() }), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: { [weak self] in @@ -8817,81 +8759,81 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro } })) })]), in: .window(.root)) - case .faq: - self.openFaq() - case .tips: - self.openTips() - case .phoneNumber: - if let user = self.data?.peer as? TelegramUser, let phoneNumber = user.phone { - let introController = PrivacyIntroController(context: self.context, mode: .changePhoneNumber(phoneNumber), proceedAction: { [weak self] in - if let strongSelf = self, let navigationController = strongSelf.controller?.navigationController as? NavigationController { - navigationController.replaceTopController(ChangePhoneNumberController(context: strongSelf.context), animated: true) - } - }) - push(introController) - } - case .username: - push(usernameSetupController(context: self.context)) - case .addAccount: - let _ = (activeAccountsAndPeers(context: context) - |> take(1) - |> deliverOnMainQueue - ).startStandalone(next: { [weak self] accountAndPeer, accountsAndPeers in - guard let strongSelf = self else { - return - } - var maximumAvailableAccounts: Int = 3 - if accountAndPeer?.1.isPremium == true && !strongSelf.context.account.testingEnvironment { - maximumAvailableAccounts = 4 - } - var count: Int = 1 - for (accountContext, peer, _) in accountsAndPeers { - if !accountContext.account.testingEnvironment { - if peer.isPremium { - maximumAvailableAccounts = 4 - } - count += 1 - } - } - - if count >= maximumAvailableAccounts { - var replaceImpl: ((ViewController) -> Void)? - let controller = PremiumLimitScreen(context: strongSelf.context, subject: .accounts, count: Int32(count), action: { - let controller = PremiumIntroScreen(context: strongSelf.context, source: .accounts) - replaceImpl?(controller) - return true - }) - replaceImpl = { [weak controller] c in - controller?.replace(with: c) - } - if let navigationController = strongSelf.context.sharedContext.mainWindow?.viewController as? NavigationController { - navigationController.pushViewController(controller) - } - } else { - strongSelf.context.sharedContext.beginNewAuth(testingEnvironment: strongSelf.context.account.testingEnvironment) + case .faq: + self.openFaq() + case .tips: + self.openTips() + case .phoneNumber: + if let user = self.data?.peer as? TelegramUser, let phoneNumber = user.phone { + let introController = PrivacyIntroController(context: self.context, mode: .changePhoneNumber(phoneNumber), proceedAction: { [weak self] in + if let strongSelf = self, let navigationController = strongSelf.controller?.navigationController as? NavigationController { + navigationController.replaceTopController(ChangePhoneNumberController(context: strongSelf.context), animated: true) } }) - case .logout: - if let user = self.data?.peer as? TelegramUser, let phoneNumber = user.phone { - if let controller = self.controller, let navigationController = controller.navigationController as? NavigationController { - self.controller?.push(logoutOptionsController(context: self.context, navigationController: navigationController, canAddAccounts: true, phoneNumber: phoneNumber)) + push(introController) + } + case .username: + push(usernameSetupController(context: self.context)) + case .addAccount: + let _ = (activeAccountsAndPeers(context: context) + |> take(1) + |> deliverOnMainQueue + ).startStandalone(next: { [weak self] accountAndPeer, accountsAndPeers in + guard let strongSelf = self else { + return + } + var maximumAvailableAccounts: Int = 3 + if accountAndPeer?.1.isPremium == true && !strongSelf.context.account.testingEnvironment { + maximumAvailableAccounts = 4 + } + var count: Int = 1 + for (accountContext, peer, _) in accountsAndPeers { + if !accountContext.account.testingEnvironment { + if peer.isPremium { + maximumAvailableAccounts = 4 + } + count += 1 } } - case .rememberPassword: - let context = self.context - let controller = TwoFactorDataInputScreen(sharedContext: self.context.sharedContext, engine: .authorized(self.context.engine), mode: .rememberPassword(doneText: self.presentationData.strings.TwoFactorSetup_Done_Action), stateUpdated: { _ in - }, presentation: .modalInLargeLayout) - controller.twoStepAuthSettingsController = { configuration in - return twoStepVerificationUnlockSettingsController(context: context, mode: .access(intro: false, data: .single(TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: configuration, password: nil))))) + + if count >= maximumAvailableAccounts { + var replaceImpl: ((ViewController) -> Void)? + let controller = PremiumLimitScreen(context: strongSelf.context, subject: .accounts, count: Int32(count), action: { + let controller = PremiumIntroScreen(context: strongSelf.context, source: .accounts) + replaceImpl?(controller) + return true + }) + replaceImpl = { [weak controller] c in + controller?.replace(with: c) + } + if let navigationController = strongSelf.context.sharedContext.mainWindow?.viewController as? NavigationController { + navigationController.pushViewController(controller) + } + } else { + strongSelf.context.sharedContext.beginNewAuth(testingEnvironment: strongSelf.context.account.testingEnvironment) } - controller.passwordRemembered = { - let _ = dismissServerProvidedSuggestion(account: context.account, suggestion: .validatePassword).startStandalone() + }) + case .logout: + if let user = self.data?.peer as? TelegramUser, let phoneNumber = user.phone { + if let controller = self.controller, let navigationController = controller.navigationController as? NavigationController { + self.controller?.push(logoutOptionsController(context: self.context, navigationController: navigationController, canAddAccounts: true, phoneNumber: phoneNumber)) } - push(controller) - case .emojiStatus: - self.headerNode.invokeDisplayPremiumIntro() - case .powerSaving: - push(energySavingSettingsScreen(context: self.context)) + } + case .rememberPassword: + let context = self.context + let controller = TwoFactorDataInputScreen(sharedContext: self.context.sharedContext, engine: .authorized(self.context.engine), mode: .rememberPassword(doneText: self.presentationData.strings.TwoFactorSetup_Done_Action), stateUpdated: { _ in + }, presentation: .modalInLargeLayout) + controller.twoStepAuthSettingsController = { configuration in + return twoStepVerificationUnlockSettingsController(context: context, mode: .access(intro: false, data: .single(TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: configuration, password: nil))))) + } + controller.passwordRemembered = { + let _ = dismissServerProvidedSuggestion(account: context.account, suggestion: .validatePassword).startStandalone() + } + push(controller) + case .emojiStatus: + self.headerNode.invokeDisplayPremiumIntro() + case .powerSaving: + push(energySavingSettingsScreen(context: self.context)) } } diff --git a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/ChannelAppearanceScreen.swift b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/ChannelAppearanceScreen.swift index 52caa07c99..d0ed3b3f60 100644 --- a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/ChannelAppearanceScreen.swift +++ b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/ChannelAppearanceScreen.swift @@ -337,12 +337,13 @@ final class ChannelAppearanceScreenComponent: Component { private var updatedPeerProfileEmoji: Int64?? private var updatedPeerStatus: PeerEmojiStatus?? - private var requiredLevel: Int? + private var requiredBoostSubject: BoostSubject? private var currentTheme: PresentationThemeReference? private var resolvedCurrentTheme: (reference: PresentationThemeReference, isDark: Bool, theme: PresentationTheme, wallpaper: TelegramWallpaper?)? private var resolvingCurrentTheme: (reference: PresentationThemeReference, isDark: Bool, disposable: Disposable)? + private var premiumConfiguration: PremiumConfiguration? private var boostLevel: Int? private var boostStatus: ChannelBoostStatus? private var boostStatusDisposable: Disposable? @@ -488,15 +489,16 @@ final class ChannelAppearanceScreenComponent: Component { } private func applySettings() { - guard let component = self.component, let resolvedState = self.resolveState(), let requiredLevel = self.requiredLevel else { + guard let component = self.component, let resolvedState = self.resolveState(), let premiumConfiguration = self.premiumConfiguration, let requiredBoostSubject = self.requiredBoostSubject else { return } if self.isApplyingSettings { return } + let requiredLevel = requiredBoostSubject.requiredLevel(premiumConfiguration) if let boostLevel = self.boostLevel, requiredLevel > boostLevel { - self.displayPremiumScreen(requiredLevel: requiredLevel) + self.displayBoostLevels(subject: requiredBoostSubject) return } @@ -545,7 +547,7 @@ final class ChannelAppearanceScreenComponent: Component { }) } - private func displayPremiumScreen(requiredLevel: Int) { + private func displayBoostLevels(subject: BoostSubject) { guard let component = self.component else { return } @@ -555,31 +557,25 @@ final class ChannelAppearanceScreenComponent: Component { guard let self, let component = self.component, let peer, let status = self.boostStatus else { return } - - let premiumConfiguration = PremiumConfiguration.with(appConfiguration: component.context.currentAppConfiguration.with { $0 }) - - let link = status.url - let controller = PremiumLimitScreen(context: component.context, subject: .storiesChannelBoost(peer: peer, boostSubject: .channelReactions(reactionCount: requiredLevel), isCurrent: true, level: Int32(status.level), currentLevelBoosts: Int32(status.currentLevelBoosts), nextLevelBoosts: status.nextLevelBoosts.flatMap(Int32.init), link: link, myBoostCount: 0, canBoostAgain: false), count: Int32(status.boosts), action: { [weak self] in - guard let self, let component = self.component else { - return true + let controller = PremiumBoostLevelsScreen( + context: component.context, + peer: peer, + subject: subject, + status: status, + openStats: { [weak self] in + guard let self else { + return + } + self.openBoostStats() + }, + openGift: { [weak self] in + guard let self, let component = self.component else { + return + } + let controller = createGiveawayController(context: component.context, peerId: component.peerId, subject: .generic) + self.environment?.controller()?.push(controller) } - - UIPasteboard.general.string = link - let presentationData = component.context.sharedContext.currentPresentationData.with { $0 } - self.environment?.controller()?.present(UndoOverlayController(presentationData: presentationData, content: .linkCopied(text: presentationData.strings.ChannelBoost_BoostLinkCopied), elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { _ in return false }), in: .current) - return true - }, openStats: { [weak self] in - guard let self else { - return - } - self.openBoostStats() - }, openGift: premiumConfiguration.giveawayGiftsPurchaseAvailable ? { [weak self] in - guard let self, let component = self.component else { - return - } - let controller = createGiveawayController(context: component.context, peerId: component.peerId, subject: .generic) - self.environment?.controller()?.push(controller) - } : nil) + ) self.environment?.controller()?.push(controller) HapticFeedback().impact(.light) @@ -713,6 +709,14 @@ final class ChannelAppearanceScreenComponent: Component { self.backgroundColor = environment.theme.list.blocksBackgroundColor } + let premiumConfiguration: PremiumConfiguration + if let current = self.premiumConfiguration { + premiumConfiguration = current + } else { + premiumConfiguration = PremiumConfiguration.with(appConfiguration: component.context.currentAppConfiguration.with { $0 }) + self.premiumConfiguration = premiumConfiguration + } + if self.contentsDataDisposable == nil { self.contentsDataDisposable = (ContentsData.get(context: component.context, peerId: component.peerId) |> deliverOnMainQueue).start(next: { [weak self] contentsData in @@ -747,7 +751,7 @@ final class ChannelAppearanceScreenComponent: Component { return availableSize } - var requiredLevel = 1 + var requiredBoostSubject: BoostSubject = .nameColors let replyIconLevel = 5 var profileIconLevel = 7 @@ -762,23 +766,25 @@ final class ChannelAppearanceScreenComponent: Component { emojiStatusLevel = Int(value) } } - - let profileColor = resolvedState.profileColor - + let replyFileId = resolvedState.replyFileId if replyFileId != nil { - requiredLevel = max(requiredLevel, replyIconLevel) + requiredBoostSubject = .nameIcon + } + + let profileColor = resolvedState.profileColor + if profileColor != nil { + requiredBoostSubject = .profileColors } let backgroundFileId = resolvedState.backgroundFileId - if profileColor != nil || backgroundFileId != nil { - requiredLevel = max(requiredLevel, profileIconLevel) + if backgroundFileId != nil { + requiredBoostSubject = .profileIcon } let emojiStatus = resolvedState.emojiStatus - if emojiStatus != nil { - requiredLevel = max(requiredLevel, emojiStatusLevel) + requiredBoostSubject = .emojiStatus } let statusFileId = emojiStatus?.fileId @@ -831,7 +837,7 @@ final class ChannelAppearanceScreenComponent: Component { } if self.currentTheme != nil && self.currentTheme != chatThemes.first { - requiredLevel = max(requiredLevel, themeLevel) + requiredBoostSubject = .wallpaper } if case let .user(user) = peer { @@ -852,7 +858,7 @@ final class ChannelAppearanceScreenComponent: Component { ) } - self.requiredLevel = requiredLevel + self.requiredBoostSubject = requiredBoostSubject let topInset: CGFloat = 24.0 let bottomContentInset: CGFloat = 24.0 @@ -890,7 +896,7 @@ final class ChannelAppearanceScreenComponent: Component { )), maximumNumberOfLines: 0 )))) - if replyFileId != nil, let boostLevel = self.boostLevel, boostLevel < replyIconLevel { + if replyFileId != nil, let boostLevel = self.boostLevel, boostLevel < premiumConfiguration.minChannelNameIconLevel { replyLogoContents.append(AnyComponentWithIdentity(id: 1, component: AnyComponent(BoostLevelIconComponent( strings: environment.strings, level: replyIconLevel @@ -996,7 +1002,7 @@ final class ChannelAppearanceScreenComponent: Component { )), maximumNumberOfLines: 0 )))) - if currentTheme != chatThemes[0], let boostLevel = self.boostLevel, boostLevel < themeLevel { + if currentTheme != chatThemes[0], let boostLevel = self.boostLevel, boostLevel < premiumConfiguration.minChannelCustomWallpaperLevel { wallpaperLogoContents.append(AnyComponentWithIdentity(id: 1, component: AnyComponent(BoostLevelIconComponent( strings: environment.strings, level: themeLevel @@ -1077,7 +1083,7 @@ final class ChannelAppearanceScreenComponent: Component { )), maximumNumberOfLines: 0 )))) - if backgroundFileId != nil, let boostLevel = self.boostLevel, boostLevel < profileIconLevel { + if backgroundFileId != nil, let boostLevel = self.boostLevel, boostLevel < premiumConfiguration.minChannelProfileIconLevel { profileLogoContents.append(AnyComponentWithIdentity(id: 1, component: AnyComponent(BoostLevelIconComponent( strings: environment.strings, level: profileIconLevel @@ -1188,7 +1194,7 @@ final class ChannelAppearanceScreenComponent: Component { )), maximumNumberOfLines: 0 )))) - if emojiStatus != nil, let boostLevel = self.boostLevel, boostLevel < emojiStatusLevel { + if emojiStatus != nil, let boostLevel = self.boostLevel, boostLevel < premiumConfiguration.minChannelEmojiStatusLevel { emojiStatusContents.append(AnyComponentWithIdentity(id: 1, component: AnyComponent(BoostLevelIconComponent( strings: environment.strings, level: emojiStatusLevel @@ -1300,9 +1306,10 @@ final class ChannelAppearanceScreenComponent: Component { Text(text: "Apply Changes", font: Font.semibold(17.0), color: environment.theme.list.itemCheckColors.foregroundColor) ))) + let requiredLevel = requiredBoostSubject.requiredLevel(premiumConfiguration) if let boostLevel = self.boostLevel, requiredLevel > boostLevel { buttonContents.append(AnyComponentWithIdentity(id: AnyHashable(1 as Int), component: AnyComponent(PremiumLockButtonSubtitleComponent( - count: requiredLevel, + count: Int(requiredLevel), theme: environment.theme, strings: environment.strings )))) diff --git a/submodules/TelegramUI/Components/TokenListTextField/Sources/EditableTokenListNode.swift b/submodules/TelegramUI/Components/TokenListTextField/Sources/EditableTokenListNode.swift index dbfda1f372..1b0f27498b 100644 --- a/submodules/TelegramUI/Components/TokenListTextField/Sources/EditableTokenListNode.swift +++ b/submodules/TelegramUI/Components/TokenListTextField/Sources/EditableTokenListNode.swift @@ -308,6 +308,7 @@ final class EditableTokenListNode: ASDisplayNode, UITextFieldDelegate { self.placeholderNode = ASTextNode() self.placeholderNode.isUserInteractionEnabled = false self.placeholderNode.maximumNumberOfLines = 1 + self.placeholderNode.displaysAsynchronously = false self.placeholderNode.attributedText = NSAttributedString(string: placeholder, font: Font.regular(15.0), textColor: theme.placeholderTextColor) self.textFieldScrollNode = ASScrollNode() diff --git a/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Contents.json b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Contents.json new file mode 100644 index 0000000000..6e965652df --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CoverColor.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CoverColor.imageset/Contents.json new file mode 100644 index 0000000000..d288e5cbca --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CoverColor.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "covercolor_30.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CoverColor.imageset/covercolor_30.pdf b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CoverColor.imageset/covercolor_30.pdf new file mode 100644 index 0000000000..0b24a428b4 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CoverColor.imageset/covercolor_30.pdf @@ -0,0 +1,298 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 4.334961 4.335022 cm +0.000000 0.478431 1.000000 scn +5.785331 19.957972 m +6.528978 19.999634 7.451835 20.000017 8.665000 20.000017 c +12.665000 20.000017 l +14.076105 20.000017 15.094439 19.999500 15.894838 19.934105 c +16.687475 19.869343 17.207642 19.744286 17.633049 19.527531 c +18.448732 19.111919 19.111902 18.448750 19.527514 17.633066 c +19.540468 17.607641 19.553097 17.581877 19.565403 17.555737 c +19.876143 17.857920 20.272636 17.995008 20.659822 17.995008 c +20.715282 17.995008 20.772083 17.992229 20.829720 17.986332 c +20.793468 18.071121 20.754486 18.154573 20.712553 18.236874 c +20.169430 19.302811 19.302795 20.169447 18.236856 20.712568 c +17.592707 21.040779 16.878029 21.188206 16.003143 21.259687 c +15.142270 21.330023 14.069739 21.330021 12.694985 21.330017 c +12.665000 21.330017 l +8.665000 21.330017 l +8.635015 21.330017 l +7.260260 21.330021 6.187730 21.330023 5.326858 21.259687 c +4.791599 21.215956 4.316306 21.143795 3.880442 21.019201 c +3.890508 20.977545 3.900183 20.939672 3.909794 20.904621 c +4.067824 20.860769 4.298860 20.812462 4.689383 20.734526 c +4.709473 20.730516 l +4.729430 20.725889 l +4.989579 20.665585 5.319242 20.527437 5.589351 20.228039 c +5.666474 20.142551 5.731493 20.051903 5.785331 19.957972 c +h +20.000000 12.665017 m +20.000000 12.493482 l +20.081505 12.334187 20.143467 12.137091 20.202589 11.886913 c +20.257551 11.654334 20.310059 11.375880 20.373531 11.039274 c +20.380175 11.004044 l +20.384460 10.981330 l +20.398952 10.904593 l +20.440691 10.758759 20.513735 10.665009 20.659822 10.665009 c +20.816343 10.665009 20.899822 10.758759 20.920691 10.904593 c +20.930399 10.957369 l +20.939493 11.006810 l +20.949696 11.062221 l +21.010153 11.390343 21.061460 11.662903 21.115931 11.891387 c +21.177372 12.149121 21.242840 12.350769 21.330002 12.512812 c +21.330002 12.665017 l +21.330002 12.694985 l +21.330002 12.695578 l +21.330002 13.540377 21.330002 14.271040 21.313671 14.908587 c +21.246031 15.055716 21.190304 15.232279 21.135550 15.448044 c +21.078949 15.671088 21.023384 15.936024 20.956772 16.253637 c +20.954065 16.266546 l +20.944857 16.310446 l +20.920691 16.425425 l +20.899822 16.571259 20.816343 16.665009 20.659822 16.665009 c +20.513735 16.665009 20.440691 16.571259 20.398952 16.425425 c +20.382780 16.348446 l +20.374823 16.310453 l +20.346594 16.175266 l +20.346577 16.175179 l +20.346514 16.174881 l +20.287724 15.893044 20.237925 15.654318 20.187643 15.450506 c +20.126453 15.202480 20.064547 15.006169 19.984858 14.846785 c +19.999807 14.239014 20.000000 13.524947 20.000000 12.665017 c +h +20.000000 8.665017 m +20.000000 9.476658 l +20.210934 9.380445 20.436922 9.335009 20.659822 9.335009 c +20.872946 9.335009 21.105841 9.376009 21.330002 9.477490 c +21.330002 8.665017 l +21.330002 8.635049 l +21.330006 7.260285 21.330008 6.187751 21.259672 5.326874 c +21.188190 4.451988 21.040764 3.737310 20.712553 3.093161 c +20.169430 2.027222 19.302795 1.160587 18.236856 0.617464 c +17.592707 0.289253 16.878029 0.141827 16.003143 0.070345 c +15.142266 0.000010 14.069732 0.000011 12.694968 0.000015 c +12.665000 0.000015 l +11.865768 0.000015 l +11.960117 0.227383 11.995039 0.458319 11.995039 0.665009 c +11.995039 0.867359 11.961351 1.099674 11.865652 1.330017 c +12.665000 1.330017 l +14.076104 1.330017 15.094439 1.330534 15.894838 1.395929 c +16.687475 1.460690 17.207642 1.585747 17.633049 1.802504 c +18.448732 2.218115 19.111902 2.881285 19.527514 3.696968 c +19.744270 4.122375 19.869328 4.642542 19.934088 5.435179 c +19.999483 6.235579 20.000000 7.253912 20.000000 8.665017 c +h +4.839176 1.463717 m +5.019685 1.436121 5.217113 1.413744 5.435162 1.395929 c +6.235561 1.330534 7.253895 1.330017 8.665000 1.330017 c +8.917085 1.330017 l +9.089041 1.282415 9.281227 1.236177 9.496844 1.188450 c +9.692974 1.145035 9.908489 1.100388 10.145796 1.052359 c +10.205174 1.040361 l +10.345039 1.012230 l +10.553735 0.970564 10.665039 0.873343 10.665039 0.665009 c +10.665039 0.456675 10.553735 0.359453 10.345039 0.303898 c +10.198030 0.275911 l +10.197282 0.275768 l +9.941029 0.226841 9.709103 0.181644 9.498774 0.137638 c +9.277951 0.091434 9.080934 0.046541 8.904569 0.000015 c +8.665000 0.000015 l +8.635032 0.000015 l +7.260268 0.000011 6.187734 0.000010 5.326858 0.070345 c +4.451973 0.141827 3.737294 0.289253 3.093144 0.617464 c +2.960023 0.685293 2.830011 0.758167 2.703350 0.835844 c +2.754484 0.931044 2.854025 0.984205 2.985039 1.012230 c +3.127856 1.040684 l +3.199264 1.054987 l +3.432428 1.101791 3.644342 1.145407 3.837319 1.187834 c +4.085014 1.242292 4.301511 1.294796 4.491705 1.349581 c +4.618789 1.386187 4.734118 1.423809 4.839176 1.463717 c +h +2.875670 2.346601 m +2.433620 2.718178 2.067664 3.176529 1.802487 3.696968 c +1.585731 4.122375 1.460673 4.642542 1.395913 5.435179 c +1.330517 6.235579 1.330000 7.253913 1.330000 8.665017 c +1.330000 12.665017 l +1.330000 13.877960 1.330382 14.800699 1.372022 15.544275 c +1.298869 15.586044 1.227320 15.634769 1.158346 15.691064 c +0.845746 15.946198 0.667074 16.291241 0.604262 16.638165 c +0.528978 17.029308 0.484173 17.260752 0.441731 17.424160 c +0.403060 17.434570 0.360459 17.445160 0.312742 17.456297 c +0.186964 17.018599 0.114287 16.541172 0.070330 16.003159 c +-0.000006 15.142287 -0.000004 14.069757 0.000000 12.695003 c +0.000000 12.665017 l +0.000000 8.665017 l +0.000000 8.635032 l +-0.000004 7.260277 -0.000006 6.187748 0.070330 5.326874 c +0.141811 4.451988 0.289237 3.737310 0.617448 3.093161 c +0.888394 2.561399 1.239850 2.079239 1.656398 1.662100 c +1.702632 1.724312 1.754487 1.784615 1.812361 1.842388 c +2.121504 2.150995 2.482045 2.264723 2.706828 2.312807 c +2.716328 2.314838 l +2.725856 2.316732 l +2.777156 2.326925 2.827075 2.336874 2.875670 2.346601 c +h +8.332518 4.500008 m +8.313696 4.589556 l +8.264160 4.874943 8.134342 5.234236 7.824867 5.533813 c +7.711397 5.643654 7.588928 5.730836 7.462107 5.798476 c +7.526080 5.818954 7.594269 5.830009 7.665039 5.830009 c +13.665039 5.830009 l +14.032309 5.830009 14.330039 5.532278 14.330039 5.165009 c +14.330039 4.797739 14.032309 4.500008 13.665039 4.500008 c +8.332518 4.500008 l +h +0.871893 18.684687 m +1.324676 19.403400 1.933466 20.011248 2.652964 20.462925 c +2.655908 20.453205 l +2.724026 20.229588 2.800882 20.070131 2.914969 19.948479 c +2.922706 19.940228 2.930614 19.932152 2.938702 19.924240 c +3.060279 19.805334 3.222550 19.723848 3.455697 19.651859 c +3.550516 19.622581 3.657057 19.594875 3.777352 19.566862 c +3.750158 19.554100 3.723372 19.540993 3.696951 19.527531 c +2.881269 19.111919 2.218098 18.448750 1.802487 17.633066 c +1.792514 17.613493 1.782735 17.593719 1.773147 17.573727 c +1.747679 17.687672 1.722332 17.789173 1.695314 17.880003 c +1.626394 18.111698 1.546598 18.273962 1.426172 18.396198 c +1.420495 18.401960 1.414726 18.407633 1.408866 18.413219 c +1.398906 18.422550 l +1.275799 18.535866 1.112183 18.613361 0.880678 18.682093 c +0.871893 18.684687 l +h +7.330039 12.165009 m +7.330039 14.006878 8.823170 15.500009 10.665039 15.500009 c +12.506908 15.500009 14.000039 14.006878 14.000039 12.165009 c +14.000039 10.323139 12.506908 8.830009 10.665039 8.830009 c +8.823170 8.830009 7.330039 10.323139 7.330039 12.165009 c +h +10.665039 16.830009 m +8.088631 16.830009 6.000039 14.741417 6.000039 12.165009 c +6.000039 9.588600 8.088631 7.500009 10.665039 7.500009 c +13.241447 7.500009 15.330039 9.588600 15.330039 12.165009 c +15.330039 14.741417 13.241447 16.830009 10.665039 16.830009 c +h +f* +n +Q +q +1.000000 0.000000 -0.000000 1.000000 4.000000 1.000000 cm +0.000000 0.478431 1.000000 scn +2.505619 20.000000 m +2.629215 20.000000 2.730338 20.067720 2.764045 20.214447 c +2.765165 20.220694 l +3.067419 21.907476 3.069506 21.919125 4.764046 22.234762 c +4.910113 22.268623 5.000000 22.358917 5.000000 22.494356 c +5.000000 22.641083 4.910113 22.731377 4.764046 22.765236 c +3.115385 23.094265 3.111211 23.114223 2.792694 24.637449 c +2.764045 24.774267 l +2.730338 24.920994 2.640450 25.000000 2.505619 25.000000 c +2.370788 25.000000 2.269665 24.909706 2.247193 24.774267 c +2.211266 24.607843 l +1.889418 23.113951 1.884714 23.092119 0.235956 22.765236 c +0.089889 22.731377 0.000000 22.629797 0.000000 22.494356 c +0.000000 22.370203 0.089889 22.268623 0.235956 22.234762 c +0.257272 22.230537 l +1.098396 22.063789 1.514779 21.981245 1.761133 21.731190 c +2.002639 21.486053 2.080742 21.079935 2.235412 20.275688 c +2.239290 20.255526 2.243215 20.235113 2.247193 20.214447 c +2.269665 20.079006 2.370788 20.000000 2.505619 20.000000 c +h +20.994783 14.000000 m +21.151304 14.000000 21.234783 14.093750 21.255651 14.239583 c +21.265360 14.292361 l +21.631285 16.282001 21.639460 16.326447 23.760000 16.729168 c +23.916521 16.770832 24.000000 16.843750 24.000000 17.000000 c +24.000000 17.156250 23.916521 17.229166 23.760000 17.260416 c +21.693047 17.675112 21.682287 17.726425 21.291733 19.588629 c +21.255651 19.760416 l +21.234783 19.906250 21.151304 20.000000 20.994783 20.000000 c +20.848696 20.000000 20.775652 19.906250 20.733913 19.760416 c +20.715693 19.673904 20.698399 19.591003 20.681820 19.511526 c +20.681557 19.510262 l +20.309143 17.724892 20.297527 17.669214 18.240000 17.260416 c +18.093912 17.229166 18.000000 17.156250 18.000000 17.000000 c +18.000000 16.843750 18.093912 16.770832 18.240000 16.729168 c +20.341238 16.321869 20.348595 16.282850 20.708492 14.374265 c +20.733913 14.239583 l +20.775652 14.093750 20.848696 14.000000 20.994783 14.000000 c +h +7.340869 0.319445 m +7.313043 0.125000 7.201739 0.000000 6.993044 0.000000 c +6.798261 0.000000 6.700870 0.125000 6.645218 0.319445 c +6.633644 0.380648 6.622359 0.440495 6.611322 0.499023 c +6.131461 3.043798 6.121650 3.095825 3.320000 3.638889 c +3.125217 3.694445 3.000000 3.791666 3.000000 4.000000 c +3.000000 4.208334 3.125217 4.305555 3.320000 4.347221 c +6.063370 4.892284 6.078856 4.966522 6.575408 7.347010 c +6.597620 7.453493 6.620794 7.564592 6.645218 7.680555 c +6.700870 7.875000 6.798261 8.000000 6.993044 8.000000 c +7.201739 8.000000 7.313043 7.875000 7.340869 7.680555 c +7.357415 7.601999 7.373423 7.525675 7.388978 7.451504 c +7.909715 4.968565 7.924064 4.900148 10.680000 4.347221 c +10.888696 4.305555 11.000000 4.208334 11.000000 4.000000 c +11.000000 3.791666 10.888696 3.694445 10.680000 3.638889 c +7.852612 3.101929 7.841713 3.042667 7.353813 0.389812 c +7.340869 0.319445 l +h +f* +n +Q + +endstream +endobj + +3 0 obj + 10217 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 30.000000 30.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000010307 00000 n +0000010331 00000 n +0000010504 00000 n +0000010578 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +10637 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CoverLogo.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CoverLogo.imageset/Contents.json new file mode 100644 index 0000000000..d725e5b17a --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CoverLogo.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "coverlogo_30.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CoverLogo.imageset/coverlogo_30.pdf b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CoverLogo.imageset/coverlogo_30.pdf new file mode 100644 index 0000000000..c1d5e17093 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CoverLogo.imageset/coverlogo_30.pdf @@ -0,0 +1,246 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 4.334961 2.674438 cm +0.000000 0.478431 1.000000 scn +8.635015 22.990601 m +8.665000 22.990601 l +12.665000 22.990601 l +12.694985 22.990601 l +14.069739 22.990604 15.142270 22.990606 16.003143 22.920271 c +16.878029 22.848789 17.592707 22.701363 18.236856 22.373152 c +19.302795 21.830030 20.169430 20.963394 20.712553 19.897457 c +21.040764 19.253307 21.188190 18.538628 21.259672 17.663742 c +21.330008 16.802868 21.330006 15.730331 21.330002 14.355569 c +21.330002 14.325601 l +21.330002 10.325601 l +21.330002 10.295632 l +21.330002 10.293933 l +21.330002 9.942374 21.330002 9.610583 21.328821 9.297045 c +21.262892 9.364636 21.195103 9.428216 21.126266 9.487875 c +20.797279 9.772998 20.412889 9.996371 19.999994 10.174931 c +20.000000 10.325601 l +20.000000 14.325601 l +20.000000 15.736705 19.999483 16.755039 19.934088 17.555439 c +19.869328 18.348076 19.744270 18.868240 19.527514 19.293650 c +19.111902 20.109333 18.448732 20.772503 17.633049 21.188114 c +17.207642 21.404869 16.687475 21.529926 15.894838 21.594688 c +15.094439 21.660084 14.076105 21.660601 12.665000 21.660601 c +8.665000 21.660601 l +7.253896 21.660601 6.235561 21.660084 5.435162 21.594688 c +4.642526 21.529926 4.122359 21.404869 3.696951 21.188114 c +2.881269 20.772503 2.218098 20.109333 1.802487 19.293650 c +1.585731 18.868240 1.460674 18.348076 1.395913 17.555439 c +1.330518 16.755039 1.330000 15.736706 1.330000 14.325601 c +1.330000 10.325601 l +1.330000 8.914496 1.330518 7.896162 1.395913 7.095762 c +1.460674 6.303125 1.585731 5.782959 1.802487 5.357552 c +2.218098 4.541868 2.881269 3.878698 3.696951 3.463087 c +4.122359 3.246330 4.642526 3.121273 5.435162 3.056513 c +6.235561 2.991117 7.253895 2.990601 8.665000 2.990601 c +11.191412 2.990601 l +11.134390 2.647013 11.166420 2.284071 11.302553 1.936174 c +11.340337 1.839617 11.384796 1.747652 11.435196 1.660599 c +8.665000 1.660599 l +8.635032 1.660599 l +7.260268 1.660595 6.187734 1.660593 5.326858 1.730928 c +4.451973 1.802410 3.737294 1.949837 3.093144 2.278048 c +2.027205 2.821171 1.160571 3.687805 0.617448 4.753744 c +0.289237 5.397894 0.141811 6.112572 0.070330 6.987457 c +-0.000006 7.848331 -0.000003 8.920860 0.000000 10.295615 c +0.000000 10.325601 l +0.000000 14.325601 l +0.000000 14.355586 l +-0.000003 15.730341 -0.000006 16.802872 0.070330 17.663742 c +0.141811 18.538628 0.289237 19.253307 0.617448 19.897457 c +1.160571 20.963394 2.027205 21.830030 3.093144 22.373152 c +3.737294 22.701363 4.451973 22.848789 5.326858 22.920271 c +6.187730 22.990606 7.260260 22.990604 8.635015 22.990601 c +h +7.665039 7.490592 m +12.464535 7.490592 l +12.354064 7.046155 12.303906 6.595884 12.295394 6.160591 c +7.665039 6.160591 l +7.297770 6.160591 7.000039 6.458323 7.000039 6.825592 c +7.000039 7.192862 7.297770 7.490592 7.665039 7.490592 c +h +10.665039 17.160591 m +8.823170 17.160591 7.330039 15.667461 7.330039 13.825592 c +7.330039 11.983723 8.823170 10.490592 10.665039 10.490592 c +12.506908 10.490592 14.000039 11.983723 14.000039 13.825592 c +14.000039 15.667461 12.506908 17.160591 10.665039 17.160591 c +h +6.000039 13.825592 m +6.000039 16.402000 8.088631 18.490593 10.665039 18.490593 c +13.241447 18.490593 15.330039 16.402000 15.330039 13.825592 c +15.330039 11.249184 13.241447 9.160592 10.665039 9.160592 c +8.088631 9.160592 6.000039 11.249184 6.000039 13.825592 c +h +18.076694 2.693638 m +18.076731 2.693611 18.075304 2.693218 18.072298 2.692541 c +18.076694 2.693638 l +h +18.314571 9.312943 m +16.560547 9.717718 15.229359 9.421805 14.419174 8.481991 c +13.649857 7.589583 13.526571 6.306986 13.694222 5.133429 c +13.760220 4.671452 13.874044 4.203140 14.026990 3.747423 c +13.780793 3.639557 13.564684 3.547737 13.390292 3.474932 c +13.242114 3.413071 13.124260 3.365025 13.043900 3.332621 c +13.003727 3.316420 12.972940 3.304136 12.952440 3.295998 c +12.929521 3.286926 l +12.924061 3.284779 l +12.922868 3.284309 l +12.922704 3.284246 l +12.922660 3.284229 l +12.580679 3.150377 12.411937 2.764647 12.545763 2.422647 c +12.679595 2.080631 13.065348 1.911865 13.407365 2.045696 c +13.165039 2.664974 l +13.407365 2.045696 13.407501 2.045750 13.407681 2.045820 c +13.408259 2.046047 l +13.410201 2.046810 l +13.417178 2.049555 l +13.443220 2.059860 l +13.465841 2.068840 13.498837 2.082008 13.541305 2.099133 c +13.626228 2.133379 13.749097 2.183477 13.902677 2.247593 c +14.080276 2.321735 14.299215 2.414738 14.548260 2.523756 c +14.691913 2.249905 14.849012 1.989143 15.017074 1.746874 c +15.651031 0.832989 16.574495 -0.000027 17.665039 -0.000027 c +18.450308 -0.000027 19.064745 0.122793 19.472816 0.472569 c +19.926409 0.861362 19.955040 1.377323 19.955040 1.664974 c +19.955040 1.759125 19.953171 1.815250 19.951641 1.861010 c +19.951641 1.861078 l +19.950190 1.904610 19.949051 1.938766 19.950130 1.987379 c +19.996878 1.994202 20.066002 1.999973 20.165039 1.999973 c +20.202976 1.999973 20.236422 1.999153 20.265808 1.997782 c +20.255564 1.968094 20.243641 1.935163 20.229881 1.898470 c +20.220390 1.873163 20.209251 1.844156 20.197189 1.812750 c +20.197121 1.812567 l +20.161291 1.719267 20.117346 1.604826 20.084358 1.503328 c +20.040909 1.369633 19.983757 1.166880 19.992804 0.949789 c +20.003326 0.697224 20.107481 0.402870 20.395264 0.203911 c +20.638384 0.035828 20.925451 -0.000027 21.165039 -0.000027 c +22.076580 -0.000027 22.721048 0.308167 23.142962 0.645695 c +23.349699 0.811085 23.497112 0.978571 23.595476 1.109722 c +23.644770 1.175447 23.682211 1.232664 23.709059 1.276884 c +23.722500 1.299023 23.733345 1.317999 23.741741 1.333267 c +23.752544 1.353363 l +23.756618 1.361227 l +23.758333 1.364594 l +23.759109 1.366135 l +23.759478 1.366867 l +23.759657 1.367224 23.759834 1.367577 23.165039 1.664974 c +23.759834 1.367577 l +23.924080 1.696072 23.790932 2.095520 23.462437 2.259768 c +23.137493 2.422237 22.743128 2.293713 22.575657 1.972963 c +22.572191 1.967125 l +22.565836 1.956657 22.552496 1.935749 22.531477 1.907722 c +22.489216 1.851376 22.417879 1.768860 22.312117 1.684250 c +22.143173 1.549095 21.868736 1.393639 21.442472 1.345188 c +21.452667 1.371820 21.463539 1.400387 21.475197 1.431477 c +21.523590 1.560520 21.584122 1.730461 21.617954 1.906981 c +21.651028 2.079536 21.673241 2.328693 21.576759 2.585970 c +21.345695 3.202147 20.701733 3.329973 20.165039 3.329973 c +19.590872 3.329973 19.026146 3.186672 18.757744 2.649870 c +18.647095 2.428570 18.626541 2.205524 18.621502 2.054316 c +18.618761 1.972124 18.621626 1.839178 18.623566 1.749092 c +18.623566 1.749023 l +18.624386 1.711035 18.625038 1.680676 18.625038 1.664974 c +18.625038 1.560623 18.617241 1.512627 18.610115 1.488873 c +18.609358 1.486341 l +18.608322 1.482874 18.608112 1.482170 18.608000 1.482183 c +18.607971 1.482187 18.607948 1.482237 18.607922 1.482300 c +18.607841 1.482479 18.607714 1.482767 18.607262 1.482380 c +18.577833 1.457153 18.379770 1.329973 17.665039 1.329973 c +17.255583 1.329973 16.679049 1.684458 16.109880 2.504948 c +15.986086 2.683403 15.868931 2.875460 15.760148 3.077400 c +16.623543 3.489267 17.604532 3.997330 18.459560 4.541439 c +18.993484 4.881208 19.497082 5.246778 19.896252 5.624077 c +20.280729 5.987486 20.640053 6.427725 20.769695 6.927771 c +20.838366 7.192643 20.843403 7.478890 20.748184 7.764547 c +20.653913 8.047359 20.476532 8.284380 20.251934 8.479030 c +19.820587 8.852865 19.161325 9.117538 18.314571 9.312943 c +h +17.745518 5.663507 m +16.968725 5.169186 16.063925 4.697718 15.244255 4.304955 c +15.138708 4.641562 15.059001 4.984503 15.010856 5.321518 c +14.866007 6.335461 15.023972 7.146614 15.426529 7.613581 c +15.788219 8.033141 16.519531 8.362228 18.015507 8.017003 c +18.793753 7.837408 19.196991 7.633331 19.380878 7.473964 c +19.463898 7.402012 19.482317 7.356318 19.486435 7.343964 c +19.489605 7.334455 19.495619 7.313085 19.482258 7.261551 c +19.447838 7.128784 19.311068 6.901054 18.982655 6.590637 c +18.668934 6.294106 18.242844 5.979988 17.745518 5.663507 c +h +19.864645 1.965506 m +19.864059 1.965872 19.867970 1.968330 19.878134 1.971779 c +19.870312 1.966864 19.865231 1.965137 19.864645 1.965506 c +h +20.452225 1.969948 m +20.454456 1.969154 20.455809 1.968904 20.456102 1.969086 c +20.456757 1.969490 20.452177 1.972034 20.440397 1.975502 c +20.445440 1.972702 20.449492 1.970919 20.452225 1.969948 c +h +20.316206 2.188324 m +20.316275 2.190765 l +20.316305 2.190790 20.316311 2.189999 20.316206 2.188324 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 8281 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 30.000000 30.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000008371 00000 n +0000008394 00000 n +0000008567 00000 n +0000008641 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +8700 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CustomWallpaper.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CustomWallpaper.imageset/Contents.json new file mode 100644 index 0000000000..e2029cfa22 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CustomWallpaper.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "backgroundphoto_30.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CustomWallpaper.imageset/backgroundphoto_30.pdf b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CustomWallpaper.imageset/backgroundphoto_30.pdf new file mode 100644 index 0000000000..13c5740a04 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/CustomWallpaper.imageset/backgroundphoto_30.pdf @@ -0,0 +1,261 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 0.748535 3.773193 cm +0.000000 0.478431 1.000000 scn +4.757206 18.226807 m +4.880801 18.226807 4.981925 18.294527 5.015633 18.441254 c +5.016752 18.447500 l +5.319006 20.134283 5.321093 20.145931 7.015633 20.461569 c +7.161700 20.495430 7.251587 20.585724 7.251587 20.721163 c +7.251587 20.867889 7.161700 20.958183 7.015633 20.992043 c +7.009992 20.993170 7.004371 20.994291 6.998768 20.995411 c +6.974089 21.000338 6.949782 21.005196 6.925841 21.009993 c +5.366710 21.322323 5.356907 21.369200 5.044281 22.864256 c +5.015633 23.001074 l +4.981925 23.147800 4.892037 23.226807 4.757206 23.226807 c +4.622375 23.226807 4.521252 23.136513 4.498779 23.001074 c +4.462852 22.834650 l +4.427909 22.672459 4.396705 22.527618 4.366728 22.397856 c +4.366711 22.397854 4.366693 22.397850 4.366676 22.397848 c +4.333385 22.253736 4.301609 22.128222 4.267910 22.018188 c +4.198979 21.793116 4.122003 21.632818 4.007557 21.510632 c +3.997129 21.499498 3.986389 21.488682 3.975317 21.478161 c +3.854285 21.363161 3.693424 21.283558 3.463661 21.213011 c +3.353117 21.179068 3.226623 21.147223 3.080942 21.114538 c +3.080941 21.114532 3.080940 21.114527 3.080939 21.114521 c +2.910971 21.076389 2.714886 21.037117 2.487543 20.992043 c +2.341476 20.958183 2.251587 20.856604 2.251587 20.721163 c +2.251587 20.597010 2.341476 20.495430 2.487543 20.461569 c +2.508859 20.457344 l +2.742526 20.411020 2.943414 20.371197 3.116983 20.332474 c +3.116984 20.332472 3.116984 20.332468 3.116984 20.332466 c +3.248639 20.303093 3.364575 20.274355 3.467176 20.243895 c +3.698681 20.175165 3.862297 20.097668 3.985404 19.984352 c +3.995363 19.975023 l +4.001225 19.969435 4.006993 19.963762 4.012670 19.958000 c +4.133096 19.835764 4.212892 19.673500 4.281812 19.441807 c +4.347450 19.221142 4.403223 18.937502 4.474832 18.565485 c +4.480278 18.537180 l +4.498730 18.441257 l +4.518395 18.322731 4.598297 18.247425 4.708312 18.230465 c +4.722797 18.228230 4.737804 18.227007 4.753265 18.226830 c +4.754576 18.226814 4.755889 18.226807 4.757206 18.226807 c +h +24.246370 12.226807 m +24.402891 12.226807 24.486370 12.320557 24.507238 12.466390 c +24.516947 12.519168 l +24.882872 14.508809 24.891047 14.553254 27.011587 14.955974 c +27.168108 14.997640 27.251587 15.070557 27.251587 15.226807 c +27.251587 15.383057 27.168108 15.455973 27.011587 15.487223 c +24.944633 15.901918 24.933874 15.953232 24.543320 17.815435 c +24.507238 17.987223 l +24.488979 18.114828 24.422783 18.202557 24.301662 18.222494 c +24.284359 18.225342 24.265936 18.226807 24.246370 18.226807 c +24.246353 18.226807 24.246338 18.226807 24.246321 18.226807 c +24.100233 18.226807 24.027189 18.133057 23.985451 17.987223 c +23.969278 17.910244 l +23.961321 17.872252 l +23.933092 17.737064 l +23.874269 17.455059 23.824446 17.216208 23.774141 17.012304 c +23.703089 16.724310 23.631075 16.506029 23.531374 16.334337 c +23.434690 16.167839 23.311968 16.045153 23.138842 15.945187 c +23.118267 15.933308 23.096983 15.921753 23.074944 15.910480 c +23.074944 15.910469 23.074938 15.910458 23.074938 15.910446 c +22.751860 15.745199 22.267017 15.641289 21.491587 15.487223 c +21.345499 15.455973 21.251587 15.383057 21.251587 15.226807 c +21.251587 15.070557 21.345499 14.997640 21.491587 14.955974 c +22.112539 14.835609 22.550634 14.747408 22.869003 14.633615 c +22.869003 14.633608 22.868999 14.633598 22.868999 14.633592 c +22.974224 14.595980 23.066374 14.555576 23.147720 14.510285 c +23.308416 14.420817 23.426970 14.312297 23.520954 14.168653 c +23.636623 13.991866 23.715080 13.761876 23.789087 13.448711 c +23.844049 13.216132 23.896557 12.937678 23.960030 12.601073 c +23.966673 12.565842 l +23.970533 12.545368 l +23.970539 12.545444 23.970545 12.545519 23.970551 12.545594 c +23.985500 12.466390 l +24.027239 12.320557 24.100283 12.226807 24.246370 12.226807 c +h +14.251544 19.561806 m +12.493417 19.561806 10.400085 19.873159 8.510571 20.249079 c +8.558092 20.402725 8.581537 20.562056 8.581537 20.721169 c +8.581537 21.033274 8.493270 21.363928 8.286821 21.652071 c +10.251558 21.242676 12.461045 20.891806 14.251544 20.891806 c +16.688210 20.891806 19.900843 21.541620 22.216579 22.104431 c +22.244366 22.111183 l +22.720421 22.226892 23.116310 22.323116 23.429131 22.373486 c +23.730738 22.422050 24.085314 22.453606 24.411896 22.324726 c +24.854853 22.149918 25.174654 21.830116 25.349463 21.387159 c +25.478342 21.060577 25.446789 20.706001 25.398224 20.404392 c +25.350077 20.105377 25.260033 19.730461 25.151121 19.282179 c +24.860535 19.481441 24.535259 19.556807 24.246321 19.556807 c +24.109430 19.556807 23.971371 19.539661 23.836353 19.504152 c +23.836788 19.505939 l +23.960970 20.016895 24.044144 20.361244 24.085136 20.615826 c +24.116716 20.811960 24.110395 20.888866 24.109098 20.904648 c +24.108902 20.907393 l +24.071024 20.999317 24.024054 21.046288 23.932131 21.084166 c +23.929386 21.084362 l +23.913607 21.085659 23.836702 21.091982 23.640562 21.060400 c +23.385981 21.019407 23.041632 20.936234 22.530676 20.812052 c +20.206852 20.247274 16.860207 19.561806 14.251544 19.561806 c +h +22.631655 12.467669 m +22.602537 12.041012 22.586542 11.625299 22.586542 11.226807 c +22.586542 8.618143 23.272011 5.271498 23.836788 2.947674 c +23.960970 2.436718 24.044144 2.092369 24.085136 1.837788 c +24.116716 1.641655 24.110395 1.564749 24.109098 1.548964 c +24.108902 1.546219 l +24.071024 1.454296 24.024054 1.407326 23.932131 1.369448 c +23.929386 1.369251 l +23.913601 1.367954 23.836695 1.361633 23.640562 1.393213 c +23.385983 1.434206 23.041632 1.517380 22.530676 1.641562 c +21.044149 2.002842 19.139084 2.413511 17.276388 2.662546 c +17.014088 2.219273 16.704496 1.807848 16.354368 1.435024 c +18.352102 1.218418 20.523932 0.760559 22.216579 0.349182 c +22.244303 0.342443 l +22.244366 0.342426 l +22.244583 0.342375 l +22.720547 0.226690 23.116360 0.130489 23.429131 0.080126 c +23.730738 0.031561 24.085314 0.000008 24.411896 0.128887 c +24.854853 0.303696 25.174654 0.623497 25.349463 1.066454 c +25.478342 1.393036 25.446789 1.747612 25.398224 2.049219 c +25.347860 2.361990 25.251659 2.757803 25.135975 3.233767 c +25.135923 3.233984 l +25.135906 3.234047 l +25.129168 3.261770 l +24.588932 5.484617 23.968536 8.533854 23.919634 10.929951 c +23.636820 10.988220 23.363411 11.124744 23.137119 11.350643 c +22.867224 11.620071 22.756607 11.926374 22.706791 12.100424 c +22.689970 12.159196 l +22.678612 12.219262 l +22.659204 12.321956 l +22.659182 12.322084 l +22.631655 12.467669 l +h +5.229526 16.966501 m +5.066857 16.917168 4.905797 16.896811 4.757156 16.896811 c +4.455744 16.896811 4.121994 16.979877 3.826485 17.190544 c +3.976629 16.469921 4.118893 15.716393 4.238856 14.962700 c +4.623399 15.231826 5.036524 15.463335 5.473050 15.652042 c +5.397152 16.096504 5.315010 16.536770 5.229526 16.966501 c +h +12.263523 13.442030 m +11.783911 13.557175 11.184472 13.561807 9.751537 13.561807 c +9.615499 13.561807 l +8.312892 13.561807 7.767750 13.557974 7.329850 13.462691 c +5.671649 13.101883 4.376461 11.806694 4.015652 10.148493 c +3.920388 9.710676 3.916537 9.160183 3.916537 7.845830 c +3.916538 7.806034 l +3.916559 7.307418 3.916570 7.007401 3.886761 6.717808 c +3.773773 5.620153 3.342675 4.579391 2.646411 3.723339 c +2.462717 3.497488 2.252196 3.286983 1.902508 2.937325 c +1.874773 2.909592 l +1.685575 2.720392 1.557790 2.592432 1.467287 2.494526 c +1.400132 2.421877 1.374395 2.387430 1.367698 2.378468 c +1.365830 2.376049 l +1.275192 2.194115 1.366466 1.973759 1.559202 1.909201 c +1.562236 1.908812 l +1.573308 1.907209 1.615863 1.901051 1.714722 1.897165 c +1.847948 1.891930 2.028787 1.891808 2.296353 1.891808 c +9.751537 1.891808 l +11.184472 1.891808 11.783911 1.896439 12.263523 2.011583 c +13.848611 2.392128 15.086215 3.629734 15.466761 5.214821 c +15.581905 5.694433 15.586536 6.293873 15.586536 7.726807 c +15.586536 9.159741 15.581905 9.759180 15.466761 10.238792 c +15.086215 11.823880 13.848611 13.061484 12.263523 13.442030 c +h +9.862087 14.891813 m +11.151264 14.891936 11.921191 14.892009 12.574005 14.735282 c +14.645407 14.237983 16.262714 12.620676 16.760014 10.549274 c +16.916740 9.896458 16.916668 9.126529 16.916546 7.837345 c +16.916538 7.726807 l +16.916546 7.616268 l +16.916668 6.327084 16.916740 5.557156 16.760014 4.904339 c +16.262714 2.832937 14.645407 1.215630 12.574005 0.718330 c +11.921206 0.561605 11.151302 0.561678 9.862179 0.561798 c +9.862162 0.561798 l +9.862096 0.561798 l +9.751537 0.561806 l +2.296353 0.561806 l +2.282249 0.561806 l +2.281802 0.561806 l +2.032090 0.561806 1.824975 0.561806 1.662498 0.568192 c +1.507339 0.574287 1.327234 0.587326 1.161439 0.640018 c +0.177813 0.952635 -0.287356 2.075651 0.187120 2.992233 c +0.267095 3.146727 0.385229 3.283298 0.490633 3.397324 c +0.601075 3.516802 0.747639 3.663364 0.924361 3.840084 c +0.934321 3.850042 l +1.319947 4.235668 1.479205 4.396076 1.614605 4.562550 c +2.147404 5.217625 2.477290 6.014040 2.563752 6.853992 c +2.585719 7.067402 2.586537 7.295616 2.586537 7.845830 c +2.586531 7.947674 l +2.586429 9.129831 2.586368 9.835228 2.716062 10.431272 c +3.187567 12.598217 4.880127 14.290776 7.047072 14.762282 c +7.643106 14.891973 8.342933 14.891913 9.514974 14.891812 c +9.514991 14.891812 l +9.615499 14.891807 l +9.751537 14.891807 l +9.862087 14.891813 l +h +f* +n +Q + +endstream +endobj + +3 0 obj + 9148 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 30.000000 30.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000009238 00000 n +0000009261 00000 n +0000009434 00000 n +0000009508 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +9567 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/EmojiStatus.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/EmojiStatus.imageset/Contents.json new file mode 100644 index 0000000000..88bed3c847 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/EmojiStatus.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "status_30.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/EmojiStatus.imageset/status_30.pdf b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/EmojiStatus.imageset/status_30.pdf new file mode 100644 index 0000000000..9b082adf4a --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/EmojiStatus.imageset/status_30.pdf @@ -0,0 +1,132 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +0.707107 0.707107 -0.707107 0.707107 21.364439 -3.965147 cm +0.000000 0.478431 1.000000 scn +8.477501 26.956255 m +7.981826 26.956255 7.580001 26.554430 7.580001 26.058754 c +7.580001 24.808754 l +7.580001 20.121254 l +7.580001 18.246254 l +7.580001 17.878986 7.282270 17.581255 6.915001 17.581255 c +6.547732 17.581255 6.250001 17.878986 6.250001 18.246254 c +6.250001 20.121254 l +6.250001 24.808754 l +6.250001 25.304430 5.848176 25.706255 5.352501 25.706255 c +4.856825 25.706255 4.455001 25.304430 4.455001 24.808754 c +4.455001 22.308754 l +4.455001 18.871254 l +4.455001 17.621254 l +4.455001 17.253986 4.157270 16.956255 3.790001 16.956255 c +3.422732 16.956255 3.125001 17.253986 3.125001 17.621254 c +3.125001 18.871254 l +3.125001 22.308754 l +3.125001 22.804430 2.723176 23.206255 2.227501 23.206255 c +1.731825 23.206255 1.330001 22.804430 1.330001 22.308754 c +1.330001 15.746254 l +1.330001 15.155370 1.330360 14.892024 1.344635 14.674225 c +1.568969 11.251553 4.295299 8.525223 7.717971 8.300888 c +7.935771 8.286613 8.199116 8.286255 8.790001 8.286255 c +11.187643 8.286255 13.360397 9.698269 14.334173 11.889265 c +17.002613 17.893257 l +17.168566 18.266649 17.011471 18.704527 16.645998 18.887264 c +16.268457 19.076035 15.809368 18.923004 15.620598 18.545464 c +13.759795 14.823858 l +13.621869 14.548006 13.312377 14.403186 13.012215 14.474044 c +12.712053 14.544903 12.500001 14.812843 12.500001 15.121255 c +12.500001 24.808754 l +12.500001 25.304430 12.098177 25.706255 11.602501 25.706255 c +11.106825 25.706255 10.705001 25.304430 10.705001 24.808754 c +10.705001 18.871254 l +10.705001 18.246254 l +10.705001 17.878986 10.407270 17.581255 10.040001 17.581255 c +9.672731 17.581255 9.375001 17.878986 9.375001 18.246254 c +9.375001 18.871254 l +9.375001 24.808754 l +9.375001 26.058754 l +9.375001 26.554430 8.973177 26.956255 8.477501 26.956255 c +h +10.582383 26.789459 m +10.279950 27.660770 9.451770 28.286255 8.477501 28.286255 c +7.503232 28.286255 6.675053 27.660770 6.372619 26.789459 c +6.066981 26.947191 5.720144 27.036255 5.352501 27.036255 c +4.122287 27.036255 3.125001 26.038969 3.125001 24.808754 c +3.125001 24.348055 l +2.850438 24.469067 2.546816 24.536255 2.227501 24.536255 c +0.997287 24.536255 0.000000 23.538969 0.000000 22.308754 c +0.000000 15.746254 l +0.000000 15.713201 l +0.000000 15.713175 l +-0.000006 15.164083 -0.000010 14.854123 0.017483 14.587238 c +0.285469 10.498560 3.542306 7.241722 7.630985 6.973736 c +7.897878 6.956242 8.207848 6.956245 8.756974 6.956253 c +8.790001 6.956253 l +11.713245 6.956253 14.362301 8.677807 15.549542 11.349100 c +18.217983 17.353092 l +18.672722 18.376255 18.242252 19.576122 17.240791 20.076851 c +16.206259 20.594118 14.948276 20.174789 14.431009 19.140257 c +13.830001 17.938240 l +13.830001 24.808754 l +13.830001 26.038969 12.832715 27.036255 11.602501 27.036255 c +11.234859 27.036255 10.888021 26.947191 10.582383 26.789459 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 2901 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 30.000000 30.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000002991 00000 n +0000003014 00000 n +0000003187 00000 n +0000003261 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +3320 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/LinkColor.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/LinkColor.imageset/Contents.json new file mode 100644 index 0000000000..4827940cc1 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/LinkColor.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "linkcolor_30.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/LinkColor.imageset/linkcolor_30.pdf b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/LinkColor.imageset/linkcolor_30.pdf new file mode 100644 index 0000000000..2d2a623cd8 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/LinkColor.imageset/linkcolor_30.pdf @@ -0,0 +1,219 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 4.284912 3.292084 cm +0.000000 0.478431 1.000000 scn +18.746542 19.734386 m +16.935171 21.545755 13.998362 21.545755 12.186993 19.734386 c +9.686993 17.234386 l +9.427294 16.974688 9.006239 16.974688 8.746540 17.234386 c +8.486842 17.494083 8.486842 17.915138 8.746540 18.174839 c +11.246540 20.674837 l +13.577307 23.005604 17.356226 23.005604 19.686995 20.674837 c +20.179169 20.182663 20.567411 19.625917 20.851727 19.031868 c +20.803699 19.035963 20.756313 19.037916 20.709869 19.037916 c +20.316519 19.037916 19.913555 18.896423 19.600668 18.584080 c +19.592823 18.576187 l +19.378183 18.993382 19.096090 19.384838 18.746542 19.734386 c +h +20.260195 12.897485 m +20.920572 13.785061 21.302557 14.814440 21.406155 15.866064 c +21.318581 16.029062 21.251387 16.231705 21.185596 16.490952 c +21.128996 16.713997 21.073431 16.978931 21.006819 17.296545 c +21.004112 17.309454 l +20.994904 17.353354 l +20.970737 17.468332 l +20.949869 17.614166 20.866390 17.707916 20.709869 17.707916 c +20.563782 17.707916 20.490738 17.614166 20.448999 17.468332 c +20.432827 17.391354 l +20.424870 17.353361 l +20.396641 17.218174 l +20.396624 17.218086 l +20.396561 17.217789 l +20.337770 16.935951 20.287971 16.697226 20.237690 16.493414 c +20.189157 16.296696 20.140177 16.132504 20.082228 15.993470 c +20.015707 15.323755 19.803888 14.665747 19.446770 14.070580 c +19.506126 14.045732 19.560778 14.019506 19.611269 13.991395 c +19.771965 13.901926 19.890518 13.793406 19.984503 13.649761 c +20.100172 13.472975 20.178629 13.242985 20.252636 12.929821 c +20.260195 12.897485 l +h +18.807087 12.887949 m +18.729610 12.911728 18.639875 12.935325 18.532253 12.960550 c +16.246542 10.674838 l +14.435172 8.863469 11.498362 8.863469 9.686993 10.674838 c +9.446299 10.915532 9.238028 11.175499 9.061817 11.449507 c +8.863164 11.758413 8.451705 11.847792 8.142797 11.649138 c +7.833890 11.450484 7.744512 11.039025 7.943166 10.730118 c +8.170393 10.376781 8.438306 10.042621 8.746540 9.734386 c +11.077307 7.403620 14.856226 7.403620 17.186995 9.734386 c +19.143881 11.691273 l +19.142160 11.700371 l +19.122753 11.803064 l +19.122730 11.803185 l +19.031767 12.284682 18.978355 12.567389 18.919037 12.776890 c +18.909550 12.810394 18.901060 12.837479 18.893795 12.859035 c +18.871344 12.867266 18.842791 12.876991 18.807087 12.887949 c +h +2.986220 3.401642 m +2.884041 3.487600 2.784698 3.578667 2.688527 3.674837 c +0.877158 5.486206 0.877158 8.423016 2.688527 10.234385 c +5.188527 12.734385 l +6.999896 14.545753 9.936707 14.545753 11.748075 12.734385 c +11.988770 12.493690 12.197041 12.233724 12.373251 11.959716 c +12.571904 11.650809 12.983363 11.561431 13.292271 11.760084 c +13.601177 11.958738 13.690556 12.370197 13.491901 12.679105 c +13.264675 13.032442 12.996762 13.366602 12.688528 13.674836 c +10.357761 16.005604 6.578842 16.005604 4.248075 13.674836 c +1.748075 11.174836 l +-0.579096 8.847667 -0.582686 5.076809 1.737303 2.745184 c +1.775440 2.793240 1.817077 2.840044 1.862407 2.885296 c +2.171551 3.193903 2.532092 3.307631 2.756874 3.355715 c +2.766374 3.357746 l +2.775903 3.359640 l +2.848739 3.374111 2.918794 3.388094 2.986220 3.401642 c +h +4.785145 2.468969 m +4.709134 2.442739 4.628162 2.417379 4.541751 2.392488 c +4.351557 2.337704 4.135060 2.285200 3.887365 2.230742 c +3.694388 2.188314 3.482475 2.144699 3.249310 2.097895 c +3.177902 2.083591 l +3.035085 2.055138 l +2.919933 2.030506 2.829098 1.986454 2.774070 1.911509 c +4.867711 0.582691 7.608359 0.685259 9.602119 2.219210 c +9.583541 2.223270 9.565132 2.227320 9.546891 2.231358 c +9.296606 2.286758 9.077891 2.340153 8.885743 2.396004 c +8.504775 2.506737 8.228245 2.627125 8.017174 2.791960 c +7.008180 2.295216 5.856144 2.187553 4.785145 2.468969 c +h +10.783853 3.329710 m +12.688528 5.234385 l +12.948226 5.494083 12.948226 5.915138 12.688528 6.174837 c +12.428829 6.434536 12.007774 6.434536 11.748075 6.174837 c +9.248740 3.675501 l +9.560926 3.583939 9.993661 3.492182 10.656712 3.359152 c +10.695142 3.351458 10.737858 3.341881 10.783853 3.329710 c +h +f* +n +Q +q +1.000000 0.000000 -0.000000 1.000000 4.000000 1.000000 cm +0.000000 0.478431 1.000000 scn +2.505619 20.000000 m +2.629215 20.000000 2.730338 20.067720 2.764045 20.214447 c +2.765165 20.220694 l +3.067419 21.907476 3.069506 21.919125 4.764046 22.234762 c +4.910113 22.268623 5.000000 22.358917 5.000000 22.494356 c +5.000000 22.641083 4.910113 22.731377 4.764046 22.765236 c +3.115385 23.094265 3.111211 23.114223 2.792694 24.637449 c +2.764045 24.774267 l +2.730338 24.920994 2.640450 25.000000 2.505619 25.000000 c +2.370788 25.000000 2.269665 24.909706 2.247193 24.774267 c +2.211266 24.607843 l +1.889418 23.113951 1.884714 23.092119 0.235956 22.765236 c +0.089889 22.731377 0.000000 22.629797 0.000000 22.494356 c +0.000000 22.370203 0.089889 22.268623 0.235956 22.234762 c +0.257272 22.230537 l +1.098396 22.063789 1.514779 21.981245 1.761133 21.731190 c +2.002639 21.486053 2.080742 21.079935 2.235412 20.275688 c +2.239290 20.255526 2.243215 20.235113 2.247193 20.214447 c +2.269665 20.079006 2.370788 20.000000 2.505619 20.000000 c +h +20.994783 14.000000 m +21.151304 14.000000 21.234783 14.093750 21.255651 14.239583 c +21.265360 14.292361 l +21.631285 16.282001 21.639460 16.326447 23.760000 16.729168 c +23.916521 16.770832 24.000000 16.843750 24.000000 17.000000 c +24.000000 17.156250 23.916521 17.229166 23.760000 17.260416 c +21.693047 17.675112 21.682287 17.726425 21.291733 19.588629 c +21.255651 19.760416 l +21.234783 19.906250 21.151304 20.000000 20.994783 20.000000 c +20.848696 20.000000 20.775652 19.906250 20.733913 19.760416 c +20.715693 19.673904 20.698399 19.591003 20.681820 19.511526 c +20.681557 19.510262 l +20.309143 17.724892 20.297527 17.669214 18.240000 17.260416 c +18.093912 17.229166 18.000000 17.156250 18.000000 17.000000 c +18.000000 16.843750 18.093912 16.770832 18.240000 16.729168 c +20.341238 16.321869 20.348595 16.282850 20.708492 14.374265 c +20.733913 14.239583 l +20.775652 14.093750 20.848696 14.000000 20.994783 14.000000 c +h +7.340869 0.319445 m +7.313043 0.125000 7.201739 0.000000 6.993044 0.000000 c +6.798261 0.000000 6.700870 0.125000 6.645218 0.319445 c +6.633644 0.380648 6.622359 0.440495 6.611322 0.499023 c +6.131461 3.043798 6.121650 3.095825 3.320000 3.638889 c +3.125217 3.694445 3.000000 3.791666 3.000000 4.000000 c +3.000000 4.208334 3.125217 4.305555 3.320000 4.347221 c +6.063370 4.892284 6.078856 4.966522 6.575408 7.347010 c +6.597620 7.453493 6.620794 7.564592 6.645218 7.680555 c +6.700870 7.875000 6.798261 8.000000 6.993044 8.000000 c +7.201739 8.000000 7.313043 7.875000 7.340869 7.680555 c +7.357415 7.601999 7.373423 7.525675 7.388978 7.451504 c +7.909715 4.968565 7.924064 4.900148 10.680000 4.347221 c +10.888696 4.305555 11.000000 4.208334 11.000000 4.000000 c +11.000000 3.791666 10.888696 3.694445 10.680000 3.638889 c +7.852612 3.101929 7.841713 3.042667 7.353813 0.389812 c +7.340869 0.319445 l +h +f* +n +Q + +endstream +endobj + +3 0 obj + 6857 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 30.000000 30.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000006947 00000 n +0000006970 00000 n +0000007143 00000 n +0000007217 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +7276 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/LinkLogo.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/LinkLogo.imageset/Contents.json new file mode 100644 index 0000000000..3d4dddeddc --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/LinkLogo.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "linkicon_30.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/LinkLogo.imageset/linkicon_30.pdf b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/LinkLogo.imageset/linkicon_30.pdf new file mode 100644 index 0000000000..0f88db3bf4 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/LinkLogo.imageset/linkicon_30.pdf @@ -0,0 +1,218 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 4.284912 3.113007 cm +0.000000 0.478431 1.000000 scn +12.186993 19.913464 m +13.998362 21.724833 16.935169 21.724833 18.746540 19.913464 c +20.557909 18.102093 20.557909 15.165284 18.746540 13.353915 c +17.585676 12.193052 l +17.612038 12.187213 17.638416 12.181248 17.664806 12.175158 c +18.127182 12.068456 18.589745 11.932618 19.021931 11.748403 c +19.686993 12.413464 l +22.017757 14.744230 22.017757 18.523148 19.686993 20.853914 c +17.356224 23.184681 13.577307 23.184681 11.246540 20.853914 c +8.746540 18.353916 l +8.486841 18.094215 8.486841 17.673161 8.746540 17.413464 c +9.006239 17.153765 9.427294 17.153765 9.686993 17.413464 c +12.186993 19.913464 l +h +9.686993 10.853915 m +10.269916 10.270992 10.969393 9.875662 11.710407 9.667924 c +11.544407 9.245638 11.443607 8.808676 11.390870 8.376139 c +10.422292 8.640283 9.507279 9.152724 8.746540 9.913464 c +8.438305 10.221698 8.170393 10.555858 7.943166 10.909195 c +7.744512 11.218102 7.833890 11.629561 8.142797 11.828216 c +8.451704 12.026869 8.863163 11.937490 9.061817 11.628584 c +9.238028 11.354576 9.446299 11.094609 9.686993 10.853915 c +h +11.480906 6.086744 m +11.491286 6.097126 l +11.492414 6.091276 l +11.490078 6.090351 l +11.486289 6.088860 l +11.486141 6.088802 l +11.485865 6.088694 l +11.480906 6.086744 l +h +9.248075 3.853914 m +10.354701 4.960541 l +10.175631 4.507072 10.160928 3.987410 10.352602 3.497576 c +10.391468 3.398251 10.437399 3.303785 10.489594 3.214527 c +10.188528 2.913462 l +7.857761 0.582695 4.078842 0.582695 1.748075 2.913462 c +-0.582692 5.244228 -0.582692 9.023148 1.748075 11.353913 c +4.248075 13.853913 l +6.578842 16.184681 10.357761 16.184681 12.688528 13.853913 c +12.996761 13.545679 13.264675 13.211519 13.491901 12.858182 c +13.690556 12.549274 13.601177 12.137815 13.292271 11.939161 c +12.983362 11.740508 12.571903 11.829886 12.373251 12.138793 c +12.197041 12.412801 11.988770 12.672768 11.748075 12.913462 c +9.936707 14.724831 6.999896 14.724831 5.188527 12.913462 c +2.688527 10.413462 l +0.877158 8.602093 0.877158 5.665283 2.688527 3.853914 c +4.499897 2.042545 7.436706 2.042545 9.248075 3.853914 c +h +17.364620 10.874345 m +15.610595 11.279119 14.279408 10.983207 13.469223 10.043392 c +12.699905 9.150985 12.576620 7.868387 12.744271 6.694830 c +12.810268 6.232853 12.924093 5.764542 13.077039 5.308825 c +12.830842 5.200958 12.614733 5.109138 12.440341 5.036333 c +12.292163 4.974472 12.174309 4.926426 12.093949 4.894022 c +12.053776 4.877821 12.022989 4.865538 12.002489 4.857399 c +11.979569 4.848328 l +11.974110 4.846180 l +11.972917 4.845711 l +11.972753 4.845648 l +11.972709 4.845631 l +11.630728 4.711779 11.461986 4.326048 11.595812 3.984049 c +11.729644 3.642033 12.115396 3.473267 12.457414 3.607098 c +12.215088 4.226376 l +12.457414 3.607098 12.457550 3.607151 12.457729 3.607222 c +12.458308 3.607449 l +12.460250 3.608212 l +12.467227 3.610956 l +12.493269 3.621262 l +12.515890 3.630241 12.548885 3.643410 12.591353 3.660534 c +12.676277 3.694780 12.799146 3.744879 12.952725 3.808994 c +13.130324 3.883137 13.349264 3.976139 13.598309 4.085157 c +13.741961 3.811306 13.899061 3.550545 14.067122 3.308275 c +14.701079 2.394390 15.624545 1.561375 16.715088 1.561375 c +17.500357 1.561375 18.114794 1.684195 18.522865 2.033970 c +18.976458 2.422764 19.005089 2.938725 19.005089 3.226376 c +19.005089 3.320526 19.003220 3.376652 19.001690 3.422411 c +19.001690 3.422480 l +19.000238 3.466011 18.999100 3.500168 19.000179 3.548780 c +19.046926 3.555603 19.116051 3.561375 19.215088 3.561375 c +19.253025 3.561375 19.286470 3.560555 19.315857 3.559183 c +19.305613 3.529495 19.293690 3.496565 19.279930 3.459871 c +19.270439 3.434565 19.259300 3.405558 19.247238 3.374151 c +19.247169 3.373968 l +19.211340 3.280668 19.167395 3.166227 19.134407 3.064730 c +19.090958 2.931034 19.033806 2.728281 19.042852 2.511190 c +19.053375 2.258625 19.157530 1.964272 19.445312 1.765312 c +19.688433 1.597229 19.975500 1.561375 20.215088 1.561375 c +21.126629 1.561375 21.771097 1.869568 22.193010 2.207096 c +22.399748 2.372486 22.547161 2.539972 22.645525 2.671124 c +22.694818 2.736849 22.732260 2.794065 22.759108 2.838285 c +22.772549 2.860424 22.783394 2.879400 22.791790 2.894669 c +22.802593 2.914764 l +22.806667 2.922628 l +22.808382 2.925995 l +22.809158 2.927536 l +22.809526 2.928268 l +22.809706 2.928625 22.809883 2.928978 22.215088 3.226376 c +22.809883 2.928978 l +22.974129 3.257473 22.840981 3.656921 22.512486 3.821169 c +22.187542 3.983639 21.793177 3.855114 21.625706 3.534365 c +21.622240 3.528526 l +21.615885 3.518059 21.602545 3.497150 21.581526 3.469124 c +21.539265 3.412777 21.467928 3.330261 21.362165 3.245651 c +21.193222 3.110497 20.918785 2.955040 20.492521 2.906590 c +20.502716 2.933222 20.513588 2.961788 20.525246 2.992878 c +20.573639 3.121922 20.634171 3.291862 20.668003 3.468382 c +20.701077 3.640938 20.723289 3.890095 20.626808 4.147371 c +20.395744 4.763548 19.751781 4.891375 19.215088 4.891375 c +18.640921 4.891375 18.076195 4.748074 17.807793 4.211271 c +17.697144 3.989971 17.676590 3.766926 17.671551 3.615717 c +17.668810 3.533525 17.671675 3.400579 17.673615 3.310493 c +17.673615 3.310425 l +17.674435 3.272436 17.675087 3.242077 17.675087 3.226376 c +17.675087 3.122025 17.667290 3.074028 17.660164 3.050274 c +17.658463 3.044598 17.658184 3.043568 17.658049 3.043585 c +17.657978 3.043594 17.657946 3.043888 17.657768 3.043959 c +17.657671 3.043999 17.657528 3.043968 17.657310 3.043781 c +17.627882 3.018555 17.429819 2.891375 16.715088 2.891375 c +16.305632 2.891375 15.729096 3.245859 15.159928 4.066349 c +15.036135 4.244804 14.918980 4.436861 14.810197 4.638802 c +15.673593 5.050669 16.654581 5.558731 17.509609 6.102840 c +18.043533 6.442610 18.547131 6.808180 18.946301 7.185477 c +19.330778 7.548887 19.690102 7.989126 19.819744 8.489172 c +19.888414 8.754045 19.893452 9.040292 19.798233 9.325949 c +19.703962 9.608761 19.526581 9.845781 19.301983 10.040431 c +18.870636 10.414267 18.211374 10.678940 17.364620 10.874345 c +h +16.795567 7.224910 m +16.018774 6.730587 15.113974 6.259119 14.294304 5.866356 c +14.188757 6.202963 14.109050 6.545904 14.060905 6.882919 c +13.916056 7.896862 14.074020 8.708015 14.476578 9.174982 c +14.838268 9.594543 15.569581 9.923630 17.065556 9.578404 c +17.843801 9.398809 18.247040 9.194733 18.430927 9.035365 c +18.513947 8.963413 18.532366 8.917719 18.536484 8.905365 c +18.539654 8.895856 18.545668 8.874486 18.532307 8.822952 c +18.497887 8.690186 18.361116 8.462456 18.032703 8.152038 c +17.718983 7.855507 17.292892 7.541389 16.795567 7.224910 c +h +18.914694 3.526907 m +18.914108 3.527273 18.918018 3.529732 18.928183 3.533180 c +18.920361 3.528265 18.915279 3.526539 18.914694 3.526907 c +h +19.506151 3.530487 m +19.505497 3.530083 19.499607 3.531816 19.490446 3.536903 c +19.502226 3.533436 19.506805 3.530891 19.506151 3.530487 c +h +19.366323 3.752167 m +19.366255 3.749725 l +19.366301 3.750448 19.366325 3.751007 19.366337 3.751406 c +19.366350 3.751930 19.366341 3.752180 19.366323 3.752167 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 6963 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 30.000000 30.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000007053 00000 n +0000007076 00000 n +0000007249 00000 n +0000007323 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +7382 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/NameColor.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/NameColor.imageset/Contents.json new file mode 100644 index 0000000000..9c449e53d0 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/NameColor.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "namecolor_30.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/NameColor.imageset/namecolor_30.pdf b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/NameColor.imageset/namecolor_30.pdf new file mode 100644 index 0000000000..55e90a4ad0 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/NameColor.imageset/namecolor_30.pdf @@ -0,0 +1,290 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 4.334961 4.334991 cm +0.000000 0.478431 1.000000 scn +5.785331 19.957972 m +6.528978 19.999634 7.451835 20.000017 8.665000 20.000017 c +12.665000 20.000017 l +14.076105 20.000017 15.094439 19.999500 15.894838 19.934105 c +16.687475 19.869343 17.207642 19.744286 17.633049 19.527531 c +18.448732 19.111919 19.111902 18.448750 19.527514 17.633066 c +19.540468 17.607641 19.553097 17.581877 19.565403 17.555737 c +19.876143 17.857920 20.272636 17.995008 20.659822 17.995008 c +20.715282 17.995008 20.772083 17.992229 20.829720 17.986332 c +20.793468 18.071121 20.754486 18.154573 20.712553 18.236874 c +20.169430 19.302811 19.302795 20.169447 18.236856 20.712568 c +17.592707 21.040779 16.878029 21.188206 16.003143 21.259687 c +15.142270 21.330023 14.069739 21.330021 12.694985 21.330017 c +12.665000 21.330017 l +8.665000 21.330017 l +8.635015 21.330017 l +7.260260 21.330021 6.187730 21.330023 5.326858 21.259687 c +4.791599 21.215956 4.316306 21.143795 3.880442 21.019201 c +3.890508 20.977545 3.900183 20.939672 3.909794 20.904621 c +4.067824 20.860769 4.298860 20.812462 4.689383 20.734526 c +4.709473 20.730516 l +4.729430 20.725889 l +4.989579 20.665585 5.319242 20.527437 5.589351 20.228039 c +5.666474 20.142551 5.731493 20.051903 5.785331 19.957972 c +h +20.000000 12.665017 m +20.000000 12.493482 l +20.081505 12.334187 20.143467 12.137091 20.202589 11.886913 c +20.257551 11.654334 20.310059 11.375880 20.373531 11.039274 c +20.380175 11.004044 l +20.384460 10.981330 l +20.398952 10.904593 l +20.440691 10.758759 20.513735 10.665009 20.659822 10.665009 c +20.816343 10.665009 20.899822 10.758759 20.920691 10.904593 c +20.930399 10.957369 l +20.939493 11.006810 l +20.949696 11.062221 l +21.010153 11.390343 21.061460 11.662903 21.115931 11.891387 c +21.177372 12.149121 21.242840 12.350769 21.330002 12.512812 c +21.330002 12.665017 l +21.330002 12.694985 l +21.330002 12.695578 l +21.330002 13.540377 21.330002 14.271040 21.313671 14.908587 c +21.246031 15.055716 21.190304 15.232279 21.135550 15.448044 c +21.078949 15.671088 21.023384 15.936024 20.956772 16.253637 c +20.954065 16.266546 l +20.944857 16.310446 l +20.920691 16.425425 l +20.899822 16.571259 20.816343 16.665009 20.659822 16.665009 c +20.513735 16.665009 20.440691 16.571259 20.398952 16.425425 c +20.382780 16.348446 l +20.374823 16.310453 l +20.346594 16.175266 l +20.346577 16.175179 l +20.346514 16.174881 l +20.287724 15.893044 20.237925 15.654318 20.187643 15.450506 c +20.126453 15.202480 20.064547 15.006169 19.984858 14.846785 c +19.999807 14.239014 20.000000 13.524947 20.000000 12.665017 c +h +20.000000 8.665017 m +20.000000 9.476658 l +20.210934 9.380445 20.436922 9.335009 20.659822 9.335009 c +20.872946 9.335009 21.105841 9.376009 21.330002 9.477490 c +21.330002 8.665017 l +21.330002 8.635049 l +21.330006 7.260285 21.330008 6.187751 21.259672 5.326874 c +21.188190 4.451988 21.040764 3.737310 20.712553 3.093161 c +20.169430 2.027222 19.302795 1.160587 18.236856 0.617464 c +17.592707 0.289253 16.878029 0.141827 16.003143 0.070345 c +15.142266 0.000010 14.069732 0.000011 12.694968 0.000015 c +12.665000 0.000015 l +11.865768 0.000015 l +11.960117 0.227383 11.995039 0.458319 11.995039 0.665009 c +11.995039 0.867359 11.961351 1.099674 11.865652 1.330017 c +12.665000 1.330017 l +14.076104 1.330017 15.094439 1.330534 15.894838 1.395929 c +16.687475 1.460690 17.207642 1.585747 17.633049 1.802504 c +18.448732 2.218115 19.111902 2.881285 19.527514 3.696968 c +19.744270 4.122375 19.869328 4.642542 19.934088 5.435179 c +19.999483 6.235579 20.000000 7.253912 20.000000 8.665017 c +h +4.839176 1.463717 m +5.019685 1.436121 5.217113 1.413744 5.435162 1.395929 c +6.235561 1.330534 7.253895 1.330017 8.665000 1.330017 c +8.917085 1.330017 l +9.089041 1.282415 9.281227 1.236177 9.496844 1.188450 c +9.692974 1.145035 9.908489 1.100388 10.145796 1.052359 c +10.205174 1.040361 l +10.345039 1.012230 l +10.553735 0.970564 10.665039 0.873343 10.665039 0.665009 c +10.665039 0.456675 10.553735 0.359453 10.345039 0.303898 c +10.198030 0.275911 l +10.197282 0.275768 l +9.941029 0.226841 9.709103 0.181644 9.498774 0.137638 c +9.277951 0.091434 9.080934 0.046541 8.904569 0.000015 c +8.665000 0.000015 l +8.635032 0.000015 l +7.260268 0.000011 6.187734 0.000010 5.326858 0.070345 c +4.451973 0.141827 3.737294 0.289253 3.093144 0.617464 c +2.960023 0.685293 2.830011 0.758167 2.703350 0.835844 c +2.754484 0.931044 2.854025 0.984205 2.985039 1.012230 c +3.127856 1.040684 l +3.199264 1.054987 l +3.432428 1.101791 3.644342 1.145407 3.837319 1.187834 c +4.085014 1.242292 4.301511 1.294796 4.491705 1.349581 c +4.618789 1.386187 4.734118 1.423809 4.839176 1.463717 c +h +2.875670 2.346601 m +2.433620 2.718178 2.067664 3.176529 1.802487 3.696968 c +1.585731 4.122375 1.460673 4.642542 1.395913 5.435179 c +1.330517 6.235579 1.330000 7.253913 1.330000 8.665017 c +1.330000 12.665017 l +1.330000 13.877960 1.330382 14.800699 1.372022 15.544275 c +1.298869 15.586044 1.227320 15.634769 1.158346 15.691064 c +0.845746 15.946198 0.667074 16.291241 0.604262 16.638165 c +0.528978 17.029308 0.484173 17.260752 0.441731 17.424160 c +0.403060 17.434570 0.360459 17.445160 0.312742 17.456297 c +0.186964 17.018599 0.114287 16.541172 0.070330 16.003159 c +-0.000006 15.142287 -0.000004 14.069757 0.000000 12.695003 c +0.000000 12.665017 l +0.000000 8.665017 l +0.000000 8.635032 l +-0.000004 7.260277 -0.000006 6.187748 0.070330 5.326874 c +0.141811 4.451988 0.289237 3.737310 0.617448 3.093161 c +0.888394 2.561399 1.239850 2.079239 1.656398 1.662100 c +1.702632 1.724312 1.754487 1.784615 1.812361 1.842388 c +2.121504 2.150995 2.482045 2.264723 2.706828 2.312807 c +2.716328 2.314838 l +2.725856 2.316732 l +2.777156 2.326925 2.827075 2.336874 2.875670 2.346601 c +h +0.871893 18.684687 m +1.324676 19.403400 1.933466 20.011248 2.652964 20.462925 c +2.655908 20.453205 l +2.724026 20.229588 2.800882 20.070131 2.914969 19.948479 c +2.922706 19.940228 2.930614 19.932152 2.938702 19.924240 c +3.060279 19.805334 3.222550 19.723848 3.455697 19.651859 c +3.550516 19.622581 3.657057 19.594875 3.777352 19.566862 c +3.750158 19.554100 3.723372 19.540993 3.696951 19.527531 c +2.881269 19.111919 2.218098 18.448750 1.802487 17.633066 c +1.792514 17.613493 1.782735 17.593719 1.773147 17.573727 c +1.747679 17.687672 1.722332 17.789173 1.695314 17.880003 c +1.626394 18.111698 1.546598 18.273962 1.426172 18.396198 c +1.420495 18.401960 1.414726 18.407633 1.408866 18.413219 c +1.398906 18.422550 l +1.275799 18.535866 1.112183 18.613361 0.880678 18.682093 c +0.871893 18.684687 l +h +7.164961 15.329995 m +6.797691 15.329995 6.499961 15.032265 6.499961 14.664995 c +6.499961 14.297726 6.797691 13.999995 7.164961 13.999995 c +9.999961 13.999995 l +9.999961 6.664995 l +9.999961 6.297726 10.297691 5.999995 10.664961 5.999995 c +11.032230 5.999995 11.329961 6.297726 11.329961 6.664995 c +11.329961 13.999995 l +14.164961 13.999995 l +14.532230 13.999995 14.829961 14.297726 14.829961 14.664995 c +14.829961 15.032265 14.532230 15.329995 14.164961 15.329995 c +10.664961 15.329995 l +7.164961 15.329995 l +h +f* +n +Q +q +1.000000 0.000000 -0.000000 1.000000 4.000000 1.000000 cm +0.000000 0.478431 1.000000 scn +2.505619 20.000000 m +2.629215 20.000000 2.730338 20.067720 2.764045 20.214447 c +2.765165 20.220694 l +3.067419 21.907478 3.069506 21.919125 4.764046 22.234762 c +4.910113 22.268623 5.000000 22.358917 5.000000 22.494356 c +5.000000 22.641083 4.910113 22.731377 4.764046 22.765236 c +3.115385 23.094265 3.111211 23.114223 2.792694 24.637449 c +2.764045 24.774267 l +2.730338 24.920994 2.640450 25.000000 2.505619 25.000000 c +2.370788 25.000000 2.269665 24.909706 2.247193 24.774267 c +2.211266 24.607843 l +1.889418 23.113951 1.884714 23.092119 0.235956 22.765236 c +0.089889 22.731377 0.000000 22.629797 0.000000 22.494356 c +0.000000 22.370203 0.089889 22.268623 0.235956 22.234762 c +0.257272 22.230537 l +1.098396 22.063789 1.514779 21.981245 1.761133 21.731190 c +2.002639 21.486053 2.080742 21.079935 2.235412 20.275688 c +2.239290 20.255526 2.243215 20.235113 2.247193 20.214447 c +2.269665 20.079006 2.370788 20.000000 2.505619 20.000000 c +h +20.994783 14.000000 m +21.151304 14.000000 21.234783 14.093750 21.255651 14.239583 c +21.265360 14.292361 l +21.631285 16.282001 21.639460 16.326447 23.760000 16.729168 c +23.916521 16.770832 24.000000 16.843750 24.000000 17.000000 c +24.000000 17.156250 23.916521 17.229166 23.760000 17.260416 c +21.693047 17.675112 21.682287 17.726425 21.291733 19.588629 c +21.255651 19.760416 l +21.234783 19.906250 21.151304 20.000000 20.994783 20.000000 c +20.848696 20.000000 20.775652 19.906250 20.733913 19.760416 c +20.715693 19.673904 20.698399 19.591003 20.681820 19.511526 c +20.681557 19.510262 l +20.309143 17.724892 20.297527 17.669214 18.240000 17.260416 c +18.093912 17.229166 18.000000 17.156250 18.000000 17.000000 c +18.000000 16.843750 18.093912 16.770832 18.240000 16.729168 c +20.341238 16.321869 20.348595 16.282850 20.708492 14.374265 c +20.733913 14.239583 l +20.775652 14.093750 20.848696 14.000000 20.994783 14.000000 c +h +7.340869 0.319445 m +7.313043 0.125000 7.201739 0.000000 6.993044 0.000000 c +6.798261 0.000000 6.700870 0.125000 6.645218 0.319445 c +6.633644 0.380648 6.622359 0.440495 6.611322 0.499023 c +6.131461 3.043798 6.121650 3.095825 3.320000 3.638889 c +3.125217 3.694445 3.000000 3.791666 3.000000 4.000000 c +3.000000 4.208334 3.125217 4.305555 3.320000 4.347221 c +6.063370 4.892284 6.078856 4.966522 6.575408 7.347010 c +6.597620 7.453493 6.620794 7.564592 6.645218 7.680555 c +6.700870 7.875000 6.798261 8.000000 6.993044 8.000000 c +7.201739 8.000000 7.313043 7.875000 7.340869 7.680555 c +7.357415 7.601999 7.373423 7.525675 7.388978 7.451504 c +7.909715 4.968565 7.924064 4.900148 10.680000 4.347221 c +10.888696 4.305555 11.000000 4.208334 11.000000 4.000000 c +11.000000 3.791666 10.888696 3.694445 10.680000 3.638889 c +7.852612 3.101929 7.841713 3.042667 7.353813 0.389812 c +7.340869 0.319445 l +h +f* +n +Q + +endstream +endobj + +3 0 obj + 9833 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 30.000000 30.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000009923 00000 n +0000009946 00000 n +0000010119 00000 n +0000010193 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +10252 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Reaction.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Reaction.imageset/Contents.json new file mode 100644 index 0000000000..c1d950e292 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Reaction.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "reaction_30.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Reaction.imageset/reaction_30.pdf b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Reaction.imageset/reaction_30.pdf new file mode 100644 index 0000000000..c26bad28b6 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Reaction.imageset/reaction_30.pdf @@ -0,0 +1,95 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 3.709961 4.027466 cm +0.000000 0.478431 1.000000 scn +6.692846 21.012543 m +2.932139 21.012543 0.000000 17.982958 0.000000 13.793707 c +0.000000 8.925182 4.040345 4.312546 9.951600 0.505657 c +9.964154 0.497768 l +10.140424 0.389732 10.347890 0.272778 10.557463 0.180889 c +10.750595 0.096207 11.017006 -0.000004 11.290000 -0.000004 c +11.565557 -0.000004 11.832716 0.094200 12.030427 0.180889 c +12.242528 0.273884 12.449573 0.392376 12.624151 0.502941 c +12.624162 0.502926 l +12.628400 0.505657 l +18.539654 4.312546 22.580002 8.925182 22.580002 13.793707 c +22.580002 17.981396 19.659847 21.012543 15.897674 21.012543 c +13.917096 21.012543 12.359436 20.090942 11.292705 18.683296 c +10.234852 20.086395 8.670308 21.012543 6.692846 21.012543 c +h +1.330000 13.793707 m +1.330000 17.325989 3.741920 19.682543 6.692846 19.682543 c +8.498928 19.682543 9.872611 18.689632 10.704028 17.140173 c +10.819477 16.925020 11.043550 16.790440 11.287719 16.789600 c +11.531888 16.788765 11.756879 16.921804 11.873800 17.136160 c +12.726985 18.700333 14.091994 19.682543 15.897674 19.682543 c +18.847134 19.682543 21.250000 17.327551 21.250000 13.793707 c +21.250000 9.657809 17.759064 5.392298 11.910530 1.625286 c +11.770142 1.536472 11.625534 1.455585 11.496355 1.398945 c +11.364441 1.341106 11.299468 1.331387 11.290930 1.330151 c +11.287782 1.330845 l +11.273407 1.333771 11.211363 1.346405 11.091535 1.398945 c +10.961029 1.456169 10.813124 1.537617 10.665328 1.627953 c +4.819291 5.394312 1.330000 9.658786 1.330000 13.793707 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 1572 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 30.000000 30.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000001662 00000 n +0000001685 00000 n +0000001858 00000 n +0000001932 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +1991 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Story.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Story.imageset/Contents.json new file mode 100644 index 0000000000..d18b85eb13 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Story.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "storiescircle_30.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Story.imageset/storiescircle_30.pdf b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Story.imageset/storiescircle_30.pdf new file mode 100644 index 0000000000..50cf27645f --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Story.imageset/storiescircle_30.pdf @@ -0,0 +1,149 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 3.834961 3.834961 cm +0.000000 0.478431 1.000000 scn +11.165000 22.330017 m +10.420193 22.330017 9.691781 22.256994 8.986743 22.117517 c +8.626456 22.046242 8.392166 21.696390 8.463442 21.336103 c +8.534718 20.975817 8.884568 20.741528 9.244855 20.812803 c +9.865344 20.935555 10.507315 21.000017 11.165000 21.000017 c +11.822685 21.000017 12.464656 20.935555 13.085145 20.812803 c +13.445432 20.741528 13.795282 20.975817 13.866557 21.336103 c +13.937833 21.696390 13.703543 22.046242 13.343256 22.117517 c +12.638218 22.256994 11.909807 22.330017 11.165000 22.330017 c +h +17.368916 20.449049 m +17.063728 20.653368 16.650688 20.571596 16.446369 20.266407 c +16.242050 19.961218 16.323822 19.548180 16.629011 19.343861 c +17.701820 18.625633 18.625614 17.701838 19.343842 16.629030 c +19.548161 16.323841 19.961201 16.242069 20.266388 16.446388 c +20.571579 16.650707 20.653351 17.063745 20.449032 17.368935 c +19.634087 18.586206 18.586189 19.634106 17.368916 20.449049 c +h +5.700987 19.343861 m +6.006176 19.548180 6.087948 19.961216 5.883629 20.266407 c +5.679309 20.571596 5.266272 20.653366 4.961082 20.449047 c +3.743810 19.634104 2.695912 18.586206 1.880969 17.368935 c +1.676650 17.063744 1.758421 16.650707 2.063610 16.446388 c +2.368799 16.242067 2.781838 16.323839 2.986157 16.629028 c +3.704383 17.701836 4.628180 18.625633 5.700987 19.343861 c +h +22.117500 13.343274 m +22.046223 13.703561 21.696373 13.937851 21.336086 13.866575 c +20.975800 13.795300 20.741508 13.445449 20.812786 13.085162 c +20.935535 12.464673 21.000000 11.822702 21.000000 11.165017 c +21.000000 10.507332 20.935535 9.865361 20.812786 9.244872 c +20.741508 8.884585 20.975800 8.534735 21.336086 8.463460 c +21.696373 8.392184 22.046223 8.626474 22.117500 8.986761 c +22.256977 9.691799 22.330002 10.420210 22.330002 11.165017 c +22.330002 11.909824 22.256977 12.638236 22.117500 13.343274 c +h +1.517214 13.085162 m +1.588490 13.445449 1.354200 13.795300 0.993913 13.866575 c +0.633626 13.937850 0.283776 13.703560 0.212500 13.343273 c +0.073023 12.638235 0.000000 11.909824 0.000000 11.165017 c +0.000000 10.420210 0.073023 9.691798 0.212501 8.986760 c +0.283776 8.626473 0.633627 8.392183 0.993913 8.463459 c +1.354200 8.534735 1.588490 8.884585 1.517215 9.244872 c +1.394463 9.865361 1.330000 10.507332 1.330000 11.165017 c +1.330000 11.822702 1.394463 12.464673 1.517214 13.085162 c +h +20.449032 4.961102 m +20.653351 5.266289 20.571579 5.679329 20.266388 5.883648 c +19.961201 6.087967 19.548161 6.006195 19.343842 5.701006 c +18.625618 4.628197 17.701820 3.704403 16.629013 2.986176 c +16.323822 2.781857 16.242052 2.368816 16.446371 2.063629 c +16.650690 1.758438 17.063728 1.676666 17.368919 1.880985 c +18.586189 2.695930 19.634087 3.743828 20.449032 4.961102 c +h +2.986157 5.701004 m +2.781838 6.006195 2.368800 6.087965 2.063611 5.883646 c +1.758422 5.679327 1.676650 5.266289 1.880970 4.961098 c +2.695913 3.743828 3.743811 2.695930 4.961083 1.880985 c +5.266273 1.676666 5.679311 1.758438 5.883630 2.063629 c +6.087949 2.368816 6.006178 2.781857 5.700988 2.986176 c +4.628181 3.704399 3.704384 4.628197 2.986157 5.701004 c +h +9.244855 1.517231 m +8.884568 1.588509 8.534718 1.354218 8.463442 0.993931 c +8.392167 0.633644 8.626457 0.283794 8.986744 0.212517 c +9.691782 0.073040 10.420193 0.000015 11.165000 0.000015 c +11.909807 0.000015 12.638219 0.073040 13.343257 0.212517 c +13.703544 0.283794 13.937834 0.633644 13.866558 0.993931 c +13.795282 1.354218 13.445432 1.588509 13.085145 1.517231 c +12.464656 1.394482 11.822685 1.330017 11.165000 1.330017 c +10.507315 1.330017 9.865344 1.394482 9.244855 1.517231 c +h +4.830000 11.165017 m +4.830000 14.663741 7.666276 17.500017 11.165000 17.500017 c +14.663724 17.500017 17.500000 14.663741 17.500000 11.165017 c +17.500000 7.666293 14.663724 4.830017 11.165000 4.830017 c +7.666276 4.830017 4.830000 7.666293 4.830000 11.165017 c +h +11.165000 18.830017 m +6.931737 18.830017 3.500000 15.398279 3.500000 11.165017 c +3.500000 6.931754 6.931737 3.500017 11.165000 3.500017 c +15.398263 3.500017 18.830000 6.931754 18.830000 11.165017 c +18.830000 15.398279 15.398263 18.830017 11.165000 18.830017 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 4150 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 30.000000 30.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000004240 00000 n +0000004263 00000 n +0000004436 00000 n +0000004510 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +4569 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Wallpaper.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Wallpaper.imageset/Contents.json new file mode 100644 index 0000000000..f6f2b9a3ab --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Wallpaper.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "background_30.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Wallpaper.imageset/background_30.pdf b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Wallpaper.imageset/background_30.pdf new file mode 100644 index 0000000000..a4b92bd23a --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/BoostPerk/Wallpaper.imageset/background_30.pdf @@ -0,0 +1,239 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 0.748535 3.334717 cm +0.000000 0.478431 1.000000 scn +5.757206 17.665283 m +5.880801 17.665283 5.981925 17.733004 6.015633 17.879730 c +6.016752 17.885977 l +6.319006 19.572760 6.321093 19.584408 8.015633 19.900045 c +8.161700 19.933907 8.251587 20.024200 8.251587 20.159639 c +8.251587 20.306366 8.161700 20.396660 8.015633 20.430519 c +6.366971 20.759548 6.362798 20.779507 6.044281 22.302732 c +6.015633 22.439550 l +5.981925 22.586277 5.892037 22.665283 5.757206 22.665283 c +5.622375 22.665283 5.521252 22.574989 5.498779 22.439550 c +5.462852 22.273127 l +5.141005 20.779234 5.136301 20.757402 3.487543 20.430519 c +3.341476 20.396660 3.251587 20.295080 3.251587 20.159639 c +3.251587 20.035486 3.341476 19.933907 3.487543 19.900045 c +3.508859 19.895821 l +3.914725 19.815361 4.221698 19.754505 4.458393 19.684975 c +4.458390 19.684971 4.458387 19.684967 4.458384 19.684961 c +4.467170 19.682367 l +4.698675 19.613636 4.862291 19.536140 4.985398 19.422825 c +4.995357 19.413494 l +5.001218 19.407907 5.006986 19.402235 5.012663 19.396473 c +5.133090 19.274237 5.212885 19.111973 5.281805 18.880278 c +5.308824 18.789448 5.334171 18.687946 5.359639 18.574001 c +5.359651 18.574028 5.359664 18.574055 5.359677 18.574081 c +5.399532 18.395777 5.439682 18.187004 5.486998 17.940971 c +5.490876 17.920811 5.494802 17.900396 5.498779 17.879730 c +5.521252 17.744289 5.622375 17.665283 5.757206 17.665283 c +h +24.326115 11.674725 m +24.431749 11.701917 24.490248 11.786128 24.507238 11.904866 c +24.516947 11.957644 l +24.882872 13.947286 24.891047 13.991731 27.011587 14.394450 c +27.168108 14.436116 27.251587 14.509033 27.251587 14.665283 c +27.251587 14.821533 27.168108 14.894449 27.011587 14.925699 c +24.944633 15.340395 24.933874 15.391708 24.543320 17.253912 c +24.507238 17.425699 l +24.488979 17.553305 24.422783 17.641033 24.301662 17.660971 c +24.284359 17.663818 24.265936 17.665283 24.246370 17.665283 c +24.246351 17.665283 24.246332 17.665283 24.246313 17.665283 c +24.100225 17.665283 24.027182 17.571533 23.985443 17.425699 c +23.969271 17.348721 l +23.961313 17.310728 l +23.933084 17.175541 l +23.933067 17.175453 l +23.933004 17.175156 l +23.874214 16.893318 23.824415 16.654593 23.774134 16.450781 c +23.712944 16.202755 23.651037 16.006443 23.571348 15.847059 c +23.571348 15.847021 23.571352 15.846979 23.571352 15.846940 c +23.301785 15.307896 22.828709 15.191364 21.491587 14.925699 c +21.345499 14.894449 21.251587 14.821533 21.251587 14.665283 c +21.251587 14.509033 21.345499 14.436116 21.491587 14.394450 c +22.823523 14.136271 23.314125 14.026070 23.586491 13.493872 c +23.586491 13.493756 l +23.667995 13.334461 23.729958 13.137365 23.789080 12.887188 c +23.844042 12.654609 23.896549 12.376155 23.960022 12.039549 c +23.966665 12.004318 l +23.970951 11.981605 l +23.985443 11.904867 l +24.027182 11.759033 24.100225 11.665283 24.246313 11.665283 c +24.246321 11.665283 24.246336 11.665283 24.246344 11.665283 c +24.326115 11.674725 m +24.302010 11.668520 24.275450 11.665283 24.246370 11.665283 c +h +12.251492 21.000292 m +11.038326 21.000292 10.115470 20.999908 9.371822 20.958246 c +9.317985 21.052177 9.252966 21.142826 9.175842 21.228312 c +8.905733 21.527712 8.576070 21.665859 8.315921 21.726164 c +8.295964 21.730789 l +8.275874 21.734800 l +7.885352 21.812737 7.654315 21.861044 7.496285 21.904896 c +7.486675 21.939947 7.476999 21.977819 7.466934 22.019476 c +7.902797 22.144070 8.378090 22.216230 8.913349 22.259962 c +9.774221 22.330297 10.846751 22.330296 12.221506 22.330292 c +12.251492 22.330292 l +16.251492 22.330292 l +16.281477 22.330292 l +17.656231 22.330296 18.728762 22.330297 19.589634 22.259962 c +20.464520 22.188480 21.179197 22.041054 21.823347 21.712843 c +22.889286 21.169722 23.755920 20.303085 24.299044 19.237148 c +24.340977 19.154848 24.379959 19.071396 24.416210 18.986607 c +24.358574 18.992504 24.301773 18.995283 24.246313 18.995283 c +23.859127 18.995283 23.462633 18.858194 23.151894 18.556011 c +23.139587 18.582151 23.126959 18.607914 23.114004 18.633341 c +22.698393 19.449024 22.035223 20.112194 21.219540 20.527805 c +20.794132 20.744560 20.273966 20.869617 19.481329 20.934380 c +18.680929 20.999775 17.662596 21.000292 16.251492 21.000292 c +12.251492 21.000292 l +h +23.586491 10.476933 m +23.586491 9.665292 l +23.586491 8.254187 23.585974 7.235853 23.520578 6.435453 c +23.455818 5.642817 23.330761 5.122650 23.114004 4.697243 c +22.698393 3.881559 22.035223 3.218390 21.219540 2.802778 c +20.794132 2.586021 20.273966 2.460964 19.481329 2.396204 c +18.918163 2.350191 18.247105 2.336298 17.407255 2.332104 c +17.146738 1.851034 16.831821 1.404419 16.470541 1.000296 c +17.755117 1.000437 18.768629 1.003542 19.589634 1.070620 c +20.464520 1.142101 21.179197 1.289528 21.823347 1.617739 c +22.889286 2.160862 23.755920 3.027496 24.299044 4.093435 c +24.627254 4.737585 24.774681 5.452263 24.846163 6.327148 c +24.916498 7.188025 24.916496 8.260560 24.916492 9.635324 c +24.916492 9.665292 l +24.916492 10.477765 l +24.692331 10.376284 24.459436 10.335283 24.246313 10.335283 c +24.023413 10.335283 23.797424 10.380719 23.586491 10.476933 c +h +4.028222 18.424435 m +3.989551 18.434845 3.946950 18.445435 3.899234 18.456572 c +3.773456 18.018873 3.700778 17.541447 3.656821 17.003433 c +3.589741 16.182411 3.586638 15.168874 3.586498 13.884255 c +3.990639 14.245567 4.437260 14.560516 4.918303 14.821041 c +4.921660 15.493275 4.931233 16.057365 4.958515 16.544550 c +4.885362 16.586319 4.813812 16.635044 4.744837 16.691338 c +4.432238 16.946472 4.253565 17.291515 4.190753 17.638439 c +4.115469 18.029583 4.070664 18.261026 4.028222 18.424435 c +h +12.263523 12.880507 m +11.783911 12.995651 11.184472 13.000283 9.751537 13.000283 c +9.615499 13.000283 l +8.312892 13.000283 7.767750 12.996450 7.329850 12.901168 c +5.671649 12.540359 4.376461 11.245171 4.015652 9.586969 c +3.920388 9.149153 3.916537 8.598660 3.916537 7.284307 c +3.916538 7.244511 l +3.916559 6.745894 3.916570 6.445877 3.886761 6.156284 c +3.773773 5.058630 3.342675 4.017868 2.646411 3.161816 c +2.462717 2.935965 2.252196 2.725460 1.902508 2.375801 c +1.874773 2.348068 l +1.685575 2.158869 1.557790 2.030909 1.467287 1.933002 c +1.400132 1.860353 1.374395 1.825907 1.367698 1.816944 c +1.365830 1.814526 l +1.275192 1.632591 1.366466 1.412235 1.559202 1.347677 c +1.562236 1.347288 l +1.573308 1.345686 1.615863 1.339527 1.714722 1.335642 c +1.847948 1.330406 2.028787 1.330284 2.296353 1.330284 c +9.751537 1.330284 l +11.184472 1.330284 11.783911 1.334915 12.263523 1.450060 c +13.848611 1.830605 15.086215 3.068211 15.466761 4.653297 c +15.581905 5.132910 15.586536 5.732349 15.586536 7.165283 c +15.586536 8.598218 15.581905 9.197657 15.466761 9.677269 c +15.086215 11.262357 13.848611 12.499961 12.263523 12.880507 c +h +9.862087 14.330290 m +11.151264 14.330413 11.921191 14.330485 12.574005 14.173759 c +14.645407 13.676459 16.262714 12.059153 16.760014 9.987751 c +16.916740 9.334934 16.916668 8.565005 16.916546 7.275822 c +16.916538 7.165283 l +16.916546 7.054745 l +16.916668 5.765560 16.916740 4.995632 16.760014 4.342815 c +16.262714 2.271414 14.645407 0.654106 12.574005 0.156807 c +11.921206 0.000082 11.151302 0.000154 9.862179 0.000275 c +9.862162 0.000275 l +9.862096 0.000275 l +9.751537 0.000282 l +2.296353 0.000282 l +2.282249 0.000282 l +2.281802 0.000282 l +2.032090 0.000282 1.824975 0.000282 1.662498 0.006668 c +1.507339 0.012764 1.327234 0.025803 1.161439 0.078495 c +0.177813 0.391111 -0.287356 1.514128 0.187120 2.430710 c +0.267095 2.585203 0.385229 2.721775 0.490633 2.835800 c +0.601075 2.955278 0.747639 3.101841 0.924361 3.278561 c +0.934321 3.288519 l +1.319947 3.674145 1.479205 3.834553 1.614605 4.001026 c +2.147404 4.656101 2.477290 5.452517 2.563752 6.292469 c +2.585719 6.505878 2.586537 6.734093 2.586537 7.284307 c +2.586531 7.386150 l +2.586429 8.568308 2.586368 9.273705 2.716062 9.869748 c +3.187567 12.036694 4.880127 13.729253 7.047072 14.200759 c +7.643106 14.330450 8.342933 14.330390 9.514974 14.330289 c +9.514991 14.330289 l +9.615499 14.330283 l +9.751537 14.330283 l +9.862087 14.330290 l +h +f* +n +Q + +endstream +endobj + +3 0 obj + 8007 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 30.000000 30.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000008097 00000 n +0000008120 00000 n +0000008293 00000 n +0000008367 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +8426 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index c76d1b750d..46ee58418a 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -18800,50 +18800,21 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G initialMediaAreas: initialMediaAreas, initialVideoPosition: nil, transitionIn: nil, - transitionOut: { finished, isNew in - if finished { - if let transitionOut = externalState.transitionOut?(externalState.storyTarget, externalState.isPeerArchived), let destinationView = transitionOut.destinationView { - return MediaEditorScreen.TransitionOut( - destinationView: destinationView, - destinationRect: transitionOut.destinationRect, - destinationCornerRadius: transitionOut.destinationCornerRadius - ) - } else { - return nil - } - } else { - return nil - } + transitionOut: { _, _ in + return nil }, completion: { result, commit in let target: Stories.PendingTarget - let targetPeerId: EnginePeer.Id if let sendAsPeerId = result.options.sendAsPeerId { target = .peer(sendAsPeerId) - targetPeerId = sendAsPeerId } else { target = .myStories - targetPeerId = context.account.peerId } externalState.storyTarget = target - let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: targetPeerId)) - |> deliverOnMainQueue).startStandalone(next: { peer in - guard let peer else { - return - } - - if case let .user(user) = peer { - externalState.isPeerArchived = user.storiesHidden ?? false - - } else if case let .channel(channel) = peer { - externalState.isPeerArchived = channel.storiesHidden ?? false - } - - if let rootController = context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface { - rootController.proceedWithStoryUpload(target: target, result: result, existingMedia: nil, forwardInfo: nil, externalState: externalState, commit: commit) - } - }) + if let rootController = context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface { + rootController.proceedWithStoryUpload(target: target, result: result, existingMedia: nil, forwardInfo: nil, externalState: externalState, commit: commit) + } } ) self.push(controller) diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index 5b6dc4d37e..cfba962d1d 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -49,6 +49,7 @@ import ChatMessageItemImpl import ChatRecentActionsController import PeerInfoScreen import ChatQrCodeScreen +import UndoUI private final class AccountUserInterfaceInUseContext { let subscribers = Bag<(Bool) -> Void>() @@ -1948,6 +1949,72 @@ public final class SharedAccountContextImpl: SharedAccountContext { return PremiumLimitScreen(context: context, subject: mappedSubject, count: count, forceDark: forceDark, cancel: cancel, action: action) } + public func makePremiumGiftController(context: AccountContext) -> ViewController { + let options = Promise<[PremiumGiftCodeOption]>() + options.set(context.engine.payments.premiumGiftCodeOptions(peerId: nil)) + + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + + let limit: Int32 = 10 + var reachedLimitImpl: ((Int32) -> Void)? + let controller = context.sharedContext.makeContactMultiselectionController(ContactMultiselectionControllerParams(context: context, mode: .premiumGifting, options: [], isPeerEnabled: { peer in + if case let .user(user) = peer, user.botInfo == nil { + return true + } else { + return false + } + }, limit: limit, reachedLimit: { limit in + reachedLimitImpl?(limit) + })) + + reachedLimitImpl = { [weak controller] limit in + guard let controller else { + return + } + HapticFeedback().error() + controller.present(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.Premium_Gift_ContactSelection_MaximumReached("\(limit)").string, timeout: nil, customUndoText: nil), elevatedLayout: true, position: .bottom, animateInAsReplacement: false, action: { _ in return false }), in: .current) + } + + let _ = combineLatest(queue: Queue.mainQueue(), controller.result, options.get()) + .startStandalone(next: { [weak controller] result, options in + guard let controller else { + return + } + var peerIds: [PeerId] = [] + if case let .result(peerIdsValue, _) = result { + peerIds = peerIdsValue.compactMap({ peerId in + if case let .peer(peerId) = peerId { + return peerId + } else { + return nil + } + }) + } + + let mappedOptions = options.filter { $0.users == 1 }.map { CachedPremiumGiftOption(months: $0.months, currency: $0.currency, amount: $0.amount, botUrl: "", storeProductId: $0.storeProductId) } + var pushImpl: ((ViewController) -> Void)? + var filterImpl: (() -> Void)? + let giftController = PremiumGiftScreen(context: context, peerIds: peerIds, options: mappedOptions, source: .settings, pushController: { c in + pushImpl?(c) + }, completion: { + filterImpl?() + }) + pushImpl = { [weak giftController] c in + giftController?.push(c) + } + filterImpl = { [weak giftController] in + if let navigationController = giftController?.navigationController as? NavigationController { + var controllers = navigationController.viewControllers + controllers = controllers.filter { !($0 is ContactMultiselectionController) } + navigationController.setViewControllers(controllers, animated: true) + } + } + controller.push(giftController) + }) + + return controller + } + public func makeStickerPackScreen(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)?, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], loadedStickerPacks: [LoadedStickerPack], parentNavigationController: NavigationController?, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?) -> ViewController { return StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: mainStickerPack, stickerPacks: stickerPacks, loadedStickerPacks: loadedStickerPacks, parentNavigationController: parentNavigationController, sendSticker: sendSticker) }