mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-06 03:33:41 +02:00
Merge commit '92c350b559'
This commit is contained in:
commit
96de278d49
27 changed files with 214 additions and 126 deletions
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ public enum PremiumIntroSource {
|
|||
case todo
|
||||
case copyProtection
|
||||
case aiTools
|
||||
case auth(String)
|
||||
case auth(String, Int32)
|
||||
case premiumGift(TelegramMediaFile)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Binary file not shown.
BIN
submodules/TelegramUI/Resources/Animations/ChatAutomation.tgs
Normal file
BIN
submodules/TelegramUI/Resources/Animations/ChatAutomation.tgs
Normal file
Binary file not shown.
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue