Merge commit '7621e2f8dec938cf48181c8b10afc9b01f444e68' into beta

This commit is contained in:
Ilya Laktyushin
2025-12-06 02:17:48 +04:00
commit 8344b97e03
28070 changed files with 7995182 additions and 0 deletions
+23
View File
@@ -0,0 +1,23 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "AuthorizationUtils",
module_name = "AuthorizationUtils",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
"//submodules/TelegramCore:TelegramCore",
"//submodules/Display:Display",
"//submodules/TextFormat:TextFormat",
"//submodules/Markdown:Markdown",
"//submodules/TelegramPresentationData:TelegramPresentationData",
],
visibility = [
"//visibility:public",
],
)
@@ -0,0 +1,170 @@
import Foundation
import UIKit
import AsyncDisplayKit
import Display
public struct AuthorizationLayoutItemSpacing {
public var weight: CGFloat
public var maxValue: CGFloat
public init(weight: CGFloat, maxValue: CGFloat) {
self.weight = weight
self.maxValue = maxValue
}
}
public struct AuthorizationLayoutItem {
public var node: ASDisplayNode?
public var view: UIView?
public var size: CGSize
public var spacingBefore: AuthorizationLayoutItemSpacing
public var spacingAfter: AuthorizationLayoutItemSpacing
public init(node: ASDisplayNode, size: CGSize, spacingBefore: AuthorizationLayoutItemSpacing, spacingAfter: AuthorizationLayoutItemSpacing) {
self.node = node
self.size = size
self.spacingBefore = spacingBefore
self.spacingAfter = spacingAfter
}
public init(view: UIView, size: CGSize, spacingBefore: AuthorizationLayoutItemSpacing, spacingAfter: AuthorizationLayoutItemSpacing) {
self.view = view
self.size = size
self.spacingBefore = spacingBefore
self.spacingAfter = spacingAfter
}
}
public final class SolvedAuthorizationLayoutItem {
public let item: AuthorizationLayoutItem
public var spacingBefore: CGFloat?
public var spacingAfter: CGFloat?
public init(item: AuthorizationLayoutItem) {
self.item = item
}
}
public func layoutAuthorizationItems(bounds: CGRect, items: [AuthorizationLayoutItem], transition: ContainedViewLayoutTransition, failIfDoesNotFit: Bool) -> Bool {
var fixedHeight: CGFloat = 0.0
var totalSpacerWeight: CGFloat = 0.0
for item in items {
fixedHeight += item.size.height
totalSpacerWeight += item.spacingBefore.weight
totalSpacerWeight += item.spacingAfter.weight
}
let solvedItems = items.map(SolvedAuthorizationLayoutItem.init)
if failIfDoesNotFit && bounds.size.height - fixedHeight < 0.0 {
return false
}
var remainingSpacersHeight = max(0.0, bounds.size.height - fixedHeight)
for i in 0 ..< 3 {
if i == 0 || i == 2 {
while true {
var hasUnsolvedItems = false
for item in solvedItems {
if item.spacingBefore == nil {
hasUnsolvedItems = true
if item.item.spacingBefore.maxValue.isZero {
item.spacingBefore = 0.0
} else {
item.spacingBefore = floor(item.item.spacingBefore.weight * remainingSpacersHeight / totalSpacerWeight)
}
}
if item.spacingAfter == nil {
hasUnsolvedItems = true
if item.item.spacingAfter.maxValue.isZero {
item.spacingAfter = 0.0
} else {
item.spacingAfter = floor(item.item.spacingAfter.weight * remainingSpacersHeight / totalSpacerWeight)
}
}
}
if !hasUnsolvedItems {
break
}
}
} else {
var updated = false
for item in solvedItems {
if !item.item.spacingBefore.maxValue.isZero {
if item.spacingBefore! > item.item.spacingBefore.maxValue {
updated = true
}
}
if !item.item.spacingAfter.maxValue.isZero {
if item.spacingAfter! > item.item.spacingAfter.maxValue {
updated = true
}
}
}
if updated {
for item in solvedItems {
if !item.item.spacingBefore.maxValue.isZero {
if item.spacingBefore! > item.item.spacingBefore.maxValue {
item.spacingBefore = item.item.spacingBefore.maxValue
} else {
item.spacingBefore = nil
}
}
if !item.item.spacingAfter.maxValue.isZero {
if item.spacingAfter! > item.item.spacingAfter.maxValue {
item.spacingAfter = item.item.spacingAfter.maxValue
} else {
item.spacingAfter = nil
}
}
}
fixedHeight = 0.0
totalSpacerWeight = 0.0
for item in solvedItems {
fixedHeight += item.item.size.height
if let spacingBefore = item.spacingBefore {
fixedHeight += spacingBefore
} else if !item.item.spacingBefore.maxValue.isZero {
totalSpacerWeight += item.item.spacingBefore.weight
}
if let spacingAfter = item.spacingAfter {
fixedHeight += spacingAfter
} else if !item.item.spacingAfter.maxValue.isZero {
totalSpacerWeight += item.item.spacingAfter.weight
}
}
remainingSpacersHeight = max(0.0, bounds.size.height - fixedHeight)
}
}
}
var totalHeight: CGFloat = 0.0
for item in solvedItems {
totalHeight += item.spacingBefore! + item.spacingAfter! + item.item.size.height
}
var verticalOrigin: CGFloat = bounds.minY + floor((bounds.size.height - totalHeight) / 2.0)
for i in 0 ..< solvedItems.count {
let item = solvedItems[i]
verticalOrigin += item.spacingBefore!
let itemFrame = CGRect(origin: CGPoint(x: floor((bounds.size.width - item.item.size.width) / 2.0), y: verticalOrigin), size: item.item.size)
if let view = item.item.view {
transition.updateFrame(view: view, frame: itemFrame)
} else if let node = item.item.node {
transition.updateFrame(node: node, frame: itemFrame)
}
verticalOrigin += item.item.size.height
verticalOrigin += item.spacingAfter!
}
return true
}
@@ -0,0 +1,134 @@
import Foundation
import UIKit
import TelegramCore
import Display
import TelegramPresentationData
import TextFormat
import Markdown
public func authorizationCurrentOptionText(_ type: SentAuthorizationCodeType, phoneNumber: String, email: String?, strings: PresentationStrings, primaryColor: UIColor, accentColor: UIColor) -> NSAttributedString {
let fontSize: CGFloat = 17.0
let body = MarkdownAttributeSet(font: Font.regular(fontSize), textColor: primaryColor)
let bold = MarkdownAttributeSet(font: Font.semibold(fontSize), textColor: primaryColor)
let attributes = MarkdownAttributes(body: body, bold: bold, link: body, linkAttribute: { _ in nil })
switch type {
case .sms:
return parseMarkdownIntoAttributedString(strings.Login_EnterCodeSMSText(phoneNumber).string, attributes: attributes, textAlignment: .center)
case .otherSession:
return parseMarkdownIntoAttributedString(strings.Login_EnterCodeTelegramText(phoneNumber).string, attributes: attributes, textAlignment: .center)
case .missedCall:
let body = MarkdownAttributeSet(font: Font.regular(fontSize), textColor: primaryColor)
let bold = MarkdownAttributeSet(font: Font.semibold(fontSize), textColor: primaryColor)
return parseMarkdownIntoAttributedString(strings.Login_ShortCallTitle, attributes: MarkdownAttributes(body: body, bold: bold, link: body, linkAttribute: { _ in nil }), textAlignment: .center)
case .call:
return parseMarkdownIntoAttributedString(strings.Login_CodeSentCallText(phoneNumber).string, attributes: attributes, textAlignment: .center)
case .flashCall:
return parseMarkdownIntoAttributedString(strings.Login_CodeSentCallText(phoneNumber).string, attributes: attributes, textAlignment: .center)
case .emailSetupRequired:
return NSAttributedString(string: "", font: Font.regular(fontSize), textColor: primaryColor, paragraphAlignment: .center)
case let .email(emailPattern, _, _, _, _, _):
let mutableString = NSAttributedString(string: strings.Login_EnterCodeEmailText(email ?? emailPattern).string, font: Font.regular(fontSize), textColor: primaryColor, paragraphAlignment: .center).mutableCopy() as! NSMutableAttributedString
if let regex = try? NSRegularExpression(pattern: "\\*", options: []) {
let matches = regex.matches(in: mutableString.string, options: [], range: NSMakeRange(0, mutableString.length))
if let first = matches.first {
mutableString.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.Spoiler), value: true, range: NSRange(location: first.range.location, length: matches.count))
}
}
return mutableString
case .fragment:
return parseMarkdownIntoAttributedString(strings.Login_EnterCodeFragmentText(phoneNumber).string, attributes: attributes, textAlignment: .center)
case .firebase:
return parseMarkdownIntoAttributedString(strings.Login_EnterCodeSMSText(phoneNumber).string, attributes: attributes, textAlignment: .center)
case let .word(startsWith):
if let startsWith {
return parseMarkdownIntoAttributedString(strings.Login_EnterWordBeginningText(startsWith, phoneNumber).string, attributes: attributes, textAlignment: .center)
} else {
return parseMarkdownIntoAttributedString(strings.Login_EnterWordText(phoneNumber).string, attributes: attributes, textAlignment: .center)
}
case let .phrase(startsWith):
if let startsWith {
return parseMarkdownIntoAttributedString(strings.Login_EnterPhraseBeginningText(startsWith, phoneNumber).string, attributes: attributes, textAlignment: .center)
} else {
return parseMarkdownIntoAttributedString(strings.Login_EnterPhraseText(phoneNumber).string, attributes: attributes, textAlignment: .center)
}
}
}
public func authorizationNextOptionText(currentType: SentAuthorizationCodeType, nextType: AuthorizationCodeNextType?, previousCodeType: SentAuthorizationCodeType? = nil, timeout: Int32?, strings: PresentationStrings, primaryColor: UIColor, accentColor: UIColor) -> (NSAttributedString, Bool) {
let font = Font.regular(16.0)
if let previousCodeType {
switch previousCodeType {
case .word:
return (NSAttributedString(string: strings.Login_ReturnToWord, font: font, textColor: accentColor, paragraphAlignment: .center), true)
case .phrase:
return (NSAttributedString(string: strings.Login_ReturnToPhrase, font: font, textColor: accentColor, paragraphAlignment: .center), true)
default:
return (NSAttributedString(string: strings.Login_ReturnToCode, font: font, textColor: accentColor, paragraphAlignment: .center), true)
}
}
if let nextType = nextType, let timeout = timeout, timeout > 0 {
let minutes = timeout / 60
let seconds = timeout % 60
switch nextType {
case .sms:
if timeout <= 0 {
return (NSAttributedString(string: strings.Login_CodeSentSms, font: font, textColor: primaryColor, paragraphAlignment: .center), false)
} else {
let timeString = NSString(format: "%d:%.02d", Int(minutes), Int(seconds))
return (NSAttributedString(string: strings.Login_WillSendSms(timeString as String).string, font: font, textColor: primaryColor, paragraphAlignment: .center), false)
}
case .call:
if timeout <= 0 {
return (NSAttributedString(string: strings.Login_CodeSentCall, font: font, textColor: primaryColor, paragraphAlignment: .center), false)
} else {
return (NSAttributedString(string: String(format: strings.ChangePhoneNumberCode_CallTimer(String(format: "%d:%.2d", minutes, seconds)).string, minutes, seconds), font: font, textColor: primaryColor, paragraphAlignment: .center), false)
}
case .flashCall, .missedCall:
if timeout <= 0 {
return (NSAttributedString(string: strings.ChangePhoneNumberCode_Called, font: font, textColor: primaryColor, paragraphAlignment: .center), false)
} else {
return (NSAttributedString(string: String(format: strings.ChangePhoneNumberCode_CallTimer(String(format: "%d:%.2d", minutes, seconds)).string, minutes, seconds), font: font, textColor: primaryColor, paragraphAlignment: .center), false)
}
case .fragment:
if timeout <= 0 {
return (NSAttributedString(string: strings.Login_CodeSentSms, font: font, textColor: primaryColor, paragraphAlignment: .center), false)
} else {
let timeString = NSString(format: "%d:%.02d", Int(minutes), Int(seconds))
return (NSAttributedString(string: strings.Login_WillSendSms(timeString as String).string, font: font, textColor: primaryColor, paragraphAlignment: .center), false)
}
}
} else {
switch currentType {
case .otherSession:
switch nextType {
case .sms:
return (NSAttributedString(string: strings.Login_SendCodeViaSms, font: font, textColor: accentColor, paragraphAlignment: .center), true)
case .call:
return (NSAttributedString(string: strings.Login_SendCodeViaCall, font: font, textColor: accentColor, paragraphAlignment: .center), true)
case .flashCall, .missedCall:
return (NSAttributedString(string: strings.Login_SendCodeViaFlashCall, font: font, textColor: accentColor, paragraphAlignment: .center), true)
case .fragment:
return (NSAttributedString(string: strings.Login_GetCodeViaFragment, font: font, textColor: accentColor, paragraphAlignment: .center), true)
case .none:
return (NSAttributedString(string: strings.Login_HaveNotReceivedCodeInternal, font: font, textColor: accentColor, paragraphAlignment: .center), true)
}
default:
switch nextType {
case .sms:
return (NSAttributedString(string: strings.Login_SendCodeViaSms, font: font, textColor: accentColor, paragraphAlignment: .center), true)
case .call:
return (NSAttributedString(string: strings.Login_SendCodeViaCall, font: font, textColor: accentColor, paragraphAlignment: .center), true)
case .flashCall, .missedCall:
return (NSAttributedString(string: strings.Login_SendCodeViaFlashCall, font: font, textColor: accentColor, paragraphAlignment: .center), true)
case .fragment:
return (NSAttributedString(string: strings.Login_GetCodeViaFragment, font: font, textColor: accentColor, paragraphAlignment: .center), true)
case .none:
return (NSAttributedString(string: strings.Login_HaveNotReceivedCodeInternal, font: font, textColor: accentColor, paragraphAlignment: .center), true)
}
}
}
}