This commit is contained in:
isaac 2026-04-29 01:33:08 +04:00
commit 96de278d49
27 changed files with 214 additions and 126 deletions

View file

@ -16217,3 +16217,18 @@ Error: %8$@";
"Chat.AdminAction.ToastReactionsDeletedTextSingle" = "Reaction Deleted.";
"Chat.AdminAction.ToastReactionsDeletedTextMultiple" = "Reactions Deleted.";
"Chat.AdminAction.ToastMessagesAndReactionsDeletedText" = "Messages and reactions deleted.";
"Premium.SignUp.SignUpNewInfo" = "Get Telegram Premium for %@";
"Premium.SignUp.SignUpNewInfo.Days_1" = "%@ day";
"Premium.SignUp.SignUpNewInfo.Days_any" = "%@ days";
"Premium.SignUp.SignUpNewInfoNone" = "Get Telegram Premium";
"Login.Fee.Support.NewText.Days_1" = "%@ day";
"Login.Fee.Support.NewText.Days_any" = "%@ days";
"Login.Fee.Support.NewText" = "Sign up for a %@ Telegram Premium subscription to help cover the SMS costs.";
"Login.Fee.Support.NewTextNone" = "Sign up for Telegram Premium subscription to help cover the SMS costs.";
"Login.Fee.GetPremiumNone" = "Get Telegram Premium";
"Login.Fee.GetPremiumForDays" = "Get Telegram Premium for %@";
"Login.Fee.GetPremiumForDays.Days_1" = "%@ day";
"Login.Fee.GetPremiumForDays.Days_any" = "%@ days";

View file

@ -45,7 +45,7 @@ public enum PremiumIntroSource {
case todo
case copyProtection
case aiTools
case auth(String)
case auth(String, Int32)
case premiumGift(TelegramMediaFile)
}

View file

@ -810,8 +810,8 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
return controller
}
private func paymentController(number: String, phoneCodeHash: String, storeProduct: String, supportEmailAddress: String, supportEmailSubject: String) -> AuthorizationSequencePaymentScreen {
let controller = AuthorizationSequencePaymentScreen(sharedContext: self.sharedContext, engine: self.engine, presentationData: self.presentationData, inAppPurchaseManager: self.inAppPurchaseManager, phoneNumber: number, phoneCodeHash: phoneCodeHash, storeProduct: storeProduct, supportEmailAddress: supportEmailAddress, supportEmailSubject: supportEmailSubject, back: { [weak self] in
private func paymentController(number: String, phoneCodeHash: String, storeProduct: String, premiumDays: Int32, supportEmailAddress: String, supportEmailSubject: String) -> AuthorizationSequencePaymentScreen {
let controller = AuthorizationSequencePaymentScreen(sharedContext: self.sharedContext, engine: self.engine, presentationData: self.presentationData, inAppPurchaseManager: self.inAppPurchaseManager, phoneNumber: number, phoneCodeHash: phoneCodeHash, storeProduct: storeProduct, premiumDays: premiumDays, supportEmailAddress: supportEmailAddress, supportEmailSubject: supportEmailSubject, back: { [weak self] in
guard let self else {
return
}
@ -1348,12 +1348,12 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
}
controllers.append(self.signUpController(firstName: firstName, lastName: lastName, termsOfService: termsOfService, displayCancel: displayCancel))
self.setViewControllers(controllers, animated: !self.viewControllers.isEmpty)
case let .payment(number, codeHash, storeProduct, supportEmailAddress, supportEmailSubject, _):
case let .payment(number, codeHash, storeProduct, premiumDays, supportEmailAddress, supportEmailSubject, _):
var controllers: [ViewController] = []
if !self.otherAccountPhoneNumbers.1.isEmpty {
controllers.append(self.splashController())
}
controllers.append(self.paymentController(number: number, phoneCodeHash: codeHash, storeProduct: storeProduct, supportEmailAddress: supportEmailAddress, supportEmailSubject: supportEmailSubject))
controllers.append(self.paymentController(number: number, phoneCodeHash: codeHash, storeProduct: storeProduct, premiumDays: premiumDays, supportEmailAddress: supportEmailAddress, supportEmailSubject: supportEmailSubject))
self.setViewControllers(controllers, animated: !self.viewControllers.isEmpty)
}
}

View file

@ -39,6 +39,7 @@ final class AuthorizationSequencePaymentScreenComponent: Component {
let phoneNumber: String
let phoneCodeHash: String
let storeProduct: String
let premiumDays: Int32
let supportEmailAddress: String
let supportEmailSubject: String
@ -50,6 +51,7 @@ final class AuthorizationSequencePaymentScreenComponent: Component {
phoneNumber: String,
phoneCodeHash: String,
storeProduct: String,
premiumDays: Int32,
supportEmailAddress: String,
supportEmailSubject: String
) {
@ -60,6 +62,7 @@ final class AuthorizationSequencePaymentScreenComponent: Component {
self.phoneNumber = phoneNumber
self.phoneCodeHash = phoneCodeHash
self.storeProduct = storeProduct
self.premiumDays = premiumDays
self.supportEmailAddress = supportEmailAddress
self.supportEmailSubject = supportEmailSubject
}
@ -115,7 +118,7 @@ final class AuthorizationSequencePaymentScreenComponent: Component {
self.state?.updated()
let (currency, amount) = storeProduct.priceCurrencyAndAmount
let purpose: AppStoreTransactionPurpose = .authCode(restore: false, phoneNumber: component.phoneNumber, phoneCodeHash: component.phoneCodeHash, currency: currency, amount: amount)
let purpose: AppStoreTransactionPurpose = .authCode(restore: false, phoneNumber: component.phoneNumber, phoneCodeHash: component.phoneCodeHash, premiumDays: component.premiumDays, currency: currency, amount: amount)
let _ = (component.engine.payments.canPurchasePremium(purpose: purpose)
|> deliverOnMainQueue).start(next: { [weak self] available in
guard let self else {
@ -333,13 +336,24 @@ final class AuthorizationSequencePaymentScreenComponent: Component {
))
)
)
let supportText: String
if component.premiumDays == 7 {
supportText = environment.strings.Login_Fee_Support_Text
} else if component.premiumDays > 0 {
let daysString = environment.strings.Login_Fee_Support_NewText_Days(component.premiumDays)
supportText = environment.strings.Login_Fee_Support_NewText(daysString).string
} else {
supportText = environment.strings.Login_Fee_Support_NewTextNone
}
items.append(
AnyComponentWithIdentity(
id: "support",
component: AnyComponent(ParagraphComponent(
title: environment.strings.Login_Fee_Support_Title,
titleColor: textColor,
text: environment.strings.Login_Fee_Support_Text,
text: supportText,
textColor: secondaryTextColor,
iconName: "Premium/Authorization/Support",
iconColor: linkColor,
@ -351,7 +365,7 @@ final class AuthorizationSequencePaymentScreenComponent: Component {
sharedContext: component.sharedContext,
engine: component.engine,
inAppPurchaseManager: component.inAppPurchaseManager,
source: .auth(product.price),
source: .auth(product.price, component.premiumDays),
proceed: { [weak self] in
self?.proceed()
}
@ -410,6 +424,16 @@ final class AuthorizationSequencePaymentScreenComponent: Component {
}
let buttonString = environment.strings.Login_Fee_SignUp(priceString).string
let buttonSubtitle: String
if component.premiumDays == 7 {
buttonSubtitle = environment.strings.Login_Fee_GetPremiumForAWeek
} else if component.premiumDays > 0 {
let daysString = environment.strings.Login_Fee_GetPremiumForDays_Days(component.premiumDays)
buttonSubtitle = environment.strings.Login_Fee_GetPremiumForDays(daysString).string
} else {
buttonSubtitle = environment.strings.Login_Fee_GetPremiumNone
}
let buttonAttributedString = NSMutableAttributedString(string: buttonString, font: Font.semibold(17.0), textColor: environment.theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)
let buttonSize = self.button.update(
transition: transition,
@ -425,7 +449,7 @@ final class AuthorizationSequencePaymentScreenComponent: Component {
component: AnyComponent(
VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(text: .plain(buttonAttributedString)))),
AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: environment.strings.Login_Fee_GetPremiumForAWeek, font: Font.medium(11.0), textColor: environment.theme.list.itemCheckColors.foregroundColor.withAlphaComponent(0.7), paragraphAlignment: .center)))))
AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: buttonSubtitle, font: Font.medium(11.0), textColor: environment.theme.list.itemCheckColors.foregroundColor.withAlphaComponent(0.7), paragraphAlignment: .center)))))
], spacing: 1.0)
)
),
@ -467,6 +491,7 @@ public final class AuthorizationSequencePaymentScreen: ViewControllerComponentCo
phoneNumber: String,
phoneCodeHash: String,
storeProduct: String,
premiumDays: Int32,
supportEmailAddress: String,
supportEmailSubject: String,
back: @escaping () -> Void
@ -479,6 +504,7 @@ public final class AuthorizationSequencePaymentScreen: ViewControllerComponentCo
phoneNumber: phoneNumber,
phoneCodeHash: phoneCodeHash,
storeProduct: storeProduct,
premiumDays: premiumDays,
supportEmailAddress: supportEmailAddress,
supportEmailSubject: supportEmailSubject
), navigationBarAppearance: .transparent, theme: .default, updatedPresentationData: (initial: presentationData, signal: .single(presentationData)))

View file

@ -42,7 +42,7 @@ private let markdownVoidHTMLTags: Set<String> = [
]
private struct MarkdownSafetyLimits {
let maxFileSize = 2_097_152
let maxFileSize = 524_288
let maxLineLength = 32_768
let maxBlockquoteDepth = 64
let maxListIndent = 96

View file

@ -662,6 +662,7 @@ private final class PendingInAppPurchaseState: Codable {
case restore
case phoneNumber
case phoneCodeHash
case premiumDays
}
enum PurposeType: Int32 {
@ -686,7 +687,7 @@ private final class PendingInAppPurchaseState: Codable {
case stars(count: Int64, peerId: EnginePeer.Id?)
case starsGift(peerId: EnginePeer.Id, count: Int64)
case starsGiveaway(stars: Int64, boostPeer: EnginePeer.Id, additionalPeerIds: [EnginePeer.Id], countries: [String], onlyNewSubscribers: Bool, showWinners: Bool, prizeDescription: String?, randomId: Int64, untilDate: Int32, users: Int32)
case authCode(restore: Bool, phoneNumber: String, phoneCodeHash: String)
case authCode(restore: Bool, phoneNumber: String, phoneCodeHash: String, premiumDays: Int32)
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
@ -748,7 +749,8 @@ private final class PendingInAppPurchaseState: Codable {
self = .authCode(
restore: try container.decode(Bool.self, forKey: .restore),
phoneNumber: try container.decode(String.self, forKey: .phoneNumber),
phoneCodeHash: try container.decode(String.self, forKey: .phoneCodeHash)
phoneCodeHash: try container.decode(String.self, forKey: .phoneCodeHash),
premiumDays: try container.decode(Int32.self, forKey: .premiumDays),
)
default:
throw DecodingError.generic
@ -804,11 +806,12 @@ private final class PendingInAppPurchaseState: Codable {
try container.encode(randomId, forKey: .randomId)
try container.encode(untilDate, forKey: .untilDate)
try container.encode(users, forKey: .users)
case let .authCode(restore, phoneNumber, phoneCodeHash):
case let .authCode(restore, phoneNumber, phoneCodeHash, premiumDays):
try container.encode(PurposeType.authCode.rawValue, forKey: .type)
try container.encode(restore, forKey: .restore)
try container.encode(phoneNumber, forKey: .phoneNumber)
try container.encode(phoneCodeHash, forKey: .phoneCodeHash)
try container.encode(premiumDays, forKey: .premiumDays)
}
}
@ -832,8 +835,8 @@ private final class PendingInAppPurchaseState: Codable {
self = .starsGift(peerId: peerId, count: count)
case let .starsGiveaway(stars, boostPeer, additionalPeerIds, countries, onlyNewSubscribers, showWinners, prizeDescription, randomId, untilDate, _, _, users):
self = .starsGiveaway(stars: stars, boostPeer: boostPeer, additionalPeerIds: additionalPeerIds, countries: countries, onlyNewSubscribers: onlyNewSubscribers, showWinners: showWinners, prizeDescription: prizeDescription, randomId: randomId, untilDate: untilDate, users: users)
case let .authCode(restore, phoneNumber, phoneCodeHash, _, _):
self = .authCode(restore: restore, phoneNumber: phoneNumber, phoneCodeHash: phoneCodeHash)
case let .authCode(restore, phoneNumber, phoneCodeHash, premiumDays, _, _):
self = .authCode(restore: restore, phoneNumber: phoneNumber, phoneCodeHash: phoneCodeHash, premiumDays: premiumDays)
}
}
@ -858,8 +861,8 @@ private final class PendingInAppPurchaseState: Codable {
return .starsGift(peerId: peerId, count: count, currency: currency, amount: amount)
case let .starsGiveaway(stars, boostPeer, additionalPeerIds, countries, onlyNewSubscribers, showWinners, prizeDescription, randomId, untilDate, users):
return .starsGiveaway(stars: stars, boostPeer: boostPeer, additionalPeerIds: additionalPeerIds, countries: countries, onlyNewSubscribers: onlyNewSubscribers, showWinners: showWinners, prizeDescription: prizeDescription, randomId: randomId, untilDate: untilDate, currency: currency, amount: amount, users: users)
case let .authCode(restore, phoneNumber, phoneCodeHash):
return .authCode(restore: restore, phoneNumber: phoneNumber, phoneCodeHash: phoneCodeHash, currency: currency, amount: amount)
case let .authCode(restore, phoneNumber, phoneCodeHash, premiumDays):
return .authCode(restore: restore, phoneNumber: phoneNumber, phoneCodeHash: phoneCodeHash, premiumDays: premiumDays, currency: currency, amount: amount)
}
}
}

View file

@ -329,8 +329,8 @@ public enum PremiumSource: Equatable {
} else {
return false
}
case let .auth(lhsPrice):
if case let .auth(rhsPrice) = rhs, lhsPrice == rhsPrice {
case let .auth(lhsPrice, lhsDays):
if case let .auth(rhsPrice, rhsDays) = rhs, lhsPrice == rhsPrice, lhsDays == rhsDays {
return true
} else {
return false
@ -391,7 +391,7 @@ public enum PremiumSource: Equatable {
case todo
case copyProtection
case aiTools
case auth(String)
case auth(String, Int32)
case premiumGift(TelegramMediaFile)
var identifier: String? {
@ -3786,9 +3786,16 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
if !buttonIsHidden {
let buttonTitle: String
var buttonSubtitle: String?
if case let .auth(price) = context.component.source {
if case let .auth(price, days) = context.component.source {
buttonTitle = environment.strings.Premium_Week_SignUp(price).string
buttonSubtitle = environment.strings.Premium_Week_SignUpInfo
if days == 7 {
buttonSubtitle = environment.strings.Premium_Week_SignUpInfo
} else if days > 0 {
let daysString = environment.strings.Premium_SignUp_SignUpNewInfo_Days(days)
buttonSubtitle = environment.strings.Premium_SignUp_SignUpNewInfo(daysString).string
} else {
buttonSubtitle = environment.strings.Premium_SignUp_SignUpNewInfoNone
}
} else if isUnusedGift {
buttonTitle = environment.strings.Premium_Gift_ApplyLink
} else if state.isPremium == true && state.canUpgrade {

View file

@ -518,7 +518,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[853188252] = { return Api.InputStickerSetItem.parse_inputStickerSetItem($0) }
dict[70813275] = { return Api.InputStickeredMedia.parse_inputStickeredMediaDocument($0) }
dict[1251549527] = { return Api.InputStickeredMedia.parse_inputStickeredMediaPhoto($0) }
dict[-1682807955] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentAuthCode($0) }
dict[1069645911] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentAuthCode($0) }
dict[1634697192] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentGiftPremium($0) }
dict[-75955309] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentPremiumGiftCode($0) }
dict[369444042] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentPremiumGiveaway($0) }
@ -1358,7 +1358,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-503089271] = { return Api.auth.PasskeyLoginOptions.parse_passkeyLoginOptions($0) }
dict[326715557] = { return Api.auth.PasswordRecovery.parse_passwordRecovery($0) }
dict[1577067778] = { return Api.auth.SentCode.parse_sentCode($0) }
dict[-527082948] = { return Api.auth.SentCode.parse_sentCodePaymentRequired($0) }
dict[-125665601] = { return Api.auth.SentCode.parse_sentCodePaymentRequired($0) }
dict[596704836] = { return Api.auth.SentCode.parse_sentCodeSuccess($0) }
dict[1035688326] = { return Api.auth.SentCodeType.parse_sentCodeTypeApp($0) }
dict[1398007207] = { return Api.auth.SentCodeType.parse_sentCodeTypeCall($0) }

View file

@ -1209,17 +1209,19 @@ public extension Api {
public var flags: Int32
public var phoneNumber: String
public var phoneCodeHash: String
public var premiumDays: Int32
public var currency: String
public var amount: Int64
public init(flags: Int32, phoneNumber: String, phoneCodeHash: String, currency: String, amount: Int64) {
public init(flags: Int32, phoneNumber: String, phoneCodeHash: String, premiumDays: Int32, currency: String, amount: Int64) {
self.flags = flags
self.phoneNumber = phoneNumber
self.phoneCodeHash = phoneCodeHash
self.premiumDays = premiumDays
self.currency = currency
self.amount = amount
}
public func descriptionFields() -> (String, [(String, ConstructorParameterDescription)]) {
return ("inputStorePaymentAuthCode", [("flags", ConstructorParameterDescription(self.flags)), ("phoneNumber", ConstructorParameterDescription(self.phoneNumber)), ("phoneCodeHash", ConstructorParameterDescription(self.phoneCodeHash)), ("currency", ConstructorParameterDescription(self.currency)), ("amount", ConstructorParameterDescription(self.amount))])
return ("inputStorePaymentAuthCode", [("flags", ConstructorParameterDescription(self.flags)), ("phoneNumber", ConstructorParameterDescription(self.phoneNumber)), ("phoneCodeHash", ConstructorParameterDescription(self.phoneCodeHash)), ("premiumDays", ConstructorParameterDescription(self.premiumDays)), ("currency", ConstructorParameterDescription(self.currency)), ("amount", ConstructorParameterDescription(self.amount))])
}
}
public class Cons_inputStorePaymentGiftPremium: TypeConstructorDescription {
@ -1362,11 +1364,12 @@ public extension Api {
switch self {
case .inputStorePaymentAuthCode(let _data):
if boxed {
buffer.appendInt32(-1682807955)
buffer.appendInt32(1069645911)
}
serializeInt32(_data.flags, buffer: buffer, boxed: false)
serializeString(_data.phoneNumber, buffer: buffer, boxed: false)
serializeString(_data.phoneCodeHash, buffer: buffer, boxed: false)
serializeInt32(_data.premiumDays, buffer: buffer, boxed: false)
serializeString(_data.currency, buffer: buffer, boxed: false)
serializeInt64(_data.amount, buffer: buffer, boxed: false)
break
@ -1488,7 +1491,7 @@ public extension Api {
public func descriptionFields() -> (String, [(String, ConstructorParameterDescription)]) {
switch self {
case .inputStorePaymentAuthCode(let _data):
return ("inputStorePaymentAuthCode", [("flags", ConstructorParameterDescription(_data.flags)), ("phoneNumber", ConstructorParameterDescription(_data.phoneNumber)), ("phoneCodeHash", ConstructorParameterDescription(_data.phoneCodeHash)), ("currency", ConstructorParameterDescription(_data.currency)), ("amount", ConstructorParameterDescription(_data.amount))])
return ("inputStorePaymentAuthCode", [("flags", ConstructorParameterDescription(_data.flags)), ("phoneNumber", ConstructorParameterDescription(_data.phoneNumber)), ("phoneCodeHash", ConstructorParameterDescription(_data.phoneCodeHash)), ("premiumDays", ConstructorParameterDescription(_data.premiumDays)), ("currency", ConstructorParameterDescription(_data.currency)), ("amount", ConstructorParameterDescription(_data.amount))])
case .inputStorePaymentGiftPremium(let _data):
return ("inputStorePaymentGiftPremium", [("userId", ConstructorParameterDescription(_data.userId)), ("currency", ConstructorParameterDescription(_data.currency)), ("amount", ConstructorParameterDescription(_data.amount))])
case .inputStorePaymentPremiumGiftCode(let _data):
@ -1513,17 +1516,20 @@ public extension Api {
_2 = parseString(reader)
var _3: String?
_3 = parseString(reader)
var _4: String?
_4 = parseString(reader)
var _5: Int64?
_5 = reader.readInt64()
var _4: Int32?
_4 = reader.readInt32()
var _5: String?
_5 = parseString(reader)
var _6: Int64?
_6 = reader.readInt64()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.InputStorePaymentPurpose.inputStorePaymentAuthCode(Cons_inputStorePaymentAuthCode(flags: _1!, phoneNumber: _2!, phoneCodeHash: _3!, currency: _4!, amount: _5!))
let _c6 = _6 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
return Api.InputStorePaymentPurpose.inputStorePaymentAuthCode(Cons_inputStorePaymentAuthCode(flags: _1!, phoneNumber: _2!, phoneCodeHash: _3!, premiumDays: _4!, currency: _5!, amount: _6!))
}
else {
return nil

View file

@ -1227,18 +1227,20 @@ public extension Api.auth {
public var phoneCodeHash: String
public var supportEmailAddress: String
public var supportEmailSubject: String
public var premiumDays: Int32
public var currency: String
public var amount: Int64
public init(storeProduct: String, phoneCodeHash: String, supportEmailAddress: String, supportEmailSubject: String, currency: String, amount: Int64) {
public init(storeProduct: String, phoneCodeHash: String, supportEmailAddress: String, supportEmailSubject: String, premiumDays: Int32, currency: String, amount: Int64) {
self.storeProduct = storeProduct
self.phoneCodeHash = phoneCodeHash
self.supportEmailAddress = supportEmailAddress
self.supportEmailSubject = supportEmailSubject
self.premiumDays = premiumDays
self.currency = currency
self.amount = amount
}
public func descriptionFields() -> (String, [(String, ConstructorParameterDescription)]) {
return ("sentCodePaymentRequired", [("storeProduct", ConstructorParameterDescription(self.storeProduct)), ("phoneCodeHash", ConstructorParameterDescription(self.phoneCodeHash)), ("supportEmailAddress", ConstructorParameterDescription(self.supportEmailAddress)), ("supportEmailSubject", ConstructorParameterDescription(self.supportEmailSubject)), ("currency", ConstructorParameterDescription(self.currency)), ("amount", ConstructorParameterDescription(self.amount))])
return ("sentCodePaymentRequired", [("storeProduct", ConstructorParameterDescription(self.storeProduct)), ("phoneCodeHash", ConstructorParameterDescription(self.phoneCodeHash)), ("supportEmailAddress", ConstructorParameterDescription(self.supportEmailAddress)), ("supportEmailSubject", ConstructorParameterDescription(self.supportEmailSubject)), ("premiumDays", ConstructorParameterDescription(self.premiumDays)), ("currency", ConstructorParameterDescription(self.currency)), ("amount", ConstructorParameterDescription(self.amount))])
}
}
public class Cons_sentCodeSuccess: TypeConstructorDescription {
@ -1272,12 +1274,13 @@ public extension Api.auth {
break
case .sentCodePaymentRequired(let _data):
if boxed {
buffer.appendInt32(-527082948)
buffer.appendInt32(-125665601)
}
serializeString(_data.storeProduct, buffer: buffer, boxed: false)
serializeString(_data.phoneCodeHash, buffer: buffer, boxed: false)
serializeString(_data.supportEmailAddress, buffer: buffer, boxed: false)
serializeString(_data.supportEmailSubject, buffer: buffer, boxed: false)
serializeInt32(_data.premiumDays, buffer: buffer, boxed: false)
serializeString(_data.currency, buffer: buffer, boxed: false)
serializeInt64(_data.amount, buffer: buffer, boxed: false)
break
@ -1295,7 +1298,7 @@ public extension Api.auth {
case .sentCode(let _data):
return ("sentCode", [("flags", ConstructorParameterDescription(_data.flags)), ("type", ConstructorParameterDescription(_data.type)), ("phoneCodeHash", ConstructorParameterDescription(_data.phoneCodeHash)), ("nextType", ConstructorParameterDescription(_data.nextType)), ("timeout", ConstructorParameterDescription(_data.timeout))])
case .sentCodePaymentRequired(let _data):
return ("sentCodePaymentRequired", [("storeProduct", ConstructorParameterDescription(_data.storeProduct)), ("phoneCodeHash", ConstructorParameterDescription(_data.phoneCodeHash)), ("supportEmailAddress", ConstructorParameterDescription(_data.supportEmailAddress)), ("supportEmailSubject", ConstructorParameterDescription(_data.supportEmailSubject)), ("currency", ConstructorParameterDescription(_data.currency)), ("amount", ConstructorParameterDescription(_data.amount))])
return ("sentCodePaymentRequired", [("storeProduct", ConstructorParameterDescription(_data.storeProduct)), ("phoneCodeHash", ConstructorParameterDescription(_data.phoneCodeHash)), ("supportEmailAddress", ConstructorParameterDescription(_data.supportEmailAddress)), ("supportEmailSubject", ConstructorParameterDescription(_data.supportEmailSubject)), ("premiumDays", ConstructorParameterDescription(_data.premiumDays)), ("currency", ConstructorParameterDescription(_data.currency)), ("amount", ConstructorParameterDescription(_data.amount))])
case .sentCodeSuccess(let _data):
return ("sentCodeSuccess", [("authorization", ConstructorParameterDescription(_data.authorization))])
}
@ -1341,18 +1344,21 @@ public extension Api.auth {
_3 = parseString(reader)
var _4: String?
_4 = parseString(reader)
var _5: String?
_5 = parseString(reader)
var _6: Int64?
_6 = reader.readInt64()
var _5: Int32?
_5 = reader.readInt32()
var _6: String?
_6 = parseString(reader)
var _7: Int64?
_7 = reader.readInt64()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = _6 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
return Api.auth.SentCode.sentCodePaymentRequired(Cons_sentCodePaymentRequired(storeProduct: _1!, phoneCodeHash: _2!, supportEmailAddress: _3!, supportEmailSubject: _4!, currency: _5!, amount: _6!))
let _c7 = _7 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
return Api.auth.SentCode.sentCodePaymentRequired(Cons_sentCodePaymentRequired(storeProduct: _1!, phoneCodeHash: _2!, supportEmailAddress: _3!, supportEmailSubject: _4!, premiumDays: _5!, currency: _6!, amount: _7!))
}
else {
return nil

View file

@ -103,6 +103,21 @@ public extension Api.functions.account {
})
}
}
public extension Api.functions.account {
static func confirmBotConnection(botId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
let buffer = Buffer()
buffer.appendInt32(1743593320)
botId.serialize(buffer, true)
return (FunctionDescription(name: "account.confirmBotConnection", parameters: [("botId", ConstructorParameterDescription(botId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
let reader = BufferReader(buffer)
var result: Api.Bool?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Bool
}
return result
})
}
}
public extension Api.functions.account {
static func confirmPasswordEmail(code: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
let buffer = Buffer()

View file

@ -128,7 +128,7 @@ public class UnauthorizedAccount {
if let nextType = nextType {
parsedNextType = AuthorizationCodeNextType(apiType: nextType)
}
if let state = transaction.getState() as? UnauthorizedAccountState, case let .payment(phoneNumber, _, _, _, _, syncContacts) = state.contents {
if let state = transaction.getState() as? UnauthorizedAccountState, case let .payment(phoneNumber, _, _, _, _, _, syncContacts) = state.contents {
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: testingEnvironment, masterDatacenterId: masterDatacenterId, contents: .confirmationCodeEntry(number: phoneNumber, type: SentAuthorizationCodeType(apiType: type), hash: phoneCodeHash, timeout: codeTimeout, nextType: parsedNextType, syncContacts: syncContacts, previousCodeEntry: nil, usePrevious: false)))
}
}).start()
@ -139,7 +139,7 @@ public class UnauthorizedAccount {
let (futureAuthToken, apiUser) = (authorizationData.futureAuthToken, authorizationData.user)
let _ = postbox.transaction({ [weak self] transaction in
var syncContacts = true
if let state = transaction.getState() as? UnauthorizedAccountState, case let .payment(_, _, _, _, _, syncContactsValue) = state.contents {
if let state = transaction.getState() as? UnauthorizedAccountState, case let .payment(_, _, _, _, _, _, syncContactsValue) = state.contents {
syncContacts = syncContactsValue
}
@ -166,7 +166,7 @@ public class UnauthorizedAccount {
let termsOfService = authorizationSignUpRequiredData.termsOfService
let _ = postbox.transaction({ [weak self] transaction in
if let self {
if let state = transaction.getState() as? UnauthorizedAccountState, case let .payment(number, codeHash, _, _, _, syncContacts) = state.contents {
if let state = transaction.getState() as? UnauthorizedAccountState, case let .payment(number, codeHash, _, _, _, _, syncContacts) = state.contents {
let _ = beginSignUp(
account: self,
data: AuthorizationSignUpData(

View file

@ -527,8 +527,8 @@ private func internalResendAuthorizationCode(accountManager: AccountManager<Tele
return .single(.sentCode(account))
case let .sentCodePaymentRequired(sentCodePaymentRequiredData):
let (storeProduct, codeHash, supportEmailAddress, supportEmailSubject) = (sentCodePaymentRequiredData.storeProduct, sentCodePaymentRequiredData.phoneCodeHash, sentCodePaymentRequiredData.supportEmailAddress, sentCodePaymentRequiredData.supportEmailSubject)
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .payment(number: number, codeHash: codeHash, storeProduct: storeProduct, supportEmailAddress: supportEmailAddress, supportEmailSubject: supportEmailSubject, syncContacts: syncContacts)))
let (storeProduct, codeHash, supportEmailAddress, supportEmailSubject, premiumDays) = (sentCodePaymentRequiredData.storeProduct, sentCodePaymentRequiredData.phoneCodeHash, sentCodePaymentRequiredData.supportEmailAddress, sentCodePaymentRequiredData.supportEmailSubject, sentCodePaymentRequiredData.premiumDays)
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .payment(number: number, codeHash: codeHash, storeProduct: storeProduct, premiumDays: premiumDays, supportEmailAddress: supportEmailAddress, supportEmailSubject: supportEmailSubject, syncContacts: syncContacts)))
return .single(.sentCode(account))
case .sentCodeSuccess:
return .single(.loggedIn)
@ -638,8 +638,8 @@ public func resendAuthorizationCode(accountManager: AccountManager<TelegramAccou
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .confirmationCodeEntry(number: number, type: parsedType, hash: phoneCodeHash, timeout: codeTimeout, nextType: parsedNextType, syncContacts: syncContacts, previousCodeEntry: previousCodeEntry, usePrevious: false)))
case let .sentCodePaymentRequired(sentCodePaymentRequiredData):
let (storeProduct, codeHash, supportEmailAddress, supportEmailSubject) = (sentCodePaymentRequiredData.storeProduct, sentCodePaymentRequiredData.phoneCodeHash, sentCodePaymentRequiredData.supportEmailAddress, sentCodePaymentRequiredData.supportEmailSubject)
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .payment(number: number, codeHash: codeHash, storeProduct: storeProduct, supportEmailAddress: supportEmailAddress, supportEmailSubject: supportEmailSubject, syncContacts: syncContacts)))
let (storeProduct, codeHash, supportEmailAddress, supportEmailSubject, premiumDays) = (sentCodePaymentRequiredData.storeProduct, sentCodePaymentRequiredData.phoneCodeHash, sentCodePaymentRequiredData.supportEmailAddress, sentCodePaymentRequiredData.supportEmailSubject, sentCodePaymentRequiredData.premiumDays)
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .payment(number: number, codeHash: codeHash, storeProduct: storeProduct, premiumDays: premiumDays, supportEmailAddress: supportEmailAddress, supportEmailSubject: supportEmailSubject, syncContacts: syncContacts)))
case .sentCodeSuccess:
break
}
@ -922,8 +922,8 @@ public func verifyLoginEmailSetup(account: UnauthorizedAccount, code: Authorizat
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .confirmationCodeEntry(number: phoneNumber, type: SentAuthorizationCodeType(apiType: type), hash: phoneCodeHash, timeout: timeout, nextType: parsedNextType, syncContacts: syncContacts, previousCodeEntry: nil, usePrevious: false)))
case let .sentCodePaymentRequired(sentCodePaymentRequiredData):
let (storeProduct, codeHash, supportEmailAddress, supportEmailSubject) = (sentCodePaymentRequiredData.storeProduct, sentCodePaymentRequiredData.phoneCodeHash, sentCodePaymentRequiredData.supportEmailAddress, sentCodePaymentRequiredData.supportEmailSubject)
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .payment(number: phoneNumber, codeHash: codeHash, storeProduct: storeProduct, supportEmailAddress: supportEmailAddress, supportEmailSubject: supportEmailSubject, syncContacts: syncContacts)))
let (storeProduct, codeHash, supportEmailAddress, supportEmailSubject, premiumDays) = (sentCodePaymentRequiredData.storeProduct, sentCodePaymentRequiredData.phoneCodeHash, sentCodePaymentRequiredData.supportEmailAddress, sentCodePaymentRequiredData.supportEmailSubject, sentCodePaymentRequiredData.premiumDays)
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .payment(number: phoneNumber, codeHash: codeHash, storeProduct: storeProduct, premiumDays: premiumDays, supportEmailAddress: supportEmailAddress, supportEmailSubject: supportEmailSubject, syncContacts: syncContacts)))
case .sentCodeSuccess:
break
}
@ -989,8 +989,8 @@ public func resetLoginEmail(account: UnauthorizedAccount, phoneNumber: String, p
return .complete()
case let .sentCodePaymentRequired(sentCodePaymentRequiredData):
let (storeProduct, codeHash, supportEmailAddress, supportEmailSubject) = (sentCodePaymentRequiredData.storeProduct, sentCodePaymentRequiredData.phoneCodeHash, sentCodePaymentRequiredData.supportEmailAddress, sentCodePaymentRequiredData.supportEmailSubject)
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .payment(number: phoneNumber, codeHash: codeHash, storeProduct: storeProduct, supportEmailAddress: supportEmailAddress, supportEmailSubject: supportEmailSubject, syncContacts: syncContacts)))
let (storeProduct, codeHash, supportEmailAddress, supportEmailSubject, premiumDays) = (sentCodePaymentRequiredData.storeProduct, sentCodePaymentRequiredData.phoneCodeHash, sentCodePaymentRequiredData.supportEmailAddress, sentCodePaymentRequiredData.supportEmailSubject, sentCodePaymentRequiredData.premiumDays)
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .payment(number: phoneNumber, codeHash: codeHash, storeProduct: storeProduct, premiumDays: premiumDays, supportEmailAddress: supportEmailAddress, supportEmailSubject: supportEmailSubject, syncContacts: syncContacts)))
return .complete()
case .sentCodeSuccess:
return .complete()

View file

@ -182,7 +182,7 @@ public indirect enum UnauthorizedAccountStateContents: PostboxCoding, Equatable
case passwordRecovery(hint: String, number: String?, code: AuthorizationCode?, emailPattern: String, syncContacts: Bool)
case awaitingAccountReset(protectedUntil: Int32, number: String?, syncContacts: Bool)
case signUp(number: String, codeHash: String, firstName: String, lastName: String, termsOfService: UnauthorizedAccountTermsOfService?, syncContacts: Bool)
case payment(number: String, codeHash: String, storeProduct: String, supportEmailAddress: String, supportEmailSubject: String, syncContacts: Bool)
case payment(number: String, codeHash: String, storeProduct: String, premiumDays: Int32, supportEmailAddress: String, supportEmailSubject: String, syncContacts: Bool)
public init(decoder: PostboxDecoder) {
switch decoder.decodeInt32ForKey("v", orElse: 0) {
@ -217,7 +217,7 @@ public indirect enum UnauthorizedAccountStateContents: PostboxCoding, Equatable
case UnauthorizedAccountStateContentsValue.signUp.rawValue:
self = .signUp(number: decoder.decodeStringForKey("n", orElse: ""), codeHash: decoder.decodeStringForKey("h", orElse: ""), firstName: decoder.decodeStringForKey("f", orElse: ""), lastName: decoder.decodeStringForKey("l", orElse: ""), termsOfService: decoder.decodeObjectForKey("tos", decoder: { UnauthorizedAccountTermsOfService(decoder: $0) }) as? UnauthorizedAccountTermsOfService, syncContacts: decoder.decodeInt32ForKey("syncContacts", orElse: 1) != 0)
case UnauthorizedAccountStateContentsValue.payment.rawValue:
self = .payment(number: decoder.decodeStringForKey("n", orElse: ""), codeHash: decoder.decodeStringForKey("h", orElse: ""), storeProduct: decoder.decodeStringForKey("storeProduct", orElse: ""), supportEmailAddress: decoder.decodeStringForKey("supportEmailAddress", orElse: ""), supportEmailSubject: decoder.decodeStringForKey("supportEmailSubject", orElse: ""), syncContacts: decoder.decodeInt32ForKey("syncContacts", orElse: 1) != 0)
self = .payment(number: decoder.decodeStringForKey("n", orElse: ""), codeHash: decoder.decodeStringForKey("h", orElse: ""), storeProduct: decoder.decodeStringForKey("storeProduct", orElse: ""), premiumDays: decoder.decodeInt32ForKey("premiumDays", orElse: 7), supportEmailAddress: decoder.decodeStringForKey("supportEmailAddress", orElse: ""), supportEmailSubject: decoder.decodeStringForKey("supportEmailSubject", orElse: ""), syncContacts: decoder.decodeInt32ForKey("syncContacts", orElse: 1) != 0)
default:
assertionFailure()
self = .empty
@ -307,11 +307,12 @@ public indirect enum UnauthorizedAccountStateContents: PostboxCoding, Equatable
encoder.encodeNil(forKey: "tos")
}
encoder.encodeInt32(syncContacts ? 1 : 0, forKey: "syncContacts")
case let .payment(number, codeHash, storeProduct, supportEmailAddress, supportEmailSubject, syncContacts):
case let .payment(number, codeHash, storeProduct, premiumDays, supportEmailAddress, supportEmailSubject, syncContacts):
encoder.encodeInt32(UnauthorizedAccountStateContentsValue.payment.rawValue, forKey: "v")
encoder.encodeString(number, forKey: "n")
encoder.encodeString(codeHash, forKey: "h")
encoder.encodeString(storeProduct, forKey: "storeProduct")
encoder.encodeInt32(premiumDays, forKey: "premiumDays")
encoder.encodeString(supportEmailAddress, forKey: "supportEmailAddress")
encoder.encodeString(supportEmailSubject, forKey: "supportEmailSubject")
encoder.encodeInt32(syncContacts ? 1 : 0, forKey: "syncContacts")
@ -386,8 +387,8 @@ public indirect enum UnauthorizedAccountStateContents: PostboxCoding, Equatable
} else {
return false
}
case let .payment(number, codeHash, storeProduct, supportEmailAddress, supportEmailSubject, syncContacts):
if case .payment(number, codeHash, storeProduct, supportEmailAddress, supportEmailSubject, syncContacts) = rhs {
case let .payment(number, codeHash, storeProduct, premiumDays, supportEmailAddress, supportEmailSubject, syncContacts):
if case .payment(number, codeHash, storeProduct, premiumDays, supportEmailAddress, supportEmailSubject, syncContacts) = rhs {
return true
} else {
return false

View file

@ -20,7 +20,7 @@ public enum AppStoreTransactionPurpose {
case stars(count: Int64, currency: String, amount: Int64, peerId: EnginePeer.Id?)
case starsGift(peerId: EnginePeer.Id, count: Int64, currency: String, amount: Int64)
case starsGiveaway(stars: Int64, boostPeer: EnginePeer.Id, additionalPeerIds: [EnginePeer.Id], countries: [String], onlyNewSubscribers: Bool, showWinners: Bool, prizeDescription: String?, randomId: Int64, untilDate: Int32, currency: String, amount: Int64, users: Int32)
case authCode(restore: Bool, phoneNumber: String, phoneCodeHash: String, currency: String, amount: Int64)
case authCode(restore: Bool, phoneNumber: String, phoneCodeHash: String, premiumDays: Int32, currency: String, amount: Int64)
}
private func apiInputStorePaymentPurpose(postbox: Postbox, purpose: AppStoreTransactionPurpose) -> Signal<Api.InputStorePaymentPurpose, NoError> {
@ -155,12 +155,12 @@ private func apiInputStorePaymentPurpose(postbox: Postbox, purpose: AppStoreTran
return .single(.inputStorePaymentStarsGiveaway(.init(flags: flags, stars: stars, boostPeer: apiBoostPeer, additionalPeers: additionalPeers, countriesIso2: countries, prizeDescription: prizeDescription, randomId: randomId, untilDate: untilDate, currency: currency, amount: amount, users: users)))
}
|> switchToLatest
case let .authCode(restore, phoneNumber, phoneCodeHash, currency, amount):
case let .authCode(restore, phoneNumber, phoneCodeHash, premiumDays, currency, amount):
var flags: Int32 = 0
if restore {
flags |= (1 << 0)
}
return .single(.inputStorePaymentAuthCode(.init(flags: flags, phoneNumber: phoneNumber, phoneCodeHash: phoneCodeHash, currency: currency, amount: amount)))
return .single(.inputStorePaymentAuthCode(.init(flags: flags, phoneNumber: phoneNumber, phoneCodeHash: phoneCodeHash, premiumDays: premiumDays, currency: currency, amount: amount)))
}
}

View file

@ -204,7 +204,7 @@ final class ComposeTodoScreenComponent: Component {
for (id, itemView) in self.todoItemsSectionContainer.itemViews {
if let view = itemView.contents.view as? ListComposePollOptionComponent.View, !view.isRevealed && !view.currentText.isEmpty {
let viewFrame = view.convert(view.bounds, to: self.todoItemsSectionContainer)
let iconFrame = CGRect(origin: CGPoint(x: viewFrame.maxX - 40.0, y: viewFrame.minY), size: CGSize(width: viewFrame.height, height: viewFrame.height))
let iconFrame = CGRect(origin: CGPoint(x: viewFrame.minX, y: viewFrame.minY), size: CGSize(width: 50.0, height: viewFrame.height))
if iconFrame.contains(localPoint) {
return (id, itemView.contents)
}

View file

@ -345,6 +345,7 @@ public final class GiftItemComponent: Component {
private var selectionLayer: SimpleShapeLayer?
private var checkLayer: CheckLayer?
private var outlineLayer: SimpleLayer?
private var outlineRenderState: OutlineRenderState?
private var animationFile: TelegramMediaFile?
@ -361,6 +362,14 @@ public final class GiftItemComponent: Component {
private var giftAuctionTimer: SwiftSignalKit.Timer?
private struct OutlineRenderState: Equatable {
let size: CGSize
let cornerRadius: CGFloat
let outline: GiftItemComponent.Outline
let hasRibbon: Bool
let themeId: ObjectIdentifier
}
public var pattern: UIView? {
if let view = self.patternView.view {
return view
@ -1537,6 +1546,14 @@ public final class GiftItemComponent: Component {
if let outline = component.outline {
let lineWidth: CGFloat = 2.0
let outlineFrame = backgroundFrame
let hasRibbon = self.ribbon.layer.superlayer != nil
let outlineRenderState = OutlineRenderState(
size: outlineFrame.size,
cornerRadius: cornerRadius,
outline: outline,
hasRibbon: hasRibbon,
themeId: ObjectIdentifier(component.theme)
)
let outlineLayer: SimpleLayer
if let current = self.outlineLayer {
@ -1544,12 +1561,15 @@ public final class GiftItemComponent: Component {
} else {
outlineLayer = SimpleLayer()
self.outlineLayer = outlineLayer
if self.ribbon.layer.superlayer != nil {
self.layer.insertSublayer(outlineLayer, below: self.ribbon.layer)
} else {
self.layer.addSublayer(outlineLayer)
}
}
if hasRibbon {
self.layer.insertSublayer(outlineLayer, below: self.ribbon.layer)
} else if outlineLayer.superlayer == nil {
self.layer.addSublayer(outlineLayer)
}
if self.outlineRenderState != outlineRenderState {
let image = generateImage(outlineFrame.size, rotatedContext: { size, context in
context.clear(CGRect(origin: .zero, size: size))
@ -1588,11 +1608,13 @@ public final class GiftItemComponent: Component {
}
})
outlineLayer.contents = image?.cgImage
outlineLayer.frame = outlineFrame
self.outlineRenderState = outlineRenderState
}
transition.setFrame(layer: outlineLayer, frame: outlineFrame)
} else if let outlineLayer = self.outlineLayer {
self.outlineLayer = nil
self.outlineRenderState = nil
outlineLayer.removeFromSuperlayer()
}

View file

@ -698,13 +698,13 @@ final class ChatbotSetupScreenComponent: Component {
let iconSize = self.icon.update(
transition: .immediate,
component: AnyComponent(LottieComponent(
content: LottieComponent.AppBundleContent(name: "BotEmoji"),
content: LottieComponent.AppBundleContent(name: "ChatAutomation"),
loop: false
)),
environment: {},
containerSize: CGSize(width: 100.0, height: 100.0)
containerSize: CGSize(width: 140.0, height: 140.0)
)
let iconFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - iconSize.width) * 0.5), y: contentHeight - 30.0), size: iconSize)
let iconFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - iconSize.width) * 0.5), y: contentHeight - 50.0), size: iconSize)
if let iconView = self.icon.view as? LottieComponent.View {
if iconView.superview == nil {
self.scrollView.addSubview(iconView)

View file

@ -530,6 +530,8 @@ extension ChatControllerImpl {
let initialInterfaceState = contentData.initialInterfaceState
contentData.initialInterfaceState = nil
let initialTextInputState = self.initialTextInputState
self.initialTextInputState = nil
if !self.didInitializePersistentPeerInterfaceData, let initialPersistentPeerData = contentData.initialPersistentPeerData {
self.didInitializePersistentPeerInterfaceData = true
@ -541,6 +543,9 @@ extension ChatControllerImpl {
if let initialInterfaceState {
interfaceState = initialInterfaceState.interfaceState
}
if let initialTextInputState {
interfaceState = interfaceState.withUpdatedComposeInputState(initialTextInputState)
}
if let channel = contentData.state.renderedPeer?.peer as? TelegramChannel {
if channel.hasBannedPermission(.banSendVoice) != nil && channel.hasBannedPermission(.banSendInstantVideos) != nil {

View file

@ -252,6 +252,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let context: AccountContext
public internal(set) var chatLocation: ChatLocation
public internal(set) var subject: ChatControllerSubject?
var initialTextInputState: ChatTextInputState?
var botStart: ChatControllerInitialBotStart?
var attachBotStart: ChatControllerInitialAttachBotStart?
@ -642,6 +643,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
chatListFilter: Int32? = nil,
chatNavigationStack: [ChatNavigationStackItem] = [],
customChatNavigationStack: [EnginePeer.Id]? = nil,
initialTextInputState: ChatTextInputState? = nil,
params: ChatControllerParams? = nil
) {
self.initTimestamp = CFAbsoluteTimeGetCurrent()
@ -654,6 +656,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.chatLocation = chatLocation
self.chatLocationContextHolder = chatLocationContextHolder
self.subject = subject
self.initialTextInputState = initialTextInputState
self.botStart = botStart
self.attachBotStart = attachBotStart
self.botAppStart = botAppStart

View file

@ -46,12 +46,12 @@ func leftNavigationButtonForChatInterfaceState(_ presentationInterfaceState: Cha
}
if canClear {
let buttonItem = UIBarButtonItem(title: "___clear", style: .plain, target: target, action: selector)
let buttonItem = UIBarButtonItem(title: strings.Conversation_ClearAll, style: .plain, target: target, action: selector)
buttonItem.accessibilityLabel = title
return ChatNavigationButton(action: .clearHistory, buttonItem: buttonItem)
} else {
title = strings.Conversation_ClearCache
let buttonItem = UIBarButtonItem(title: "___clear", style: .plain, target: target, action: selector)
let buttonItem = UIBarButtonItem(title: strings.Conversation_ClearCache, style: .plain, target: target, action: selector)
buttonItem.accessibilityLabel = title
return ChatNavigationButton(action: .clearCache, buttonItem: buttonItem)
}

View file

@ -253,8 +253,14 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
controller.presentBotApp(botApp: botAppStart.botApp, botPeer: peer, payload: botAppStart.payload, mode: botAppStart.mode)
}
}
if controller.chatLocation.peerId == params.chatLocation.asChatLocation.peerId && controller.chatLocation.threadId == params.chatLocation.asChatLocation.threadId && (controller.subject != .scheduledMessages || controller.subject == params.subject) {
if let updateTextInputState = params.updateTextInputState {
controller.updateTextInputState(updateTextInputState)
}
}
} else {
controller = ChatControllerImpl(context: params.context, chatLocation: params.chatLocation.asChatLocation, chatLocationContextHolder: params.chatLocationContextHolder, subject: params.subject, botStart: params.botStart, attachBotStart: params.attachBotStart, botAppStart: params.botAppStart, peekData: params.peekData, chatListFilter: params.chatListFilter, chatNavigationStack: params.chatNavigationStack, customChatNavigationStack: params.customChatNavigationStack)
controller = ChatControllerImpl(context: params.context, chatLocation: params.chatLocation.asChatLocation, chatLocationContextHolder: params.chatLocationContextHolder, subject: params.subject, botStart: params.botStart, attachBotStart: params.attachBotStart, botAppStart: params.botAppStart, peekData: params.peekData, chatListFilter: params.chatListFilter, chatNavigationStack: params.chatNavigationStack, customChatNavigationStack: params.customChatNavigationStack, initialTextInputState: params.updateTextInputState)
if let botAppStart = params.botAppStart, case let .peer(peer) = params.chatLocation {
Queue.mainQueue().after(0.1) {
@ -263,14 +269,6 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
}
}
if controller.chatLocation.peerId == params.chatLocation.asChatLocation.peerId && controller.chatLocation.threadId == params.chatLocation.asChatLocation.threadId && (controller.subject != .scheduledMessages || controller.subject == params.subject) {
if let updateTextInputState = params.updateTextInputState {
Queue.mainQueue().after(0.1) {
controller.updateTextInputState(updateTextInputState)
}
}
}
controller.purposefulAction = params.purposefulAction
if let search = params.activateMessageSearch {
controller.activateSearch(domain: search.0, query: search.1)
@ -449,7 +447,7 @@ public func navigateToForumThreadImpl(context: AccountContext, peerId: EnginePee
}
}
public func chatControllerForForumThreadImpl(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64) -> Signal<ChatController, NoError> {
public func chatControllerForForumThreadImpl(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, initialTextInputState: ChatTextInputState? = nil) -> Signal<ChatController, NoError> {
return context.engine.data.get(
TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)
)
@ -477,7 +475,8 @@ public func chatControllerForForumThreadImpl(context: AccountContext, peerId: En
initialAnchor: .automatic,
isNotAvailable: false
)),
chatLocationContextHolder: Atomic(value: nil)
chatLocationContextHolder: Atomic(value: nil),
initialTextInputState: initialTextInputState
))
} else {
return fetchAndPreloadReplyThreadInfo(context: context, subject: .groupMessage(MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId))), atMessageId: nil, preload: false)
@ -489,7 +488,8 @@ public func chatControllerForForumThreadImpl(context: AccountContext, peerId: En
return ChatControllerImpl(
context: context,
chatLocation: .replyThread(message: result.message),
chatLocationContextHolder: result.contextHolder
chatLocationContextHolder: result.contextHolder,
initialTextInputState: initialTextInputState
)
}
}

View file

@ -20,7 +20,6 @@ import JoinLinkPreviewUI
import LanguageLinkPreviewUI
import SettingsUI
import UrlHandling
import ChatInterfaceState
import TelegramCallsUI
import UndoUI
import ImportStickerPackUI
@ -631,16 +630,16 @@ func openResolvedUrlImpl(
}
let chatController: Signal<ChatController, NoError>
if let threadId {
chatController = chatControllerForForumThreadImpl(context: context, peerId: peerId, threadId: threadId)
chatController = chatControllerForForumThreadImpl(context: context, peerId: peerId, threadId: threadId, initialTextInputState: textInputState)
} else {
chatController = .single(ChatControllerImpl(context: context, chatLocation: .peer(id: peerId)))
chatController = .single(ChatControllerImpl(context: context, chatLocation: .peer(id: peerId), initialTextInputState: textInputState))
}
let _ = (chatController
|> deliverOnMainQueue).start(next: { [weak navigationController] chatController in
guard let navigationController else {
return
}
}
var controllers = navigationController.viewControllers.filter { controller in
if controller is PeerSelectionController {
return false
@ -651,17 +650,8 @@ func openResolvedUrlImpl(
navigationController.setViewControllers(controllers, animated: true)
})
}
if let textInputState = textInputState {
let _ = (ChatInterfaceState.update(engine: context.engine, peerId: peerId, threadId: threadId, { currentState in
return currentState.withUpdatedComposeInputState(textInputState)
})
|> deliverOnMainQueue).startStandalone(completed: {
updateControllers()
})
} else {
updateControllers()
}
updateControllers()
}
if let to = to {

View file

@ -2975,8 +2975,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
mappedSource = .copyProtection
case .aiTools:
mappedSource = .aiTools
case let .auth(price):
mappedSource = .auth(price)
case let .auth(price, days):
mappedSource = .auth(price, days)
case let .premiumGift(file):
mappedSource = .premiumGift(file)
}

View file

@ -604,20 +604,9 @@ private func refreshTextMentions(text: NSString, initialAttributedText: NSAttrib
}
}
private let textUrlEdgeCharacters: CharacterSet = {
var set: CharacterSet = .alphanumerics
set.formUnion(.symbols)
set.formUnion(.punctuationCharacters)
set.remove("(")
set.remove(")")
return set
}()
private let textUrlCharacters: CharacterSet = {
var set: CharacterSet = textUrlEdgeCharacters
set.formUnion(.whitespacesAndNewlines)
return set
}()
private func isTextUrlInnerCharacter(_ c: UnicodeScalar) -> Bool {
return alphanumericCharacters.contains(c) || c == " " as UnicodeScalar
}
private func refreshTextUrls(text: NSString, initialAttributedText: NSAttributedString, attributedText: NSMutableAttributedString, fullRange: NSRange) {
var textUrlRanges: [(NSRange, ChatTextInputTextUrlAttribute)] = []
@ -635,7 +624,7 @@ private func refreshTextUrls(text: NSString, initialAttributedText: NSAttributed
var validLower = range.lowerBound
inner1: for i in range.lowerBound ..< range.upperBound {
if let c = UnicodeScalar(text.character(at: i)) {
if textUrlCharacters.contains(c) {
if isTextUrlInnerCharacter(c) {
validLower = i
break inner1
}
@ -646,7 +635,7 @@ private func refreshTextUrls(text: NSString, initialAttributedText: NSAttributed
var validUpper = range.upperBound
inner2: for i in (validLower ..< range.upperBound).reversed() {
if let c = UnicodeScalar(text.character(at: i)) {
if textUrlCharacters.contains(c) {
if isTextUrlInnerCharacter(c) {
validUpper = i + 1
break inner2
}
@ -658,7 +647,7 @@ private func refreshTextUrls(text: NSString, initialAttributedText: NSAttributed
let minLower = (i == 0) ? fullRange.lowerBound : textUrlRanges[i - 1].0.upperBound
inner3: for i in (minLower ..< validLower).reversed() {
if let c = UnicodeScalar(text.character(at: i)) {
if textUrlEdgeCharacters.contains(c) {
if alphanumericCharacters.contains(c) {
validLower = i
} else {
break inner3
@ -671,7 +660,7 @@ private func refreshTextUrls(text: NSString, initialAttributedText: NSAttributed
let maxUpper = (i == textUrlRanges.count - 1) ? fullRange.upperBound : textUrlRanges[i + 1].0.lowerBound
inner3: for i in validUpper ..< maxUpper {
if let c = UnicodeScalar(text.character(at: i)) {
if textUrlEdgeCharacters.contains(c) {
if alphanumericCharacters.contains(c) {
validUpper = i + 1
} else {
break inner3
@ -693,7 +682,7 @@ private func refreshTextUrls(text: NSString, initialAttributedText: NSAttributed
var combine = true
inner: for j in textUrlRanges[i].0.upperBound ..< textUrlRanges[i + 1].0.lowerBound {
if let c = UnicodeScalar(text.character(at: j)) {
if textUrlCharacters.contains(c) {
if isTextUrlInnerCharacter(c) {
} else {
combine = false
break inner