diff --git a/submodules/AuthorizationUI/Sources/AuthorizationSequenceController.swift b/submodules/AuthorizationUI/Sources/AuthorizationSequenceController.swift index 84cabc14c4..ff71e9e9cf 100644 --- a/submodules/AuthorizationUI/Sources/AuthorizationSequenceController.swift +++ b/submodules/AuthorizationUI/Sources/AuthorizationSequenceController.swift @@ -767,8 +767,8 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth return controller } - private func paymentController(number: String, phoneCodeHash: String, storeProduct: String) -> AuthorizationSequencePaymentScreen { - let controller = AuthorizationSequencePaymentScreen(sharedContext: self.sharedContext, engine: self.engine, presentationData: self.presentationData, inAppPurchaseManager: self.inAppPurchaseManager, phoneNumber: number, phoneCodeHash: phoneCodeHash, storeProduct: storeProduct, back: { [weak self] in + 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 guard let self else { return } @@ -808,7 +808,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth case .emailNotAllowed: text = strongSelf.presentationData.strings.Login_EmailNotAllowedError } - lastController.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root)) + lastController.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: nil, text: text, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root)) } })) } else { @@ -1305,12 +1305,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, _, _, _): + case let .payment(number, codeHash, storeProduct, supportEmailAddress, supportEmailSubject, _): var controllers: [ViewController] = [] if !self.otherAccountPhoneNumbers.1.isEmpty { controllers.append(self.splashController()) } - controllers.append(self.paymentController(number: number, phoneCodeHash: codeHash, storeProduct: storeProduct)) + controllers.append(self.paymentController(number: number, phoneCodeHash: codeHash, storeProduct: storeProduct, supportEmailAddress: supportEmailAddress, supportEmailSubject: supportEmailSubject)) self.setViewControllers(controllers, animated: !self.viewControllers.isEmpty) } } @@ -1337,7 +1337,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth } } - private static func presentEmailComposeController(address: String, subject: String, body: String, from controller: ViewController, presentationData: PresentationData) { + static func presentEmailComposeController(address: String, subject: String, body: String, from controller: ViewController, presentationData: PresentationData) { if MFMailComposeViewController.canSendMail() { final class ComposeDelegate: NSObject, MFMailComposeViewControllerDelegate { @objc func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) { @@ -1414,24 +1414,20 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth phoneNumber: String, mnc: String ) { - if MFMailComposeViewController.canSendMail() { - let formattedNumber = formatPhoneNumber(phoneNumber) - - var emailBody = "" - emailBody.append(presentationData.strings.Login_EmailCodeBody(formattedNumber).string) - emailBody.append("\n\n") - - let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown" - let systemVersion = UIDevice.current.systemVersion - let locale = Locale.current.identifier - emailBody.append("Telegram: \(appVersion)\n") - emailBody.append("OS: \(systemVersion)\n") - emailBody.append("Locale: \(locale)\n") - emailBody.append("MNC: \(mnc)") - - AuthorizationSequenceController.presentEmailComposeController(address: "sms@telegram.org", subject: presentationData.strings.Login_EmailCodeSubject(formattedNumber).string, body: emailBody, from: controller, presentationData: presentationData) - } else { - controller.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: presentationData.strings.Login_EmailNotConfiguredError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root)) - } + let formattedNumber = formatPhoneNumber(phoneNumber) + + var emailBody = "" + emailBody.append(presentationData.strings.Login_EmailCodeBody(formattedNumber).string) + emailBody.append("\n\n") + + let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown" + let systemVersion = UIDevice.current.systemVersion + let locale = Locale.current.identifier + emailBody.append("Telegram: \(appVersion)\n") + emailBody.append("OS: \(systemVersion)\n") + emailBody.append("Locale: \(locale)\n") + emailBody.append("MNC: \(mnc)") + + AuthorizationSequenceController.presentEmailComposeController(address: "sms@telegram.org", subject: presentationData.strings.Login_EmailCodeSubject(formattedNumber).string, body: emailBody, from: controller, presentationData: presentationData) } } diff --git a/submodules/AuthorizationUI/Sources/AuthorizationSequencePaymentScreen.swift b/submodules/AuthorizationUI/Sources/AuthorizationSequencePaymentScreen.swift index 8310c8f980..1f35a72415 100644 --- a/submodules/AuthorizationUI/Sources/AuthorizationSequencePaymentScreen.swift +++ b/submodules/AuthorizationUI/Sources/AuthorizationSequencePaymentScreen.swift @@ -23,6 +23,9 @@ import Markdown import CountrySelectionUI import AccountContext import AlertUI +import MessageUI +import CoreTelephony +import PhoneNumberFormat final class AuthorizationSequencePaymentScreenComponent: Component { typealias EnvironmentType = ViewControllerComponentContainer.Environment @@ -34,6 +37,8 @@ final class AuthorizationSequencePaymentScreenComponent: Component { let phoneNumber: String let phoneCodeHash: String let storeProduct: String + let supportEmailAddress: String + let supportEmailSubject: String init( sharedContext: SharedAccountContext, @@ -42,7 +47,9 @@ final class AuthorizationSequencePaymentScreenComponent: Component { presentationData: PresentationData, phoneNumber: String, phoneCodeHash: String, - storeProduct: String + storeProduct: String, + supportEmailAddress: String, + supportEmailSubject: String ) { self.sharedContext = sharedContext self.engine = engine @@ -51,6 +58,8 @@ final class AuthorizationSequencePaymentScreenComponent: Component { self.phoneNumber = phoneNumber self.phoneCodeHash = phoneCodeHash self.storeProduct = storeProduct + self.supportEmailAddress = supportEmailAddress + self.supportEmailSubject = supportEmailSubject } static func ==(lhs: AuthorizationSequencePaymentScreenComponent, rhs: AuthorizationSequencePaymentScreenComponent) -> Bool { @@ -125,26 +134,54 @@ final class AuthorizationSequencePaymentScreenComponent: Component { self.state?.updated(transition: .immediate) var errorText: String? + var errorCode: Int32? switch error { case .generic: errorText = presentationData.strings.Premium_Purchase_ErrorUnknown + errorCode = 1001 case .network: errorText = presentationData.strings.Premium_Purchase_ErrorNetwork + errorCode = 1002 case .notAllowed: errorText = presentationData.strings.Premium_Purchase_ErrorNotAllowed + errorCode = 1003 case .cantMakePayments: errorText = presentationData.strings.Premium_Purchase_ErrorCantMakePayments + errorCode = 1004 case .assignFailed: errorText = presentationData.strings.Premium_Purchase_ErrorUnknown + errorCode = 1005 case .tryLater: errorText = presentationData.strings.Premium_Purchase_ErrorUnknown + errorCode = 1006 case .cancelled: break } - if let errorText { + if let errorText, let errorCode { let theme = AlertControllerTheme(presentationData: presentationData) - let alertController = textAlertController(alertContext: AlertControllerContext(theme: theme, themeSignal: .single(theme)), title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]) + let alertController = textAlertController( + alertContext: AlertControllerContext(theme: theme, themeSignal: .single(theme)), + title: nil, + text: errorText, + actions: [ + TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {}), + TextAlertAction(type: .defaultAction, title: presentationData.strings.Login_PhoneNumberHelp, action: { [weak controller] in + guard let controller else { + return + } + let formattedNumber = formatPhoneNumber(component.phoneNumber) + let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown" + let systemVersion = UIDevice.current.systemVersion + let locale = Locale.current.identifier + let carrier = CTCarrier() + let mnc = carrier.mobileNetworkCode ?? "none" + let errorString: String = "\(errorCode): \(errorText)" + + AuthorizationSequenceController.presentEmailComposeController(address: component.supportEmailAddress, subject: component.supportEmailSubject, body: presentationData.strings.Login_PhoneGenericEmailBody(formattedNumber, errorString, appVersion, systemVersion, locale, mnc).string, from: controller, presentationData: presentationData) + }) + ] + ) controller.present(alertController, in: .window(.root)) } })) @@ -377,6 +414,8 @@ public final class AuthorizationSequencePaymentScreen: ViewControllerComponentCo phoneNumber: String, phoneCodeHash: String, storeProduct: String, + supportEmailAddress: String, + supportEmailSubject: String, back: @escaping () -> Void ) { super.init(component: AuthorizationSequencePaymentScreenComponent( @@ -386,7 +425,9 @@ public final class AuthorizationSequencePaymentScreen: ViewControllerComponentCo presentationData: presentationData, phoneNumber: phoneNumber, phoneCodeHash: phoneCodeHash, - storeProduct: storeProduct + storeProduct: storeProduct, + supportEmailAddress: supportEmailAddress, + supportEmailSubject: supportEmailSubject ), navigationBarAppearance: .transparent, theme: .default, updatedPresentationData: (initial: presentationData, signal: .single(presentationData))) loadServerCountryCodes(accountManager: sharedContext.accountManager, engine: engine, completion: { [weak self] in diff --git a/submodules/TelegramUI/Components/Stars/StarsPurchaseScreen/Sources/StarsPurchaseScreen.swift b/submodules/TelegramUI/Components/Stars/StarsPurchaseScreen/Sources/StarsPurchaseScreen.swift index a727875cea..6a5acba10c 100644 --- a/submodules/TelegramUI/Components/Stars/StarsPurchaseScreen/Sources/StarsPurchaseScreen.swift +++ b/submodules/TelegramUI/Components/Stars/StarsPurchaseScreen/Sources/StarsPurchaseScreen.swift @@ -676,7 +676,7 @@ private final class StarsPurchaseScreenComponent: CombinedComponent { case let .gift(peerId): purpose = .starsGift(peerId: peerId, count: product.count, currency: currency, amount: amount) default: - purpose = .stars(count: product.count, currency: currency, amount: amount, peerId: nil) + purpose = .stars(count: product.count, currency: currency, amount: amount, peerId: self.purpose.commercialPeerId) } let _ = (self.context.engine.payments.canPurchasePremium(purpose: purpose) @@ -1264,6 +1264,21 @@ private extension StarsPurchasePurpose { } } + var commercialPeerId: EnginePeer.Id? { + switch self { + case let .transfer(peerId, _): + return peerId + case let .reactions(peerId, _): + return peerId + case let .subscription(peerId, _, _): + return peerId + case let .sendMessage(peerId, _): + return peerId + default: + return nil + } + } + var requiredStars: Int64? { switch self { case let .topUp(requiredStars, _):