mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-08 00:21:12 +00:00
Merge commit 'b8a7ca4de1ace9e5f1d097349aa9c8fba2b136e3'
This commit is contained in:
commit
a90d128527
@ -8335,3 +8335,5 @@ Sorry for the inconvenience.";
|
||||
|
||||
"UserInfo.AnonymousNumberLabel" = "anonymous number";
|
||||
"UserInfo.AnonymousNumberInfo" = "This number is not tied to a SIM card and was acquired on [Fragment]().";
|
||||
|
||||
"Login.NewNumber" = "New Number";
|
||||
|
@ -15,7 +15,6 @@ public final class AuthorizationSequenceCodeEntryController: ViewController {
|
||||
|
||||
private let strings: PresentationStrings
|
||||
private let theme: PresentationTheme
|
||||
private let openUrl: (String) -> Void
|
||||
|
||||
public var loginWithCode: ((String) -> Void)?
|
||||
public var signInWithApple: (() -> Void)?
|
||||
@ -38,10 +37,9 @@ public final class AuthorizationSequenceCodeEntryController: ViewController {
|
||||
}
|
||||
}
|
||||
|
||||
public init(presentationData: PresentationData, openUrl: @escaping (String) -> Void, back: @escaping () -> Void) {
|
||||
public init(presentationData: PresentationData, back: @escaping () -> Void) {
|
||||
self.strings = presentationData.strings
|
||||
self.theme = presentationData.theme
|
||||
self.openUrl = openUrl
|
||||
|
||||
super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: AuthorizationSequenceController.navigationBarTheme(theme), strings: NavigationBarStrings(presentationStrings: strings)))
|
||||
|
||||
@ -217,7 +215,7 @@ public final class AuthorizationSequenceCodeEntryController: ViewController {
|
||||
self.loginWithCode?(code)
|
||||
}
|
||||
|
||||
func applyConfirmationCode(_ code: Int) {
|
||||
public func applyConfirmationCode(_ code: Int) {
|
||||
self.controllerNode.updateCode("\(code)")
|
||||
}
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
|
||||
let masterDatacenterId = strongSelf.account.masterDatacenterId
|
||||
let isTestingEnvironment = strongSelf.account.testingEnvironment
|
||||
|
||||
let countryCode = defaultCountryCode()
|
||||
let countryCode = AuthorizationSequenceController.defaultCountryCode()
|
||||
|
||||
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: isTestingEnvironment, masterDatacenterId: masterDatacenterId, contents: .phoneEntry(countryCode: countryCode, number: ""))).start()
|
||||
}
|
||||
@ -275,13 +275,11 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
|
||||
if let currentController = currentController {
|
||||
controller = currentController
|
||||
} else {
|
||||
controller = AuthorizationSequenceCodeEntryController(presentationData: self.presentationData, openUrl: { [weak self] url in
|
||||
self?.openUrl(url)
|
||||
}, back: { [weak self] in
|
||||
controller = AuthorizationSequenceCodeEntryController(presentationData: self.presentationData, back: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let countryCode = defaultCountryCode()
|
||||
let countryCode = AuthorizationSequenceController.defaultCountryCode()
|
||||
|
||||
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .phoneEntry(countryCode: countryCode, number: ""))).start()
|
||||
})
|
||||
@ -542,7 +540,7 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let countryCode = defaultCountryCode()
|
||||
let countryCode = AuthorizationSequenceController.defaultCountryCode()
|
||||
|
||||
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .phoneEntry(countryCode: countryCode, number: ""))).start()
|
||||
})
|
||||
@ -707,7 +705,7 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let countryCode = defaultCountryCode()
|
||||
let countryCode = AuthorizationSequenceController.defaultCountryCode()
|
||||
|
||||
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .phoneEntry(countryCode: countryCode, number: ""))).start()
|
||||
})
|
||||
@ -852,7 +850,7 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let countryCode = defaultCountryCode()
|
||||
let countryCode = AuthorizationSequenceController.defaultCountryCode()
|
||||
|
||||
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .phoneEntry(countryCode: countryCode, number: ""))).start()
|
||||
})
|
||||
@ -912,7 +910,7 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let countryCode = defaultCountryCode()
|
||||
let countryCode = AuthorizationSequenceController.defaultCountryCode()
|
||||
|
||||
let _ = TelegramEngineUnauthorized(account: strongSelf.account).auth.setState(state: UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .phoneEntry(countryCode: countryCode, number: ""))).start()
|
||||
}, displayCancel: displayCancel)
|
||||
@ -1022,7 +1020,7 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
|
||||
if self.otherAccountPhoneNumbers.1.isEmpty {
|
||||
controllers.append(self.splashController())
|
||||
} else {
|
||||
controllers.append(self.phoneEntryController(countryCode: defaultCountryCode(), number: "", splashController: nil))
|
||||
controllers.append(self.phoneEntryController(countryCode: AuthorizationSequenceController.defaultCountryCode(), number: "", splashController: nil))
|
||||
}
|
||||
self.setViewControllers(controllers, animated: !self.viewControllers.isEmpty)
|
||||
}
|
||||
@ -1050,7 +1048,7 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
|
||||
if !self.otherAccountPhoneNumbers.1.isEmpty {
|
||||
controllers.append(self.splashController())
|
||||
}
|
||||
controllers.append(self.phoneEntryController(countryCode: defaultCountryCode(), number: "", splashController: nil))
|
||||
controllers.append(self.phoneEntryController(countryCode: AuthorizationSequenceController.defaultCountryCode(), number: "", splashController: nil))
|
||||
if case let .emailSetupRequired(appleSignInAllowed) = type {
|
||||
self.appleSignInAllowed = appleSignInAllowed
|
||||
controllers.append(self.emailSetupController(number: number, appleSignInAllowed: appleSignInAllowed))
|
||||
@ -1156,30 +1154,30 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
|
||||
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private func defaultCountryCode() -> Int32 {
|
||||
var countryId: String? = nil
|
||||
let networkInfo = CTTelephonyNetworkInfo()
|
||||
if let carrier = networkInfo.subscriberCellularProvider {
|
||||
countryId = carrier.isoCountryCode
|
||||
}
|
||||
public static func defaultCountryCode() -> Int32 {
|
||||
var countryId: String? = nil
|
||||
let networkInfo = CTTelephonyNetworkInfo()
|
||||
if let carrier = networkInfo.subscriberCellularProvider {
|
||||
countryId = carrier.isoCountryCode
|
||||
}
|
||||
|
||||
if countryId == nil {
|
||||
countryId = (Locale.current as NSLocale).object(forKey: .countryCode) as? String
|
||||
}
|
||||
if countryId == nil {
|
||||
countryId = (Locale.current as NSLocale).object(forKey: .countryCode) as? String
|
||||
}
|
||||
|
||||
var countryCode: Int32 = 1
|
||||
var countryCode: Int32 = 1
|
||||
|
||||
if let countryId = countryId {
|
||||
let normalizedId = countryId.uppercased()
|
||||
for (code, idAndName) in countryCodeToIdAndName {
|
||||
if idAndName.0 == normalizedId {
|
||||
countryCode = Int32(code)
|
||||
break
|
||||
if let countryId = countryId {
|
||||
let normalizedId = countryId.uppercased()
|
||||
for (code, idAndName) in countryCodeToIdAndName {
|
||||
if idAndName.0 == normalizedId {
|
||||
countryCode = Int32(code)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return countryCode
|
||||
return countryCode
|
||||
}
|
||||
}
|
||||
|
@ -11,8 +11,9 @@ import AccountContext
|
||||
import CountrySelectionUI
|
||||
import PhoneNumberFormat
|
||||
import DebugSettingsUI
|
||||
import MessageUI
|
||||
|
||||
final class AuthorizationSequencePhoneEntryController: ViewController {
|
||||
public final class AuthorizationSequencePhoneEntryController: ViewController, MFMailComposeViewControllerDelegate {
|
||||
private var controllerNode: AuthorizationSequencePhoneEntryControllerNode {
|
||||
return self.displayNode as! AuthorizationSequencePhoneEntryControllerNode
|
||||
}
|
||||
@ -20,7 +21,7 @@ final class AuthorizationSequencePhoneEntryController: ViewController {
|
||||
private var validLayout: ContainerViewLayout?
|
||||
|
||||
private let sharedContext: SharedAccountContext
|
||||
private var account: UnauthorizedAccount
|
||||
private var account: UnauthorizedAccount?
|
||||
private let isTestingEnvironment: Bool
|
||||
private let otherAccountPhoneNumbers: ((String, AccountRecordId, Bool)?, [(String, AccountRecordId, Bool)])
|
||||
private let network: Network
|
||||
@ -43,14 +44,14 @@ final class AuthorizationSequencePhoneEntryController: ViewController {
|
||||
return self.controllerNode.buttonNode
|
||||
}
|
||||
|
||||
var inProgress: Bool = false {
|
||||
public var inProgress: Bool = false {
|
||||
didSet {
|
||||
self.updateNavigationItems()
|
||||
self.controllerNode.inProgress = self.inProgress
|
||||
self.confirmationController?.inProgress = self.inProgress
|
||||
}
|
||||
}
|
||||
var loginWithNumber: ((String, Bool) -> Void)?
|
||||
public var loginWithNumber: ((String, Bool) -> Void)?
|
||||
var accountUpdated: ((UnauthorizedAccount) -> Void)?
|
||||
|
||||
weak var confirmationController: PhoneConfirmationController?
|
||||
@ -59,7 +60,7 @@ final class AuthorizationSequencePhoneEntryController: ViewController {
|
||||
|
||||
private let hapticFeedback = HapticFeedback()
|
||||
|
||||
init(sharedContext: SharedAccountContext, account: UnauthorizedAccount, isTestingEnvironment: Bool, otherAccountPhoneNumbers: ((String, AccountRecordId, Bool)?, [(String, AccountRecordId, Bool)]), network: Network, presentationData: PresentationData, openUrl: @escaping (String) -> Void, back: @escaping () -> Void) {
|
||||
public init(sharedContext: SharedAccountContext, account: UnauthorizedAccount?, countriesConfiguration: CountriesConfiguration? = nil, isTestingEnvironment: Bool, otherAccountPhoneNumbers: ((String, AccountRecordId, Bool)?, [(String, AccountRecordId, Bool)]), network: Network, presentationData: PresentationData, openUrl: @escaping (String) -> Void, back: @escaping () -> Void) {
|
||||
self.sharedContext = sharedContext
|
||||
self.account = account
|
||||
self.isTestingEnvironment = isTestingEnvironment
|
||||
@ -86,6 +87,10 @@ final class AuthorizationSequencePhoneEntryController: ViewController {
|
||||
if !otherAccountPhoneNumbers.1.isEmpty {
|
||||
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed))
|
||||
}
|
||||
|
||||
if let countriesConfiguration {
|
||||
AuthorizationSequenceCountrySelectionController.setupCountryCodes(countries: countriesConfiguration.countries, codesByPrefix: countriesConfiguration.countriesByPrefix)
|
||||
}
|
||||
}
|
||||
|
||||
required init(coder aDecoder: NSCoder) {
|
||||
@ -113,7 +118,7 @@ final class AuthorizationSequencePhoneEntryController: ViewController {
|
||||
}
|
||||
}
|
||||
|
||||
func updateData(countryCode: Int32, countryName: String?, number: String) {
|
||||
public func updateData(countryCode: Int32, countryName: String?, number: String) {
|
||||
self.currentData = (countryCode, countryName, number)
|
||||
if self.isNodeLoaded {
|
||||
self.controllerNode.codeAndNumber = (countryCode, countryName, number)
|
||||
@ -173,15 +178,23 @@ final class AuthorizationSequencePhoneEntryController: ViewController {
|
||||
self?.nextPressed()
|
||||
}
|
||||
|
||||
loadServerCountryCodes(accountManager: sharedContext.accountManager, engine: TelegramEngineUnauthorized(account: self.account), completion: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.controllerNode.updateCountryCode()
|
||||
}
|
||||
})
|
||||
if let account = self.account {
|
||||
loadServerCountryCodes(accountManager: sharedContext.accountManager, engine: TelegramEngineUnauthorized(account: account), completion: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.controllerNode.updateCountryCode()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
self.controllerNode.updateCountryCode()
|
||||
}
|
||||
}
|
||||
|
||||
public func updateCountryCode() {
|
||||
self.controllerNode.updateCountryCode()
|
||||
}
|
||||
|
||||
private var animatingIn = false
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
override public func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
if self.shouldAnimateIn {
|
||||
@ -197,7 +210,7 @@ final class AuthorizationSequencePhoneEntryController: ViewController {
|
||||
}
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
override public func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
if !self.animatingIn {
|
||||
@ -205,7 +218,7 @@ final class AuthorizationSequencePhoneEntryController: ViewController {
|
||||
}
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
override public func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
|
||||
if let confirmationController = self.confirmationController {
|
||||
@ -213,7 +226,7 @@ final class AuthorizationSequencePhoneEntryController: ViewController {
|
||||
}
|
||||
}
|
||||
|
||||
override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
super.containerLayoutUpdated(layout, transition: transition)
|
||||
|
||||
let hadLayout = self.validLayout != nil
|
||||
@ -287,4 +300,8 @@ final class AuthorizationSequencePhoneEntryController: ViewController {
|
||||
self.controllerNode.animateError()
|
||||
}
|
||||
}
|
||||
|
||||
public func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
|
||||
controller.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ import ManagedAnimationNode
|
||||
|
||||
private final class PhoneAndCountryNode: ASDisplayNode {
|
||||
let strings: PresentationStrings
|
||||
let theme: PresentationTheme
|
||||
|
||||
let countryButton: ASButtonNode
|
||||
let phoneBackground: ASImageNode
|
||||
let phoneInputNode: PhoneInputNode
|
||||
@ -33,6 +35,7 @@ private final class PhoneAndCountryNode: ASDisplayNode {
|
||||
|
||||
init(strings: PresentationStrings, theme: PresentationTheme) {
|
||||
self.strings = strings
|
||||
self.theme = theme
|
||||
|
||||
let inset: CGFloat = 24.0
|
||||
|
||||
@ -119,36 +122,9 @@ private final class PhoneAndCountryNode: ASDisplayNode {
|
||||
|
||||
self.countryButton.addTarget(self, action: #selector(self.countryPressed), forControlEvents: .touchUpInside)
|
||||
|
||||
let processNumberChange: (String) -> Bool = { [weak self] number in
|
||||
guard let strongSelf = self else {
|
||||
return false
|
||||
}
|
||||
if let (country, _) = AuthorizationSequenceCountrySelectionController.lookupCountryIdByNumber(number, preferredCountries: strongSelf.preferredCountryIdForCode) {
|
||||
let flagString = emojiFlagForISOCountryCode(country.id)
|
||||
var localizedName: String = AuthorizationSequenceCountrySelectionController.lookupCountryNameById(country.id, strings: strongSelf.strings) ?? country.name
|
||||
if country.id == "FT" {
|
||||
localizedName = strongSelf.strings.Login_AnonymousNumbers
|
||||
}
|
||||
strongSelf.countryButton.setTitle("\(flagString) \(localizedName)", with: Font.regular(20.0), with: theme.list.itemAccentColor, for: [])
|
||||
strongSelf.hasCountry = true
|
||||
|
||||
let maskFont = Font.with(size: 20.0, design: .regular, traits: [.monospacedNumbers])
|
||||
if let mask = AuthorizationSequenceCountrySelectionController.lookupPatternByNumber(number, preferredCountries: strongSelf.preferredCountryIdForCode).flatMap({ NSAttributedString(string: $0, font: maskFont, textColor: theme.list.itemPlaceholderTextColor) }) {
|
||||
strongSelf.phoneInputNode.numberField.textField.attributedPlaceholder = nil
|
||||
strongSelf.phoneInputNode.mask = mask
|
||||
} else {
|
||||
strongSelf.phoneInputNode.mask = nil
|
||||
strongSelf.phoneInputNode.numberField.textField.attributedPlaceholder = NSAttributedString(string: strings.Login_PhonePlaceholder, font: Font.regular(20.0), textColor: theme.list.itemPlaceholderTextColor)
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
self.phoneInputNode.numberTextUpdated = { [weak self] number in
|
||||
if let strongSelf = self {
|
||||
let _ = processNumberChange(strongSelf.phoneInputNode.number)
|
||||
let _ = strongSelf.processNumberChange(number: strongSelf.phoneInputNode.number)
|
||||
|
||||
if strongSelf.hasCountry {
|
||||
strongSelf.hasNumberUpdated?(!strongSelf.phoneInputNode.codeAndNumber.2.isEmpty)
|
||||
@ -164,7 +140,7 @@ private final class PhoneAndCountryNode: ASDisplayNode {
|
||||
strongSelf.preferredCountryIdForCode[code] = name
|
||||
}
|
||||
|
||||
if processNumberChange(strongSelf.phoneInputNode.number) {
|
||||
if strongSelf.processNumberChange(number: strongSelf.phoneInputNode.number) {
|
||||
} else if let code = Int(code), let name = name, let countryName = countryCodeAndIdToName[CountryCodeAndId(code: code, id: name)] {
|
||||
let flagString = emojiFlagForISOCountryCode(name)
|
||||
var localizedName: String = AuthorizationSequenceCountrySelectionController.lookupCountryNameById(name, strings: strongSelf.strings) ?? countryName
|
||||
@ -222,6 +198,30 @@ private final class PhoneAndCountryNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
func processNumberChange(number: String) -> Bool {
|
||||
if let (country, _) = AuthorizationSequenceCountrySelectionController.lookupCountryIdByNumber(number, preferredCountries: self.preferredCountryIdForCode) {
|
||||
let flagString = emojiFlagForISOCountryCode(country.id)
|
||||
var localizedName: String = AuthorizationSequenceCountrySelectionController.lookupCountryNameById(country.id, strings: self.strings) ?? country.name
|
||||
if country.id == "FT" {
|
||||
localizedName = self.strings.Login_AnonymousNumbers
|
||||
}
|
||||
self.countryButton.setTitle("\(flagString) \(localizedName)", with: Font.regular(20.0), with: self.theme.list.itemAccentColor, for: [])
|
||||
self.hasCountry = true
|
||||
|
||||
let maskFont = Font.with(size: 20.0, design: .regular, traits: [.monospacedNumbers])
|
||||
if let mask = AuthorizationSequenceCountrySelectionController.lookupPatternByNumber(number, preferredCountries: self.preferredCountryIdForCode).flatMap({ NSAttributedString(string: $0, font: maskFont, textColor: self.theme.list.itemPlaceholderTextColor) }) {
|
||||
self.phoneInputNode.numberField.textField.attributedPlaceholder = nil
|
||||
self.phoneInputNode.mask = mask
|
||||
} else {
|
||||
self.phoneInputNode.mask = nil
|
||||
self.phoneInputNode.numberField.textField.attributedPlaceholder = NSAttributedString(string: strings.Login_PhonePlaceholder, font: Font.regular(20.0), textColor: self.theme.list.itemPlaceholderTextColor)
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@objc func countryPressed() {
|
||||
self.selectCountryCode?()
|
||||
}
|
||||
@ -281,7 +281,7 @@ private final class ContactSyncNode: ASDisplayNode {
|
||||
|
||||
final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
|
||||
private let sharedContext: SharedAccountContext
|
||||
private var account: UnauthorizedAccount
|
||||
private var account: UnauthorizedAccount?
|
||||
private let strings: PresentationStrings
|
||||
private let theme: PresentationTheme
|
||||
private let hasOtherAccounts: Bool
|
||||
@ -358,7 +358,7 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
|
||||
return self.proceedNode
|
||||
}
|
||||
|
||||
init(sharedContext: SharedAccountContext, account: UnauthorizedAccount, strings: PresentationStrings, theme: PresentationTheme, debugAction: @escaping () -> Void, hasOtherAccounts: Bool) {
|
||||
init(sharedContext: SharedAccountContext, account: UnauthorizedAccount?, strings: PresentationStrings, theme: PresentationTheme, debugAction: @escaping () -> Void, hasOtherAccounts: Bool) {
|
||||
self.sharedContext = sharedContext
|
||||
self.account = account
|
||||
|
||||
@ -376,14 +376,15 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
|
||||
self.titleNode = ASTextNode()
|
||||
self.titleNode.isUserInteractionEnabled = true
|
||||
self.titleNode.displaysAsynchronously = false
|
||||
self.titleNode.attributedText = NSAttributedString(string: strings.Login_PhoneTitle, font: Font.light(30.0), textColor: theme.list.itemPrimaryTextColor)
|
||||
self.titleNode.attributedText = NSAttributedString(string: account == nil ? strings.Login_NewNumber : strings.Login_PhoneTitle, font: Font.light(30.0), textColor: theme.list.itemPrimaryTextColor)
|
||||
|
||||
self.noticeNode = ASTextNode()
|
||||
self.noticeNode.maximumNumberOfLines = 0
|
||||
self.noticeNode.isUserInteractionEnabled = true
|
||||
self.noticeNode.displaysAsynchronously = false
|
||||
self.noticeNode.lineSpacing = 0.1
|
||||
self.noticeNode.attributedText = NSAttributedString(string: strings.Login_PhoneAndCountryHelp, font: Font.regular(17.0), textColor: theme.list.itemPrimaryTextColor, paragraphAlignment: .center)
|
||||
|
||||
self.noticeNode.attributedText = NSAttributedString(string: account == nil ? strings.ChangePhoneNumberNumber_Help : strings.Login_PhoneAndCountryHelp, font: Font.regular(17.0), textColor: theme.list.itemPrimaryTextColor, paragraphAlignment: .center)
|
||||
|
||||
self.contactSyncNode = ContactSyncNode(theme: theme, strings: strings)
|
||||
|
||||
@ -425,10 +426,12 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
self.tokenEventsDisposable.set((account.updateLoginTokenEvents
|
||||
|> deliverOnMainQueue).start(next: { [weak self] _ in
|
||||
self?.refreshQrToken()
|
||||
}))
|
||||
if let account = account {
|
||||
self.tokenEventsDisposable.set((account.updateLoginTokenEvents
|
||||
|> deliverOnMainQueue).start(next: { [weak self] _ in
|
||||
self?.refreshQrToken()
|
||||
}))
|
||||
}
|
||||
|
||||
self.proceedNode.pressed = { [weak self] in
|
||||
self?.checkPhone?()
|
||||
@ -517,6 +520,7 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
|
||||
|
||||
func updateCountryCode() {
|
||||
self.phoneAndCountryNode.phoneInputNode.codeAndNumber = self.codeAndNumber
|
||||
let _ = self.phoneAndCountryNode.processNumberChange(number: self.phoneAndCountryNode.phoneInputNode.number)
|
||||
}
|
||||
|
||||
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
@ -536,7 +540,10 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
|
||||
|
||||
let animationSize = CGSize(width: 100.0, height: 100.0)
|
||||
let titleSize = self.titleNode.measure(CGSize(width: maximumWidth, height: CGFloat.greatestFiniteMagnitude))
|
||||
let noticeSize = self.noticeNode.measure(CGSize(width: min(274.0, maximumWidth - 28.0), height: CGFloat.greatestFiniteMagnitude))
|
||||
|
||||
let noticeInset: CGFloat = self.account == nil ? 32.0 : 0.0
|
||||
|
||||
let noticeSize = self.noticeNode.measure(CGSize(width: min(274.0 + noticeInset, maximumWidth - 28.0), height: CGFloat.greatestFiniteMagnitude))
|
||||
let proceedHeight = self.proceedNode.updateLayout(width: maximumWidth - inset * 2.0, transition: transition)
|
||||
let proceedSize = CGSize(width: maximumWidth - inset * 2.0, height: proceedHeight)
|
||||
|
||||
@ -625,8 +632,10 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
private func refreshQrToken() {
|
||||
guard let account = self.account else {
|
||||
return
|
||||
}
|
||||
let sharedContext = self.sharedContext
|
||||
let account = self.account
|
||||
let tokenSignal = sharedContext.activeAccountContexts
|
||||
|> castError(ExportAuthTransferTokenError.self)
|
||||
|> take(1)
|
||||
|
@ -198,8 +198,13 @@ public final class AuthorizationSequenceCountrySelectionController: ViewControll
|
||||
return countryCodes
|
||||
}
|
||||
|
||||
public static func setupCountryCodes(countries: [Country], codesByPrefix: [String: (Country, Country.CountryCode)]) {
|
||||
countryCodes = countries
|
||||
countryCodesByPrefix = codesByPrefix
|
||||
}
|
||||
|
||||
public static func lookupCountryNameById(_ id: String, strings: PresentationStrings) -> String? {
|
||||
for country in self.countries() {
|
||||
for country in countryCodes {
|
||||
if id == country.id {
|
||||
let locale = localeWithStrings(strings)
|
||||
if let countryName = locale.localizedString(forRegionCode: id) {
|
||||
@ -254,7 +259,7 @@ public final class AuthorizationSequenceCountrySelectionController: ViewControll
|
||||
}
|
||||
|
||||
public static func lookupCountryIdByCode(_ code: Int) -> String? {
|
||||
for country in self.countries() {
|
||||
for country in countryCodes {
|
||||
for countryCode in country.countryCodes {
|
||||
if countryCode.code == "\(code)" {
|
||||
return country.id
|
||||
|
@ -165,6 +165,7 @@ public final class PhoneInputNode: ASDisplayNode, UITextFieldDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
private var didSetupPlaceholder = false
|
||||
private func updatePlaceholder() {
|
||||
if let mask = self.mask {
|
||||
let mutableMask = NSMutableAttributedString(attributedString: mask)
|
||||
@ -178,7 +179,10 @@ public final class PhoneInputNode: ASDisplayNode, UITextFieldDelegate {
|
||||
} else {
|
||||
self.placeholderNode.attributedText = NSAttributedString(string: "")
|
||||
}
|
||||
let _ = self.placeholderNode.updateLayout(CGSize(width: self.frame.size.width, height: CGFloat.greatestFiniteMagnitude))
|
||||
if !self.frame.size.width.isZero {
|
||||
self.didSetupPlaceholder = true
|
||||
let _ = self.placeholderNode.updateLayout(CGSize(width: self.frame.size.width, height: CGFloat.greatestFiniteMagnitude))
|
||||
}
|
||||
}
|
||||
|
||||
private let fontSize: CGFloat
|
||||
@ -352,4 +356,12 @@ public final class PhoneInputNode: ASDisplayNode, UITextFieldDelegate {
|
||||
|
||||
self.updatePlaceholder()
|
||||
}
|
||||
|
||||
public override func layout() {
|
||||
super.layout()
|
||||
|
||||
if !self.didSetupPlaceholder, self.frame.width > 0.0 {
|
||||
self.updatePlaceholder()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,185 +13,324 @@ import CountrySelectionUI
|
||||
import PhoneNumberFormat
|
||||
import CoreTelephony
|
||||
import MessageUI
|
||||
import AuthorizationUI
|
||||
|
||||
public final class ChangePhoneNumberController: ViewController, MFMailComposeViewControllerDelegate {
|
||||
private var controllerNode: ChangePhoneNumberControllerNode {
|
||||
return self.displayNode as! ChangePhoneNumberControllerNode
|
||||
}
|
||||
public func ChangePhoneNumberController(context: AccountContext) -> ViewController {
|
||||
var dismissImpl: (() -> Void)?
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
private let context: AccountContext
|
||||
let requestDisposable = MetaDisposable()
|
||||
let changePhoneDisposable = MetaDisposable()
|
||||
|
||||
private var currentData: (Int32, String?, String)?
|
||||
private let requestDisposable = MetaDisposable()
|
||||
let controller = AuthorizationSequencePhoneEntryController(sharedContext: context.sharedContext, account: nil, countriesConfiguration: context.currentCountriesConfiguration.with { $0 }, isTestingEnvironment: false, otherAccountPhoneNumbers: (nil, []), network: context.account.network, presentationData: presentationData, openUrl: { _ in }, back: {
|
||||
dismissImpl?()
|
||||
})
|
||||
controller.loginWithNumber = { [weak controller] phoneNumber, _ in
|
||||
controller?.inProgress = true
|
||||
|
||||
var inProgress: Bool = false {
|
||||
didSet {
|
||||
if self.inProgress {
|
||||
let item = UIBarButtonItem(customDisplayNode: ProgressNavigationButtonNode(color: self.presentationData.theme.rootController.navigationBar.accentTextColor))
|
||||
self.navigationItem.rightBarButtonItem = item
|
||||
} else {
|
||||
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Next, style: .done, target: self, action: #selector(self.nextPressed))
|
||||
}
|
||||
self.controllerNode.inProgress = self.inProgress
|
||||
}
|
||||
}
|
||||
var loginWithNumber: ((String) -> Void)?
|
||||
requestDisposable.set((context.engine.accountData.requestChangeAccountPhoneNumberVerification(phoneNumber: phoneNumber)
|
||||
|> deliverOnMainQueue).start(next: { [weak controller] next in
|
||||
controller?.inProgress = false
|
||||
|
||||
private let hapticFeedback = HapticFeedback()
|
||||
var dismissImpl: (() -> Void)?
|
||||
let codeController = AuthorizationSequenceCodeEntryController(presentationData: presentationData, back: {
|
||||
dismissImpl?()
|
||||
})
|
||||
codeController.loginWithCode = { [weak codeController] code in
|
||||
codeController?.inProgress = true
|
||||
|
||||
private var presentationData: PresentationData
|
||||
changePhoneDisposable.set((context.engine.accountData.requestChangeAccountPhoneNumber(phoneNumber: phoneNumber, phoneCodeHash: next.hash, phoneCode: code)
|
||||
|> deliverOnMainQueue).start(error: { [weak codeController] error in
|
||||
if case .invalidCode = error {
|
||||
codeController?.animateError(text: presentationData.strings.Login_WrongCodeError)
|
||||
} else {
|
||||
var resetCode = false
|
||||
let text: String
|
||||
switch error {
|
||||
case .generic:
|
||||
text = presentationData.strings.Login_UnknownError
|
||||
case .invalidCode:
|
||||
resetCode = true
|
||||
text = presentationData.strings.Login_InvalidCodeError
|
||||
case .codeExpired:
|
||||
resetCode = true
|
||||
text = presentationData.strings.Login_CodeExpiredError
|
||||
case .limitExceeded:
|
||||
resetCode = true
|
||||
text = presentationData.strings.Login_CodeFloodError
|
||||
}
|
||||
|
||||
public init(context: AccountContext) {
|
||||
self.context = context
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
if resetCode {
|
||||
codeController?.resetCode()
|
||||
}
|
||||
|
||||
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData))
|
||||
|
||||
self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
|
||||
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
|
||||
|
||||
self.title = self.presentationData.strings.ChangePhoneNumberNumber_Title
|
||||
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Next, style: .done, target: self, action: #selector(self.nextPressed))
|
||||
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)
|
||||
}
|
||||
|
||||
required init(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.requestDisposable.dispose()
|
||||
}
|
||||
|
||||
func updateData(countryCode: Int32, countryName: String, number: String) {
|
||||
if self.currentData == nil || self.currentData! != (countryCode, countryName, number) {
|
||||
self.currentData = (countryCode, countryName, number)
|
||||
if self.isNodeLoaded {
|
||||
self.controllerNode.codeAndNumber = (countryCode, countryName, number)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override public func loadDisplayNode() {
|
||||
self.displayNode = ChangePhoneNumberControllerNode(presentationData: self.presentationData)
|
||||
self.displayNodeDidLoad()
|
||||
self.controllerNode.selectCountryCode = { [weak self] in
|
||||
if let strongSelf = self {
|
||||
let controller = AuthorizationSequenceCountrySelectionController(strings: strongSelf.presentationData.strings, theme: strongSelf.presentationData.theme)
|
||||
controller.completeWithCountryCode = { code, name in
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateData(countryCode: Int32(code), countryName: name, number: strongSelf.controllerNode.codeAndNumber.2)
|
||||
strongSelf.controllerNode.activateInput()
|
||||
codeController?.present(textAlertController(context: context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
}
|
||||
}
|
||||
strongSelf.controllerNode.view.endEditing(true)
|
||||
strongSelf.push(controller)
|
||||
}
|
||||
}
|
||||
}, completed: { [weak codeController] in
|
||||
codeController?.present(OverlayStatusController(theme: presentationData.theme, type: .success), in: .window(.root))
|
||||
|
||||
loadServerCountryCodes(accountManager: self.context.sharedContext.accountManager, engine: self.context.engine, completion: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.controllerNode.updateCountryCode()
|
||||
}
|
||||
})
|
||||
let _ = dismissServerProvidedSuggestion(account: context.account, suggestion: .validatePhoneNumber).start()
|
||||
|
||||
self.navigationBar?.updateBackgroundAlpha(0.0, transition: .immediate)
|
||||
}
|
||||
|
||||
override public func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
self.controllerNode.activateInput()
|
||||
}
|
||||
|
||||
override public func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
self.controllerNode.activateInput()
|
||||
}
|
||||
|
||||
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
super.containerLayoutUpdated(layout, transition: transition)
|
||||
|
||||
self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: 0.0, transition: transition)
|
||||
}
|
||||
|
||||
@objc func nextPressed() {
|
||||
let (code, _, number) = self.controllerNode.codeAndNumber
|
||||
var phoneNumber = number
|
||||
if let code = code {
|
||||
phoneNumber = "\(code)\(phoneNumber)"
|
||||
}
|
||||
if !number.isEmpty {
|
||||
self.inProgress = true
|
||||
self.requestDisposable.set((self.context.engine.accountData.requestChangeAccountPhoneNumberVerification(phoneNumber: self.controllerNode.currentNumber) |> deliverOnMainQueue).start(next: { [weak self] next in
|
||||
if let strongSelf = self {
|
||||
strongSelf.inProgress = false
|
||||
(strongSelf.navigationController as? NavigationController)?.pushViewController(changePhoneNumberCodeController(context: strongSelf.context, phoneNumber: strongSelf.controllerNode.currentNumber, codeData: next))
|
||||
}
|
||||
}, error: { [weak self] error in
|
||||
if let strongSelf = self {
|
||||
strongSelf.inProgress = false
|
||||
|
||||
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
let text: String
|
||||
var actions: [TextAlertAction] = []
|
||||
switch error {
|
||||
case .limitExceeded:
|
||||
text = presentationData.strings.Login_CodeFloodError
|
||||
actions.append(TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {}))
|
||||
case .invalidPhoneNumber:
|
||||
text = presentationData.strings.Login_InvalidPhoneError
|
||||
actions.append(TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {}))
|
||||
case .phoneNumberOccupied:
|
||||
text = presentationData.strings.ChangePhone_ErrorOccupied(formatPhoneNumber(context: strongSelf.context, number: phoneNumber)).string
|
||||
actions.append(TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {}))
|
||||
case .phoneBanned:
|
||||
text = presentationData.strings.Login_PhoneBannedError
|
||||
actions.append(TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_OK, action: {}))
|
||||
actions.append(TextAlertAction(type: .genericAction, title: presentationData.strings.Login_PhoneNumberHelp, action: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let formattedNumber = formatPhoneNumber(context: strongSelf.context, number: number)
|
||||
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"
|
||||
|
||||
strongSelf.presentEmailComposeController(address: "login@stel.com", subject: presentationData.strings.Login_PhoneBannedEmailSubject(formattedNumber).string, body: presentationData.strings.Login_PhoneBannedEmailBody(formattedNumber, appVersion, systemVersion, locale, mnc).string)
|
||||
}))
|
||||
case .generic:
|
||||
text = presentationData.strings.Login_UnknownError
|
||||
actions.append(TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {}))
|
||||
if let navigationController = codeController?.navigationController as? NavigationController {
|
||||
var viewControllers = navigationController.viewControllers
|
||||
viewControllers.removeAll(where: { c in
|
||||
if c is AuthorizationSequencePhoneEntryController {
|
||||
return true
|
||||
} else if c is AuthorizationSequenceCodeEntryController {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
navigationController.setViewControllers(viewControllers, animated: true)
|
||||
}
|
||||
}))
|
||||
}
|
||||
codeController.openFragment = { url in
|
||||
context.sharedContext.applicationBindings.openUrl(url)
|
||||
}
|
||||
codeController.updateData(number: formatPhoneNumber(context: context, number: phoneNumber), email: nil, codeType: next.type, nextType: nil, timeout: next.timeout, termsOfService: nil)
|
||||
dismissImpl = { [weak codeController] in
|
||||
codeController?.dismiss()
|
||||
}
|
||||
controller?.push(codeController)
|
||||
}, error: { [weak controller] error in
|
||||
controller?.inProgress = false
|
||||
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: text, actions: actions), in: .window(.root))
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
self.hapticFeedback.error()
|
||||
self.controllerNode.animateError()
|
||||
}
|
||||
let text: String
|
||||
var actions: [TextAlertAction] = []
|
||||
switch error {
|
||||
case .limitExceeded:
|
||||
text = presentationData.strings.Login_CodeFloodError
|
||||
actions.append(TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {}))
|
||||
case .invalidPhoneNumber:
|
||||
text = presentationData.strings.Login_InvalidPhoneError
|
||||
actions.append(TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {}))
|
||||
case .phoneNumberOccupied:
|
||||
text = presentationData.strings.ChangePhone_ErrorOccupied(formatPhoneNumber(context: context, number: phoneNumber)).string
|
||||
actions.append(TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {}))
|
||||
case .phoneBanned:
|
||||
text = presentationData.strings.Login_PhoneBannedError
|
||||
actions.append(TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {}))
|
||||
actions.append(TextAlertAction(type: .genericAction, title: presentationData.strings.Login_PhoneNumberHelp, action: { [weak controller] in
|
||||
let formattedNumber = formatPhoneNumber(context: context, number: 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"
|
||||
|
||||
if MFMailComposeViewController.canSendMail() {
|
||||
let composeController = MFMailComposeViewController()
|
||||
composeController.setToRecipients(["login@stel.com"])
|
||||
composeController.setSubject(presentationData.strings.Login_PhoneBannedEmailSubject(formattedNumber).string)
|
||||
composeController.setMessageBody(presentationData.strings.Login_PhoneBannedEmailBody(formattedNumber, appVersion, systemVersion, locale, mnc).string, isHTML: false)
|
||||
composeController.mailComposeDelegate = controller
|
||||
|
||||
controller?.view.window?.rootViewController?.present(composeController, animated: true, completion: nil)
|
||||
} 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))
|
||||
}
|
||||
}))
|
||||
case .generic:
|
||||
text = presentationData.strings.Login_UnknownError
|
||||
actions.append(TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {}))
|
||||
}
|
||||
|
||||
controller?.present(textAlertController(context: context, title: nil, text: text, actions: actions), in: .window(.root))
|
||||
}))
|
||||
}
|
||||
|
||||
private func presentEmailComposeController(address: String, subject: String, body: String) {
|
||||
if MFMailComposeViewController.canSendMail() {
|
||||
let composeController = MFMailComposeViewController()
|
||||
composeController.setToRecipients([address])
|
||||
composeController.setSubject(subject)
|
||||
composeController.setMessageBody(body, isHTML: false)
|
||||
composeController.mailComposeDelegate = self
|
||||
|
||||
self.view.window?.rootViewController?.present(composeController, animated: true, completion: nil)
|
||||
} else {
|
||||
self.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: self.presentationData), title: nil, text: self.presentationData.strings.Login_EmailNotConfiguredError, actions: [TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
}
|
||||
dismissImpl = { [weak controller] in
|
||||
controller?.dismiss()
|
||||
}
|
||||
|
||||
public func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
|
||||
controller.dismiss(animated: true, completion: nil)
|
||||
Queue.mainQueue().justDispatch {
|
||||
controller.updateData(countryCode: AuthorizationSequenceController.defaultCountryCode(), countryName: nil, number: "")
|
||||
controller.updateCountryCode()
|
||||
}
|
||||
|
||||
return controller
|
||||
}
|
||||
|
||||
//public final class ChangePhoneNumberController: ViewController, MFMailComposeViewControllerDelegate {
|
||||
// private var controllerNode: ChangePhoneNumberControllerNode {
|
||||
// return self.displayNode as! ChangePhoneNumberControllerNode
|
||||
// }
|
||||
//
|
||||
// private let context: AccountContext
|
||||
//
|
||||
// private var currentData: (Int32, String?, String)?
|
||||
// private let requestDisposable = MetaDisposable()
|
||||
//
|
||||
// var inProgress: Bool = false {
|
||||
// didSet {
|
||||
// if self.inProgress {
|
||||
// let item = UIBarButtonItem(customDisplayNode: ProgressNavigationButtonNode(color: self.presentationData.theme.rootController.navigationBar.accentTextColor))
|
||||
// self.navigationItem.rightBarButtonItem = item
|
||||
// } else {
|
||||
// self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Next, style: .done, target: self, action: #selector(self.nextPressed))
|
||||
// }
|
||||
// self.controllerNode.inProgress = self.inProgress
|
||||
// }
|
||||
// }
|
||||
// var loginWithNumber: ((String) -> Void)?
|
||||
//
|
||||
// private let hapticFeedback = HapticFeedback()
|
||||
//
|
||||
// private var presentationData: PresentationData
|
||||
//
|
||||
// public init(context: AccountContext) {
|
||||
// self.context = context
|
||||
// self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
//
|
||||
// super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData))
|
||||
//
|
||||
// self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
|
||||
// self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
|
||||
//
|
||||
// self.title = self.presentationData.strings.ChangePhoneNumberNumber_Title
|
||||
// self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Next, style: .done, target: self, action: #selector(self.nextPressed))
|
||||
// self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)
|
||||
// }
|
||||
//
|
||||
// required init(coder aDecoder: NSCoder) {
|
||||
// fatalError("init(coder:) has not been implemented")
|
||||
// }
|
||||
//
|
||||
// deinit {
|
||||
// self.requestDisposable.dispose()
|
||||
// }
|
||||
//
|
||||
// func updateData(countryCode: Int32, countryName: String, number: String) {
|
||||
// if self.currentData == nil || self.currentData! != (countryCode, countryName, number) {
|
||||
// self.currentData = (countryCode, countryName, number)
|
||||
// if self.isNodeLoaded {
|
||||
// self.controllerNode.codeAndNumber = (countryCode, countryName, number)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override public func loadDisplayNode() {
|
||||
// self.displayNode = ChangePhoneNumberControllerNode(presentationData: self.presentationData)
|
||||
// self.displayNodeDidLoad()
|
||||
// self.controllerNode.selectCountryCode = { [weak self] in
|
||||
// if let strongSelf = self {
|
||||
// let controller = AuthorizationSequenceCountrySelectionController(strings: strongSelf.presentationData.strings, theme: strongSelf.presentationData.theme)
|
||||
// controller.completeWithCountryCode = { code, name in
|
||||
// if let strongSelf = self {
|
||||
// strongSelf.updateData(countryCode: Int32(code), countryName: name, number: strongSelf.controllerNode.codeAndNumber.2)
|
||||
// strongSelf.controllerNode.activateInput()
|
||||
// }
|
||||
// }
|
||||
// strongSelf.controllerNode.view.endEditing(true)
|
||||
// strongSelf.push(controller)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// loadServerCountryCodes(accountManager: self.context.sharedContext.accountManager, engine: self.context.engine, completion: { [weak self] in
|
||||
// if let strongSelf = self {
|
||||
// strongSelf.controllerNode.updateCountryCode()
|
||||
// }
|
||||
// })
|
||||
//
|
||||
// self.navigationBar?.updateBackgroundAlpha(0.0, transition: .immediate)
|
||||
// }
|
||||
//
|
||||
// override public func viewWillAppear(_ animated: Bool) {
|
||||
// super.viewWillAppear(animated)
|
||||
//
|
||||
// self.controllerNode.activateInput()
|
||||
// }
|
||||
//
|
||||
// override public func viewDidAppear(_ animated: Bool) {
|
||||
// super.viewDidAppear(animated)
|
||||
//
|
||||
// self.controllerNode.activateInput()
|
||||
// }
|
||||
//
|
||||
// override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
// super.containerLayoutUpdated(layout, transition: transition)
|
||||
//
|
||||
// self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: 0.0, transition: transition)
|
||||
// }
|
||||
//
|
||||
// @objc func nextPressed() {
|
||||
// let (code, _, number) = self.controllerNode.codeAndNumber
|
||||
// var phoneNumber = number
|
||||
// if let code = code {
|
||||
// phoneNumber = "\(code)\(phoneNumber)"
|
||||
// }
|
||||
// if !number.isEmpty {
|
||||
// self.inProgress = true
|
||||
// self.requestDisposable.set((self.context.engine.accountData.requestChangeAccountPhoneNumberVerification(phoneNumber: self.controllerNode.currentNumber) |> deliverOnMainQueue).start(next: { [weak self] next in
|
||||
// if let strongSelf = self {
|
||||
// strongSelf.inProgress = false
|
||||
// (strongSelf.navigationController as? NavigationController)?.pushViewController(changePhoneNumberCodeController(context: strongSelf.context, phoneNumber: strongSelf.controllerNode.currentNumber, codeData: next))
|
||||
// }
|
||||
// }, error: { [weak self] error in
|
||||
// if let strongSelf = self {
|
||||
// strongSelf.inProgress = false
|
||||
//
|
||||
// let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
||||
//
|
||||
// let text: String
|
||||
// var actions: [TextAlertAction] = []
|
||||
// switch error {
|
||||
// case .limitExceeded:
|
||||
// text = presentationData.strings.Login_CodeFloodError
|
||||
// actions.append(TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {}))
|
||||
// case .invalidPhoneNumber:
|
||||
// text = presentationData.strings.Login_InvalidPhoneError
|
||||
// actions.append(TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {}))
|
||||
// case .phoneNumberOccupied:
|
||||
// text = presentationData.strings.ChangePhone_ErrorOccupied(formatPhoneNumber(context: strongSelf.context, number: phoneNumber)).string
|
||||
// actions.append(TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {}))
|
||||
// case .phoneBanned:
|
||||
// text = presentationData.strings.Login_PhoneBannedError
|
||||
// actions.append(TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_OK, action: {}))
|
||||
// actions.append(TextAlertAction(type: .genericAction, title: presentationData.strings.Login_PhoneNumberHelp, action: { [weak self] in
|
||||
// guard let strongSelf = self else {
|
||||
// return
|
||||
// }
|
||||
// let formattedNumber = formatPhoneNumber(context: strongSelf.context, number: number)
|
||||
// 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"
|
||||
//
|
||||
// strongSelf.presentEmailComposeController(address: "login@stel.com", subject: presentationData.strings.Login_PhoneBannedEmailSubject(formattedNumber).string, body: presentationData.strings.Login_PhoneBannedEmailBody(formattedNumber, appVersion, systemVersion, locale, mnc).string)
|
||||
// }))
|
||||
// case .generic:
|
||||
// text = presentationData.strings.Login_UnknownError
|
||||
// actions.append(TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {}))
|
||||
// }
|
||||
//
|
||||
// strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: text, actions: actions), in: .window(.root))
|
||||
// }
|
||||
// }))
|
||||
// } else {
|
||||
// self.hapticFeedback.error()
|
||||
// self.controllerNode.animateError()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private func presentEmailComposeController(address: String, subject: String, body: String) {
|
||||
// if MFMailComposeViewController.canSendMail() {
|
||||
// let composeController = MFMailComposeViewController()
|
||||
// composeController.setToRecipients([address])
|
||||
// composeController.setSubject(subject)
|
||||
// composeController.setMessageBody(body, isHTML: false)
|
||||
// composeController.mailComposeDelegate = self
|
||||
//
|
||||
// self.view.window?.rootViewController?.present(composeController, animated: true, completion: nil)
|
||||
// } else {
|
||||
// self.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: self.presentationData), title: nil, text: self.presentationData.strings.Login_EmailNotConfiguredError, actions: [TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
|
||||
// controller.dismiss(animated: true, completion: nil)
|
||||
// }
|
||||
//}
|
||||
|
@ -1,153 +0,0 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import AsyncDisplayKit
|
||||
import TelegramCore
|
||||
import TelegramPresentationData
|
||||
import TextFormat
|
||||
import AccountContext
|
||||
import AlertUI
|
||||
import PresentationDataUtils
|
||||
import AppBundle
|
||||
import Markdown
|
||||
import PhoneNumberFormat
|
||||
|
||||
private final class ChangePhoneNumberIntroControllerNode: ASDisplayNode {
|
||||
var presentationData: PresentationData
|
||||
|
||||
let iconNode: ASImageNode
|
||||
let labelNode: ASTextNode
|
||||
let buttonNode: HighlightableButtonNode
|
||||
|
||||
var dismiss: (() -> Void)?
|
||||
var action: (() -> Void)?
|
||||
|
||||
init(presentationData: PresentationData) {
|
||||
self.presentationData = presentationData
|
||||
|
||||
self.iconNode = ASImageNode()
|
||||
self.labelNode = ASTextNode()
|
||||
self.buttonNode = HighlightableButtonNode()
|
||||
|
||||
super.init()
|
||||
|
||||
self.setViewBlock({
|
||||
return UITracingLayerView()
|
||||
})
|
||||
|
||||
self.iconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Settings/ChangePhoneIntroIcon"), color: presentationData.theme.list.freeMonoIconColor)
|
||||
let textColor = self.presentationData.theme.list.freeTextColor
|
||||
self.labelNode.attributedText = parseMarkdownIntoAttributedString(self.presentationData.strings.PhoneNumberHelp_Help, attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: Font.regular(14.0), textColor: textColor), bold: MarkdownAttributeSet(font: Font.semibold(14.0), textColor: textColor), link: MarkdownAttributeSet(font: Font.regular(14.0), textColor: textColor), linkAttribute: { _ in return nil }), textAlignment: .center)
|
||||
self.buttonNode.setTitle(self.presentationData.strings.PhoneNumberHelp_ChangeNumber, with: Font.regular(19.0), with: self.presentationData.theme.list.itemAccentColor, for: .normal)
|
||||
self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside)
|
||||
|
||||
self.addSubnode(self.iconNode)
|
||||
self.addSubnode(self.labelNode)
|
||||
self.addSubnode(self.buttonNode)
|
||||
|
||||
self.backgroundColor = self.presentationData.theme.list.blocksBackgroundColor
|
||||
}
|
||||
|
||||
func animateIn() {
|
||||
self.layer.animatePosition(from: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), to: self.layer.position, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
}
|
||||
|
||||
func animateOut() {
|
||||
self.layer.animatePosition(from: self.layer.position, to: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), duration: 0.2, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false, completion: { [weak self] _ in
|
||||
if let strongSelf = self {
|
||||
strongSelf.dismiss?()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
var insets = layout.insets(options: [.statusBar])
|
||||
insets.top += navigationBarHeight
|
||||
let availableHeight = layout.size.height - insets.top - insets.bottom
|
||||
|
||||
let largeScreen = availableHeight >= 420.0
|
||||
let contentHeight: CGFloat = largeScreen ? 420.0 : 400.0
|
||||
|
||||
let iconSize = self.iconNode.measure(CGSize(width: 400.0, height: 400.0))
|
||||
let labelSize = self.labelNode.updateLayout(CGSize(width: 295.0, height: CGFloat.greatestFiniteMagnitude))
|
||||
let buttonSize = self.buttonNode.measure(CGSize(width: 295.0, height: CGFloat.greatestFiniteMagnitude))
|
||||
|
||||
transition.updateFrame(node: self.iconNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - iconSize.width) / 2.0), y: insets.top + floor((availableHeight - contentHeight) / 2.0) + floor(iconSize.height * (largeScreen ? CGFloat(0.2) : CGFloat(0.5)))), size: iconSize))
|
||||
|
||||
transition.updateFrame(node: self.labelNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - labelSize.width) / 2.0), y: insets.top + floor((availableHeight - contentHeight) / 2.0) + floor((contentHeight - labelSize.height) / 2.0) + floor((contentHeight - iconSize.height - buttonSize.height) * 0.11)), size: labelSize))
|
||||
|
||||
transition.updateFrame(node: self.buttonNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - buttonSize.width) / 2.0), y: insets.top + floor((availableHeight - contentHeight) / 2.0) + contentHeight - buttonSize.height), size: buttonSize))
|
||||
}
|
||||
|
||||
@objc func buttonPressed() {
|
||||
self.action?()
|
||||
}
|
||||
}
|
||||
|
||||
public final class ChangePhoneNumberIntroController: ViewController {
|
||||
private let context: AccountContext
|
||||
private var didPlayPresentationAnimation = false
|
||||
|
||||
private var presentationData: PresentationData
|
||||
|
||||
public init(context: AccountContext, phoneNumber: String) {
|
||||
self.context = context
|
||||
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData))
|
||||
|
||||
self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
|
||||
|
||||
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
|
||||
|
||||
let formattedPhone = formatPhoneNumber(context: context, number: phoneNumber)
|
||||
self.title = formattedPhone
|
||||
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)
|
||||
//self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(self.cancelPressed))
|
||||
}
|
||||
|
||||
required init(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public override func loadDisplayNode() {
|
||||
self.displayNode = ChangePhoneNumberIntroControllerNode(presentationData: self.presentationData)
|
||||
(self.displayNode as! ChangePhoneNumberIntroControllerNode).dismiss = { [weak self] in
|
||||
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||
}
|
||||
(self.displayNode as! ChangePhoneNumberIntroControllerNode).action = { [weak self] in
|
||||
self?.proceed()
|
||||
}
|
||||
self.displayNodeDidLoad()
|
||||
|
||||
self.navigationBar?.updateBackgroundAlpha(0.0, transition: .immediate)
|
||||
}
|
||||
|
||||
public override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
/*if !self.didPlayPresentationAnimation {
|
||||
self.didPlayPresentationAnimation = true
|
||||
(self.displayNode as! ChangePhoneNumberIntroControllerNode).animateIn()
|
||||
}*/
|
||||
}
|
||||
|
||||
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
super.containerLayoutUpdated(layout, transition: transition)
|
||||
|
||||
(self.displayNode as! ChangePhoneNumberIntroControllerNode).containerLayoutUpdated(layout, navigationBarHeight: self.navigationLayout(layout: layout).navigationFrame.maxY, transition: transition)
|
||||
}
|
||||
|
||||
@objc func cancelPressed() {
|
||||
(self.displayNode as! ChangePhoneNumberIntroControllerNode).animateOut()
|
||||
}
|
||||
|
||||
func proceed() {
|
||||
self.present(textAlertController(context: self.context, title: nil, text: self.presentationData.strings.PhoneNumberHelp_Alert, actions: [TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: self.presentationData.strings.TwoFactorSetup_Email_Action, action: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
(strongSelf.navigationController as? NavigationController)?.replaceTopController(ChangePhoneNumberController(context: strongSelf.context), animated: true)
|
||||
}
|
||||
})]), in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
}
|
||||
}
|
@ -1203,7 +1203,7 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting
|
||||
var dismissCodeControllerImpl: (() -> Void)?
|
||||
var presentControllerImpl: ((ViewController) -> Void)?
|
||||
|
||||
let codeController = AuthorizationSequenceCodeEntryController(presentationData: presentationData, openUrl: { _ in }, back: {
|
||||
let codeController = AuthorizationSequenceCodeEntryController(presentationData: presentationData, back: {
|
||||
dismissCodeControllerImpl?()
|
||||
})
|
||||
|
||||
|
@ -28,6 +28,7 @@ import Markdown
|
||||
import WebUI
|
||||
import BotPaymentsUI
|
||||
import PremiumUI
|
||||
import AuthorizationUI
|
||||
|
||||
private func defaultNavigationForPeerId(_ peerId: PeerId?, navigation: ChatControllerInteractionNavigateToPeer) -> ChatControllerInteractionNavigateToPeer {
|
||||
if case .default = navigation {
|
||||
@ -223,7 +224,9 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
|
||||
dismissInput()
|
||||
present(ProxyServerActionSheetController(context: context, server: server), nil)
|
||||
case let .confirmationCode(code):
|
||||
if let topController = navigationController?.topViewController as? ChangePhoneNumberCodeController {
|
||||
if let topController = navigationController?.topViewController as? AuthorizationSequenceCodeEntryController {
|
||||
topController.applyConfirmationCode(code)
|
||||
} else if let topController = navigationController?.topViewController as? ChangePhoneNumberCodeController {
|
||||
topController.applyCode(code)
|
||||
} else {
|
||||
var found = false
|
||||
|
Loading…
x
Reference in New Issue
Block a user