import Foundation import UIKit import Display import AsyncDisplayKit import Postbox import TelegramCore import SwiftSignalKit import TelegramPresentationData import LegacyComponents import SolidRoundedButtonNode import RMIntro public final class AuthorizationSequenceSplashController: ViewController { private var controllerNode: AuthorizationSequenceSplashControllerNode { return self.displayNode as! AuthorizationSequenceSplashControllerNode } private let accountManager: AccountManager private let account: UnauthorizedAccount private let theme: PresentationTheme private let controller: RMIntroViewController private var validLayout: ContainerViewLayout? var nextPressed: ((PresentationStrings?) -> Void)? private let suggestedLocalization = Promise() private let activateLocalizationDisposable = MetaDisposable() private let startButton: SolidRoundedButtonNode init(accountManager: AccountManager, account: UnauthorizedAccount, theme: PresentationTheme) { self.accountManager = accountManager self.account = account self.theme = theme self.suggestedLocalization.set(.single(nil) |> then(TelegramEngineUnauthorized(account: self.account).localization.currentlySuggestedLocalization(extractKeys: ["Login.ContinueWithLocalization"]))) let suggestedLocalization = self.suggestedLocalization let localizationSignal = SSignal(generator: { subscriber in let disposable = suggestedLocalization.get().start(next: { localization in guard let localization = localization else { return } var continueWithLanguageString: String = "Continue" for entry in localization.extractedEntries { switch entry { case let .string(key, value): if key == "Login.ContinueWithLocalization" { continueWithLanguageString = value } default: break } } if let available = localization.availableLocalizations.first, available.languageCode != "en" { let value = TGSuggestedLocalization(info: TGAvailableLocalization(title: available.title, localizedTitle: available.localizedTitle, code: available.languageCode), continueWithLanguageString: continueWithLanguageString, chooseLanguageString: "Choose Language", chooseLanguageOtherString: "Choose Language", englishLanguageNameString: "English") subscriber.putNext(value) } }, completed: { subscriber.putCompletion() }) return SBlockDisposable(block: { disposable.dispose() }) }) self.controller = RMIntroViewController(backgroundColor: theme.list.plainBackgroundColor, primaryColor: theme.list.itemPrimaryTextColor, buttonColor: theme.intro.startButtonColor, accentColor: theme.list.itemAccentColor, regularDotColor: theme.intro.dotColor, highlightedDotColor: theme.list.itemAccentColor, suggestedLocalizationSignal: localizationSignal) self.startButton = SolidRoundedButtonNode(title: "Start Messaging", theme: SolidRoundedButtonTheme(theme: theme), height: 50.0, cornerRadius: 13.0, gloss: true) super.init(navigationBarPresentationData: nil) self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait) self.statusBar.statusBarStyle = theme.intro.statusBarStyle.style self.controller.startMessaging = { [weak self] in self?.activateLocalization("en") } self.controller.startMessagingInAlternativeLanguage = { [weak self] code in if let code = code { self?.activateLocalization(code) } } self.startButton.pressed = { [weak self] in self?.activateLocalization("en") } self.controller.createStartButton = { [weak self] width in let _ = self?.startButton.updateLayout(width: width, transition: .immediate) return self?.startButton.view } } required init(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } deinit { self.activateLocalizationDisposable.dispose() } public override func loadDisplayNode() { self.displayNode = AuthorizationSequenceSplashControllerNode(theme: self.theme) self.displayNodeDidLoad() } func animateIn() { self.controller.animateIn() } var buttonFrame: CGRect { return self.startButton.frame } var buttonTitle: String { return self.startButton.title ?? "" } var animationSnapshot: UIView? { return self.controller.createAnimationSnapshot() } var textSnaphot: UIView? { return self.controller.createTextSnapshot() } private func addControllerIfNeeded() { if !self.controller.isViewLoaded || self.controller.view.superview == nil { self.displayNode.view.addSubview(self.controller.view) if let layout = self.validLayout { controller.view.frame = CGRect(origin: CGPoint(), size: layout.size) } self.controller.viewDidAppear(false) } } public override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.addControllerIfNeeded() self.controller.viewWillAppear(false) } public override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) controller.viewDidAppear(animated) } public override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) controller.viewWillDisappear(animated) } public override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) controller.viewDidDisappear(animated) } public override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { super.containerLayoutUpdated(layout, transition: transition) self.validLayout = layout let controllerFrame = CGRect(origin: CGPoint(), size: layout.size) self.controller.defaultFrame = controllerFrame self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: 0.0, transition: transition) self.addControllerIfNeeded() if case .immediate = transition { self.controller.view.frame = controllerFrame } else { UIView.animate(withDuration: 0.3, animations: { self.controller.view.frame = controllerFrame }) } } private func activateLocalization(_ code: String) { let currentCode = self.accountManager.transaction { transaction -> String in if let current = transaction.getSharedData(SharedDataKeys.localizationSettings)?.get(LocalizationSettings.self) { return current.primaryComponent.languageCode } else { return "en" } } let suggestedCode = self.suggestedLocalization.get() |> map { localization -> String? in return localization?.availableLocalizations.first?.languageCode } let _ = (combineLatest(currentCode, suggestedCode) |> take(1) |> deliverOnMainQueue).start(next: { [weak self] currentCode, suggestedCode in guard let strongSelf = self else { return } if let suggestedCode = suggestedCode { _ = TelegramEngineUnauthorized(account: strongSelf.account).localization.markSuggestedLocalizationAsSeenInteractively(languageCode: suggestedCode).start() } if currentCode == code { strongSelf.pressNext(strings: nil) return } strongSelf.controller.isEnabled = false strongSelf.startButton.alpha = 0.6 let accountManager = strongSelf.accountManager strongSelf.activateLocalizationDisposable.set(TelegramEngineUnauthorized(account: strongSelf.account).localization.downloadAndApplyLocalization(accountManager: accountManager, languageCode: code).start(completed: { let _ = (accountManager.transaction { transaction -> PresentationStrings? in let localizationSettings: LocalizationSettings? if let current = transaction.getSharedData(SharedDataKeys.localizationSettings)?.get(LocalizationSettings.self) { localizationSettings = current } else { localizationSettings = nil } let stringsValue: PresentationStrings if let localizationSettings = localizationSettings { stringsValue = PresentationStrings(primaryComponent: PresentationStrings.Component(languageCode: localizationSettings.primaryComponent.languageCode, localizedName: localizationSettings.primaryComponent.localizedName, pluralizationRulesCode: localizationSettings.primaryComponent.customPluralizationCode, dict: dictFromLocalization(localizationSettings.primaryComponent.localization)), secondaryComponent: localizationSettings.secondaryComponent.flatMap({ PresentationStrings.Component(languageCode: $0.languageCode, localizedName: $0.localizedName, pluralizationRulesCode: $0.customPluralizationCode, dict: dictFromLocalization($0.localization)) }), groupingSeparator: "") } else { stringsValue = defaultPresentationStrings } return stringsValue } |> deliverOnMainQueue).start(next: { strings in self?.controller.isEnabled = true self?.startButton.alpha = 1.0 self?.pressNext(strings: strings) }) })) }) } private func pressNext(strings: PresentationStrings?) { if let navigationController = self.navigationController, navigationController.viewControllers.last === self { self.nextPressed?(strings) } } }