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.CancelEmailVerificationStop" = "Stop";
"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
}
private var validLayout: ContainerViewLayout?
private let presentationData: PresentationData
var loginWithPassword: ((String) -> Void)?
@ -33,12 +35,7 @@ final class AuthorizationSequencePasswordEntryController: ViewController {
var inProgress: Bool = false {
didSet {
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))
}
self.updateNavigationItems()
self.controllerNode.inProgress = self.inProgress
}
}
@ -60,8 +57,6 @@ final class AuthorizationSequencePasswordEntryController: ViewController {
self.navigationBar?.backPressed = {
back()
}
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Next, style: .done, target: self, action: #selector(self.nextPressed))
}
required init(coder aDecoder: NSCoder) {
@ -97,6 +92,19 @@ final class AuthorizationSequencePasswordEntryController: ViewController {
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) {
if self.hint != hint || self.suggestReset != suggestReset {
self.hint = hint
@ -109,6 +117,7 @@ final class AuthorizationSequencePasswordEntryController: ViewController {
func passwordIsInvalid() {
if self.isNodeLoaded {
self.hapticFeedback.error()
self.controllerNode.passwordIsInvalid()
}
}
@ -116,6 +125,13 @@ final class AuthorizationSequencePasswordEntryController: ViewController {
override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
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)
}

View File

@ -2,17 +2,23 @@ import Foundation
import UIKit
import AsyncDisplayKit
import Display
import SwiftSignalKit
import TelegramPresentationData
import AuthorizationUtils
import AnimatedStickerNode
import TelegramAnimatedStickerNode
import SolidRoundedButtonNode
final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UITextFieldDelegate {
private let strings: PresentationStrings
private let theme: PresentationTheme
private let animationNode: AnimatedStickerNode
private let titleNode: ASTextNode
private let noticeNode: ASTextNode
private let forgotNode: HighlightableButtonNode
private let resetNode: HighlightableButtonNode
private let proceedNode: SolidRoundedButtonNode
private let codeField: TextFieldNode
private let codeSeparatorNode: ASDisplayNode
@ -35,13 +41,26 @@ final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UIT
var inProgress: Bool = false {
didSet {
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) {
self.strings = strings
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.isUserInteractionEnabled = false
self.titleNode.displaysAsynchronously = false
@ -75,6 +94,10 @@ final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UIT
self.codeField.textField.disableAutomaticKeyboardHandling = [.forward, .backward]
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()
self.setViewBlock({
@ -84,6 +107,7 @@ final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UIT
self.backgroundColor = self.theme.list.plainBackgroundColor
self.codeField.textField.delegate = self
self.codeField.textField.addTarget(self, action: #selector(self.textDidChange), for: .editingChanged)
self.addSubnode(self.codeSeparatorNode)
self.addSubnode(self.codeField)
@ -91,9 +115,26 @@ final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UIT
self.addSubnode(self.forgotNode)
self.addSubnode(self.resetNode)
self.addSubnode(self.noticeNode)
self.addSubnode(self.animationNode)
self.addSubnode(self.proceedNode)
self.forgotNode.addTarget(self, action: #selector(self.forgotPressed), 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) {
@ -109,26 +150,33 @@ final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UIT
self.layoutArguments = (layout, navigationBarHeight)
var insets = layout.insets(options: [])
insets.top = navigationBarHeight
if let inputHeight = layout.inputHeight {
insets.bottom += max(inputHeight, layout.standardInputHeight)
insets.top = layout.statusBarHeight ?? 20.0
if let inputHeight = layout.inputHeight, !inputHeight.isZero {
insets.bottom = max(inputHeight, insets.bottom)
}
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)
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 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 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] = []
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.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.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.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 - 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)))
@ -139,7 +187,22 @@ final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UIT
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() {
@ -154,6 +217,10 @@ final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UIT
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 {
if self.clearOnce {
self.clearOnce = false

View File

@ -712,7 +712,7 @@ private final class DemoSheetContent: CombinedComponent {
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
var availableItems: [PremiumPerk: DemoPagerComponent.Item] = [:]
@ -794,15 +794,14 @@ private final class DemoSheetContent: CombinedComponent {
id: PremiumDemoScreen.Subject.uniqueReactions,
component: AnyComponent(
PageComponent(
content: AnyComponent(
ReactionsCarouselComponent(
content: AnyComponent(PhoneDemoComponent(
context: component.context,
theme: environment.theme,
reactions: reactions
)
),
title: isStandalone ? strings.Premium_ReactionsStandalone : strings.Premium_Reactions,
text: isStandalone ? strings.Premium_ReactionsStandaloneInfo : strings.Premium_ReactionsInfo,
position: .top,
videoFile: configuration.videos["infinite_reactions"],
decoration: .badgeStars
)),
title: strings.Premium_InfiniteReactions,
text: strings.Premium_InfiniteReactionsInfo,
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(
AnyComponentWithIdentity(
id: PremiumDemoScreen.Subject.advancedChatManagement,
@ -1171,6 +1188,7 @@ public class PremiumDemoScreen: ViewControllerComponentContainer {
case animatedUserpics
case appIcons
case animatedEmoji
case emojiStatus
}
public enum Source: Equatable {

View File

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

View File

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

View File

@ -1107,7 +1107,7 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting
}
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
return false
}))

View File

@ -555,7 +555,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
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
} else if emojiString != nil {
emojiFile = nil