Various fixes

This commit is contained in:
Ilya Laktyushin 2022-09-06 15:51:56 +02:00
parent 40908ce9b4
commit 4316b417e5
10 changed files with 155 additions and 33 deletions

Binary file not shown.

View File

@ -8040,3 +8040,9 @@ Sorry for the inconvenience.";
"Login.CancelEmailVerification" = "Do you want to stop the email verification process?"; "Login.CancelEmailVerification" = "Do you want to stop the email verification process?";
"Login.CancelEmailVerificationStop" = "Stop"; "Login.CancelEmailVerificationStop" = "Stop";
"Login.CancelEmailVerificationContinue" = "Continue"; "Login.CancelEmailVerificationContinue" = "Continue";
"Premium.InfiniteReactions" = "Infinite Reactions";
"Premium.InfiniteReactionsInfo" = "React with thousands of emoji — with multiple reactions per message.";
"Premium.EmojiStatus" = "Emoji Status";
"Premium.EmojiStatusInfo" = "Add any of thousands emojis next to your name to display current activity.";

View File

@ -10,6 +10,8 @@ final class AuthorizationSequencePasswordEntryController: ViewController {
return self.displayNode as! AuthorizationSequencePasswordEntryControllerNode return self.displayNode as! AuthorizationSequencePasswordEntryControllerNode
} }
private var validLayout: ContainerViewLayout?
private let presentationData: PresentationData private let presentationData: PresentationData
var loginWithPassword: ((String) -> Void)? var loginWithPassword: ((String) -> Void)?
@ -33,12 +35,7 @@ final class AuthorizationSequencePasswordEntryController: ViewController {
var inProgress: Bool = false { var inProgress: Bool = false {
didSet { didSet {
if self.inProgress { self.updateNavigationItems()
let item = UIBarButtonItem(customDisplayNode: ProgressNavigationButtonNode(color: self.presentationData.theme.rootController.navigationBar.accentTextColor))
self.navigationItem.rightBarButtonItem = item
} else {
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Next, style: .done, target: self, action: #selector(self.nextPressed))
}
self.controllerNode.inProgress = self.inProgress self.controllerNode.inProgress = self.inProgress
} }
} }
@ -60,8 +57,6 @@ final class AuthorizationSequencePasswordEntryController: ViewController {
self.navigationBar?.backPressed = { self.navigationBar?.backPressed = {
back() back()
} }
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Next, style: .done, target: self, action: #selector(self.nextPressed))
} }
required init(coder aDecoder: NSCoder) { required init(coder aDecoder: NSCoder) {
@ -97,6 +92,19 @@ final class AuthorizationSequencePasswordEntryController: ViewController {
self.controllerNode.activateInput() self.controllerNode.activateInput()
} }
func updateNavigationItems() {
guard let layout = self.validLayout, layout.size.width < 360.0 else {
return
}
if self.inProgress {
let item = UIBarButtonItem(customDisplayNode: ProgressNavigationButtonNode(color: self.presentationData.theme.rootController.navigationBar.accentTextColor))
self.navigationItem.rightBarButtonItem = item
} else {
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Next, style: .done, target: self, action: #selector(self.nextPressed))
}
}
func updateData(hint: String, suggestReset: Bool) { func updateData(hint: String, suggestReset: Bool) {
if self.hint != hint || self.suggestReset != suggestReset { if self.hint != hint || self.suggestReset != suggestReset {
self.hint = hint self.hint = hint
@ -109,6 +117,7 @@ final class AuthorizationSequencePasswordEntryController: ViewController {
func passwordIsInvalid() { func passwordIsInvalid() {
if self.isNodeLoaded { if self.isNodeLoaded {
self.hapticFeedback.error()
self.controllerNode.passwordIsInvalid() self.controllerNode.passwordIsInvalid()
} }
} }
@ -116,6 +125,13 @@ final class AuthorizationSequencePasswordEntryController: ViewController {
override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
super.containerLayoutUpdated(layout, transition: transition) super.containerLayoutUpdated(layout, transition: transition)
let hadLayout = self.validLayout != nil
self.validLayout = layout
if !hadLayout {
self.updateNavigationItems()
}
self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationLayout(layout: layout).navigationFrame.maxY, transition: transition) self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationLayout(layout: layout).navigationFrame.maxY, transition: transition)
} }

View File

@ -2,17 +2,23 @@ import Foundation
import UIKit import UIKit
import AsyncDisplayKit import AsyncDisplayKit
import Display import Display
import SwiftSignalKit
import TelegramPresentationData import TelegramPresentationData
import AuthorizationUtils import AuthorizationUtils
import AnimatedStickerNode
import TelegramAnimatedStickerNode
import SolidRoundedButtonNode
final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UITextFieldDelegate { final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UITextFieldDelegate {
private let strings: PresentationStrings private let strings: PresentationStrings
private let theme: PresentationTheme private let theme: PresentationTheme
private let animationNode: AnimatedStickerNode
private let titleNode: ASTextNode private let titleNode: ASTextNode
private let noticeNode: ASTextNode private let noticeNode: ASTextNode
private let forgotNode: HighlightableButtonNode private let forgotNode: HighlightableButtonNode
private let resetNode: HighlightableButtonNode private let resetNode: HighlightableButtonNode
private let proceedNode: SolidRoundedButtonNode
private let codeField: TextFieldNode private let codeField: TextFieldNode
private let codeSeparatorNode: ASDisplayNode private let codeSeparatorNode: ASDisplayNode
@ -35,13 +41,26 @@ final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UIT
var inProgress: Bool = false { var inProgress: Bool = false {
didSet { didSet {
self.codeField.alpha = self.inProgress ? 0.6 : 1.0 self.codeField.alpha = self.inProgress ? 0.6 : 1.0
if self.inProgress != oldValue {
if self.inProgress {
self.proceedNode.transitionToProgress()
} else {
self.proceedNode.transitionFromProgress()
}
}
} }
} }
private var timer: SwiftSignalKit.Timer?
init(strings: PresentationStrings, theme: PresentationTheme) { init(strings: PresentationStrings, theme: PresentationTheme) {
self.strings = strings self.strings = strings
self.theme = theme self.theme = theme
self.animationNode = DefaultAnimatedStickerNodeImpl()
self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "IntroPassword"), width: 256, height: 256, playbackMode: .still(.start), mode: .direct(cachePathPrefix: nil))
self.titleNode = ASTextNode() self.titleNode = ASTextNode()
self.titleNode.isUserInteractionEnabled = false self.titleNode.isUserInteractionEnabled = false
self.titleNode.displaysAsynchronously = false self.titleNode.displaysAsynchronously = false
@ -75,6 +94,10 @@ final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UIT
self.codeField.textField.disableAutomaticKeyboardHandling = [.forward, .backward] self.codeField.textField.disableAutomaticKeyboardHandling = [.forward, .backward]
self.codeField.textField.tintColor = self.theme.list.itemAccentColor self.codeField.textField.tintColor = self.theme.list.itemAccentColor
self.proceedNode = SolidRoundedButtonNode(title: self.strings.Login_Continue, theme: SolidRoundedButtonTheme(theme: self.theme), height: 50.0, cornerRadius: 11.0, gloss: false)
self.proceedNode.progressType = .embedded
self.proceedNode.isEnabled = false
super.init() super.init()
self.setViewBlock({ self.setViewBlock({
@ -84,6 +107,7 @@ final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UIT
self.backgroundColor = self.theme.list.plainBackgroundColor self.backgroundColor = self.theme.list.plainBackgroundColor
self.codeField.textField.delegate = self self.codeField.textField.delegate = self
self.codeField.textField.addTarget(self, action: #selector(self.textDidChange), for: .editingChanged)
self.addSubnode(self.codeSeparatorNode) self.addSubnode(self.codeSeparatorNode)
self.addSubnode(self.codeField) self.addSubnode(self.codeField)
@ -91,9 +115,26 @@ final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UIT
self.addSubnode(self.forgotNode) self.addSubnode(self.forgotNode)
self.addSubnode(self.resetNode) self.addSubnode(self.resetNode)
self.addSubnode(self.noticeNode) self.addSubnode(self.noticeNode)
self.addSubnode(self.animationNode)
self.addSubnode(self.proceedNode)
self.forgotNode.addTarget(self, action: #selector(self.forgotPressed), forControlEvents: .touchUpInside) self.forgotNode.addTarget(self, action: #selector(self.forgotPressed), forControlEvents: .touchUpInside)
self.resetNode.addTarget(self, action: #selector(self.resetPressed), forControlEvents: .touchUpInside) self.resetNode.addTarget(self, action: #selector(self.resetPressed), forControlEvents: .touchUpInside)
self.proceedNode.pressed = { [weak self] in
if let strongSelf = self {
strongSelf.loginWithCode?(strongSelf.currentPassword)
}
}
self.timer = SwiftSignalKit.Timer(timeout: 7.5, repeat: true, completion: { [weak self] in
self?.animationNode.playOnce()
}, queue: Queue.mainQueue())
self.timer?.start()
}
deinit {
self.timer?.invalidate()
} }
func updateData(hint: String, didForgotWithNoRecovery: Bool, suggestReset: Bool) { func updateData(hint: String, didForgotWithNoRecovery: Bool, suggestReset: Bool) {
@ -109,26 +150,33 @@ final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UIT
self.layoutArguments = (layout, navigationBarHeight) self.layoutArguments = (layout, navigationBarHeight)
var insets = layout.insets(options: []) var insets = layout.insets(options: [])
insets.top = navigationBarHeight insets.top = layout.statusBarHeight ?? 20.0
if let inputHeight = layout.inputHeight, !inputHeight.isZero {
if let inputHeight = layout.inputHeight { insets.bottom = max(inputHeight, insets.bottom)
insets.bottom += max(inputHeight, layout.standardInputHeight)
} }
let titleInset: CGFloat = layout.size.width > 320.0 ? 18.0 : 0.0
let additionalBottomInset: CGFloat = layout.size.width > 320.0 ? 110.0 : 20.0
self.titleNode.attributedText = NSAttributedString(string: self.strings.LoginPassword_Title, font: Font.semibold(28.0), textColor: self.theme.list.itemPrimaryTextColor) self.titleNode.attributedText = NSAttributedString(string: self.strings.LoginPassword_Title, font: Font.semibold(28.0), textColor: self.theme.list.itemPrimaryTextColor)
let inset: CGFloat = 24.0
let animationSize = CGSize(width: 100.0, height: 100.0)
let titleSize = self.titleNode.measure(CGSize(width: layout.size.width, height: CGFloat.greatestFiniteMagnitude)) let titleSize = self.titleNode.measure(CGSize(width: layout.size.width, height: CGFloat.greatestFiniteMagnitude))
let noticeSize = self.noticeNode.measure(CGSize(width: layout.size.width - 28.0, height: CGFloat.greatestFiniteMagnitude)) let noticeSize = self.noticeNode.measure(CGSize(width: layout.size.width - 28.0, height: CGFloat.greatestFiniteMagnitude))
let forgotSize = self.forgotNode.measure(CGSize(width: layout.size.width, height: CGFloat.greatestFiniteMagnitude)) let forgotSize = self.forgotNode.measure(CGSize(width: layout.size.width, height: CGFloat.greatestFiniteMagnitude))
let resetSize = self.resetNode.measure(CGSize(width: layout.size.width, height: CGFloat.greatestFiniteMagnitude)) let resetSize = self.resetNode.measure(CGSize(width: layout.size.width, height: CGFloat.greatestFiniteMagnitude))
let proceedHeight = self.proceedNode.updateLayout(width: layout.size.width - inset * 2.0, transition: transition)
let proceedSize = CGSize(width: layout.size.width - inset * 2.0, height: proceedHeight)
var items: [AuthorizationLayoutItem] = [] var items: [AuthorizationLayoutItem] = []
items.append(AuthorizationLayoutItem(node: self.titleNode, size: titleSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) items.append(AuthorizationLayoutItem(node: self.titleNode, size: titleSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: titleInset, maxValue: titleInset), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
items.append(AuthorizationLayoutItem(node: self.noticeNode, size: noticeSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 18.0, maxValue: 18.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) items.append(AuthorizationLayoutItem(node: self.noticeNode, size: noticeSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 18.0, maxValue: 18.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
items.append(AuthorizationLayoutItem(node: self.codeField, size: CGSize(width: layout.size.width - 88.0, height: 44.0), spacingBefore: AuthorizationLayoutItemSpacing(weight: 32.0, maxValue: 60.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) items.append(AuthorizationLayoutItem(node: self.codeField, size: CGSize(width: layout.size.width - 80.0, height: 44.0), spacingBefore: AuthorizationLayoutItemSpacing(weight: 32.0, maxValue: 60.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
items.append(AuthorizationLayoutItem(node: self.codeSeparatorNode, size: CGSize(width: layout.size.width - 88.0, height: UIScreenPixel), spacingBefore: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) items.append(AuthorizationLayoutItem(node: self.codeSeparatorNode, size: CGSize(width: layout.size.width - 48.0, height: UIScreenPixel), spacingBefore: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
items.append(AuthorizationLayoutItem(node: self.forgotNode, size: forgotSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 48.0, maxValue: 100.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) items.append(AuthorizationLayoutItem(node: self.forgotNode, size: forgotSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 48.0, maxValue: 100.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
@ -139,7 +187,22 @@ final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UIT
self.resetNode.isHidden = true self.resetNode.isHidden = true
} }
let _ = layoutAuthorizationItems(bounds: CGRect(origin: CGPoint(x: 0.0, y: insets.top), size: CGSize(width: layout.size.width, height: layout.size.height - insets.top - insets.bottom - 20.0)), items: items, transition: transition, failIfDoesNotFit: false) if layout.size.width > 320.0 {
items.insert(AuthorizationLayoutItem(node: self.animationNode, size: animationSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 10.0, maxValue: 10.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)), at: 0)
self.proceedNode.isHidden = false
self.animationNode.isHidden = false
self.animationNode.visibility = true
} else {
insets.top = navigationBarHeight
self.proceedNode.isHidden = true
self.animationNode.isHidden = true
}
transition.updateFrame(node: self.proceedNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - proceedSize.width) / 2.0), y: layout.size.height - insets.bottom - proceedSize.height - inset), size: proceedSize))
self.animationNode.updateLayout(size: animationSize)
let _ = layoutAuthorizationItems(bounds: CGRect(origin: CGPoint(x: 0.0, y: insets.top), size: CGSize(width: layout.size.width, height: layout.size.height - insets.top - insets.bottom - additionalBottomInset)), items: items, transition: transition, failIfDoesNotFit: false)
} }
func activateInput() { func activateInput() {
@ -154,6 +217,10 @@ final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UIT
self.clearOnce = true self.clearOnce = true
} }
@objc func textDidChange() {
self.proceedNode.isEnabled = !(self.codeField.textField.text ?? "").isEmpty
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if self.clearOnce { if self.clearOnce {
self.clearOnce = false self.clearOnce = false

View File

@ -712,7 +712,7 @@ private final class DemoSheetContent: CombinedComponent {
isStandalone = true isStandalone = true
} }
if let reactions = state.reactions, let stickers = state.stickers, let appIcons = state.appIcons, let configuration = state.promoConfiguration { if let stickers = state.stickers, let appIcons = state.appIcons, let configuration = state.promoConfiguration {
let textColor = theme.actionSheet.primaryTextColor let textColor = theme.actionSheet.primaryTextColor
var availableItems: [PremiumPerk: DemoPagerComponent.Item] = [:] var availableItems: [PremiumPerk: DemoPagerComponent.Item] = [:]
@ -794,15 +794,14 @@ private final class DemoSheetContent: CombinedComponent {
id: PremiumDemoScreen.Subject.uniqueReactions, id: PremiumDemoScreen.Subject.uniqueReactions,
component: AnyComponent( component: AnyComponent(
PageComponent( PageComponent(
content: AnyComponent( content: AnyComponent(PhoneDemoComponent(
ReactionsCarouselComponent( context: component.context,
context: component.context, position: .top,
theme: environment.theme, videoFile: configuration.videos["infinite_reactions"],
reactions: reactions decoration: .badgeStars
) )),
), title: strings.Premium_InfiniteReactions,
title: isStandalone ? strings.Premium_ReactionsStandalone : strings.Premium_Reactions, text: strings.Premium_InfiniteReactionsInfo,
text: isStandalone ? strings.Premium_ReactionsStandaloneInfo : strings.Premium_ReactionsInfo,
textColor: textColor textColor: textColor
) )
) )
@ -826,6 +825,24 @@ private final class DemoSheetContent: CombinedComponent {
) )
) )
) )
availableItems[.emojiStatus] = DemoPagerComponent.Item(
AnyComponentWithIdentity(
id: PremiumDemoScreen.Subject.emojiStatus,
component: AnyComponent(
PageComponent(
content: AnyComponent(PhoneDemoComponent(
context: component.context,
position: .top,
videoFile: configuration.videos["emoji_status"],
decoration: .swirlStars
)),
title: strings.Premium_EmojiStatus,
text: strings.Premium_EmojiStatusInfo,
textColor: textColor
)
)
)
)
availableItems[.advancedChatManagement] = DemoPagerComponent.Item( availableItems[.advancedChatManagement] = DemoPagerComponent.Item(
AnyComponentWithIdentity( AnyComponentWithIdentity(
id: PremiumDemoScreen.Subject.advancedChatManagement, id: PremiumDemoScreen.Subject.advancedChatManagement,
@ -1171,6 +1188,7 @@ public class PremiumDemoScreen: ViewControllerComponentContainer {
case animatedUserpics case animatedUserpics
case appIcons case appIcons
case animatedEmoji case animatedEmoji
case emojiStatus
} }
public enum Source: Equatable { public enum Source: Equatable {

View File

@ -397,6 +397,8 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
demoSubject = .appIcons demoSubject = .appIcons
case .animatedEmoji: case .animatedEmoji:
demoSubject = .animatedEmoji demoSubject = .animatedEmoji
case .emojiStatus:
demoSubject = .emojiStatus
} }
let controller = PremiumDemoScreen( let controller = PremiumDemoScreen(

View File

@ -54,7 +54,7 @@ public enum PremiumSource: Equatable {
case .stickers: case .stickers:
return "premium_stickers" return "premium_stickers"
case .reactions: case .reactions:
return "unique_reactions" return "infinite_reactions"
case .ads: case .ads:
return "no_ads" return "no_ads"
case .upload: case .upload:
@ -110,6 +110,7 @@ enum PremiumPerk: CaseIterable {
case animatedUserpics case animatedUserpics
case appIcons case appIcons
case animatedEmoji case animatedEmoji
case emojiStatus
static var allCases: [PremiumPerk] { static var allCases: [PremiumPerk] {
return [ return [
@ -124,7 +125,8 @@ enum PremiumPerk: CaseIterable {
.profileBadge, .profileBadge,
.animatedUserpics, .animatedUserpics,
.appIcons, .appIcons,
.animatedEmoji .animatedEmoji,
.emojiStatus
] ]
} }
@ -151,7 +153,7 @@ enum PremiumPerk: CaseIterable {
case .noAds: case .noAds:
return "no_ads" return "no_ads"
case .uniqueReactions: case .uniqueReactions:
return "unique_reactions" return "infinite_reactions"
case .premiumStickers: case .premiumStickers:
return "premium_stickers" return "premium_stickers"
case .advancedChatManagement: case .advancedChatManagement:
@ -164,6 +166,8 @@ enum PremiumPerk: CaseIterable {
return "app_icons" return "app_icons"
case .animatedEmoji: case .animatedEmoji:
return "animated_emoji" return "animated_emoji"
case .emojiStatus:
return "emoji_status"
} }
} }
@ -180,7 +184,7 @@ enum PremiumPerk: CaseIterable {
case .noAds: case .noAds:
return strings.Premium_NoAds return strings.Premium_NoAds
case .uniqueReactions: case .uniqueReactions:
return strings.Premium_Reactions return strings.Premium_InfiniteReactions
case .premiumStickers: case .premiumStickers:
return strings.Premium_Stickers return strings.Premium_Stickers
case .advancedChatManagement: case .advancedChatManagement:
@ -193,6 +197,8 @@ enum PremiumPerk: CaseIterable {
return strings.Premium_AppIcon return strings.Premium_AppIcon
case .animatedEmoji: case .animatedEmoji:
return strings.Premium_AnimatedEmoji return strings.Premium_AnimatedEmoji
case .emojiStatus:
return strings.Premium_EmojiStatus
} }
} }
@ -209,7 +215,7 @@ enum PremiumPerk: CaseIterable {
case .noAds: case .noAds:
return strings.Premium_NoAdsInfo return strings.Premium_NoAdsInfo
case .uniqueReactions: case .uniqueReactions:
return strings.Premium_ReactionsInfo return strings.Premium_InfiniteReactionsInfo
case .premiumStickers: case .premiumStickers:
return strings.Premium_StickersInfo return strings.Premium_StickersInfo
case .advancedChatManagement: case .advancedChatManagement:
@ -222,6 +228,8 @@ enum PremiumPerk: CaseIterable {
return strings.Premium_AppIconInfo return strings.Premium_AppIconInfo
case .animatedEmoji: case .animatedEmoji:
return strings.Premium_AnimatedEmojiInfo return strings.Premium_AnimatedEmojiInfo
case .emojiStatus:
return strings.Premium_EmojiStatusInfo
} }
} }
@ -251,6 +259,8 @@ enum PremiumPerk: CaseIterable {
return "Premium/Perk/AppIcon" return "Premium/Perk/AppIcon"
case .animatedEmoji: case .animatedEmoji:
return "Premium/Perk/Emoji" return "Premium/Perk/Emoji"
case .emojiStatus:
return "Premium/Perk/Emoji"
} }
} }
} }
@ -263,6 +273,7 @@ struct PremiumIntroConfiguration {
.fasterDownload, .fasterDownload,
.voiceToText, .voiceToText,
.noAds, .noAds,
.emojiStatus,
.uniqueReactions, .uniqueReactions,
.premiumStickers, .premiumStickers,
.animatedEmoji, .animatedEmoji,
@ -1445,6 +1456,8 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
demoSubject = .appIcons demoSubject = .appIcons
case .animatedEmoji: case .animatedEmoji:
demoSubject = .animatedEmoji demoSubject = .animatedEmoji
case .emojiStatus:
demoSubject = .emojiStatus
} }
let controller = PremiumDemoScreen( let controller = PremiumDemoScreen(

View File

@ -1107,7 +1107,7 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting
} }
navigationController.setViewControllers(controllers, animated: true) navigationController.setViewControllers(controllers, animated: true)
Queue.mainQueue().after(0.1, { Queue.mainQueue().after(0.5, {
navigationController.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .emoji(name: "IntroLetter", text: presentationData.strings.Login_EmailChanged), elevatedLayout: false, animateInAsReplacement: false, action: { _ in navigationController.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .emoji(name: "IntroLetter", text: presentationData.strings.Login_EmailChanged), elevatedLayout: false, animateInAsReplacement: false, action: { _ in
return false return false
})) }))

View File

@ -555,7 +555,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
emojiFile = item.associatedData.animatedEmojiStickers[emoji.strippedEmoji]?.first?.file emojiFile = item.associatedData.animatedEmojiStickers[emoji.strippedEmoji]?.first?.file
} }
if item.message.text.count == 1, item.message.associatedMedia.isEmpty && emojiFile != nil { if item.message.text.count == 1, (item.message.textEntitiesAttribute?.entities ?? []).isEmpty && emojiFile != nil {
emojiString = nil emojiString = nil
} else if emojiString != nil { } else if emojiString != nil {
emojiFile = nil emojiFile = nil