mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
498 lines
15 KiB
Swift
498 lines
15 KiB
Swift
import Foundation
|
|
import Display
|
|
import AsyncDisplayKit
|
|
|
|
private let countryNamesAndCodes: [(String, Int)] = [
|
|
("Jamaica", 1876),
|
|
("Saint Kitts & Nevis", 1869),
|
|
("Trinidad & Tobago", 1868),
|
|
("Saint Vincent & the Grenadines", 1784),
|
|
("Dominica", 1767),
|
|
("Saint Lucia", 1758),
|
|
("Sint Maarten", 1721),
|
|
("American Samoa", 1684),
|
|
("Guam", 1671),
|
|
("Northern Mariana Islands", 1670),
|
|
("Montserrat", 1664),
|
|
("Turks & Caicos Islands", 1649),
|
|
("Grenada", 1473),
|
|
("Bermuda", 1441),
|
|
("Cayman Islands", 1345),
|
|
("US Virgin Islands", 1340),
|
|
("British Virgin Islands", 1284),
|
|
("Antigua & Barbuda", 1268),
|
|
("Anguilla", 1264),
|
|
("Barbados", 1246),
|
|
("Bahamas", 1242),
|
|
("Uzbekistan", 998),
|
|
("Kyrgyzstan", 996),
|
|
("Georgia", 995),
|
|
("Azerbaijan", 994),
|
|
("Turkmenistan", 993),
|
|
("Tajikistan", 992),
|
|
("Nepal", 977),
|
|
("Mongolia", 976),
|
|
("Bhutan", 975),
|
|
("Qatar", 974),
|
|
("Bahrain", 973),
|
|
("Israel", 972),
|
|
("United Arab Emirates", 971),
|
|
("Palestine", 970),
|
|
("Oman", 968),
|
|
("Yemen", 967),
|
|
("Saudi Arabia", 966),
|
|
("Kuwait", 965),
|
|
("Iraq", 964),
|
|
("Syrian Arab Republic", 963),
|
|
("Jordan", 962),
|
|
("Lebanon", 961),
|
|
("Maldives", 960),
|
|
("Taiwan", 886),
|
|
("Bangladesh", 880),
|
|
("Laos", 856),
|
|
("Cambodia", 855),
|
|
("Macau", 853),
|
|
("Hong Kong", 852),
|
|
("North Korea", 850),
|
|
("Marshall Islands", 692),
|
|
("Micronesia", 691),
|
|
("Tokelau", 690),
|
|
("French Polynesia", 689),
|
|
("Tuvalu", 688),
|
|
("New Caledonia", 687),
|
|
("Kiribati", 686),
|
|
("Samoa", 685),
|
|
("Niue", 683),
|
|
("Cook Islands", 682),
|
|
("Wallis & Futuna", 681),
|
|
("Palau", 680),
|
|
("Fiji", 679),
|
|
("Vanuatu", 678),
|
|
("Solomon Islands", 677),
|
|
("Tonga", 676),
|
|
("Papua New Guinea", 675),
|
|
("Nauru", 674),
|
|
("Brunei Darussalam", 673),
|
|
("Norfolk Island", 672),
|
|
("Timor-Leste", 670),
|
|
("Bonaire, Sint Eustatius & Saba", 599),
|
|
("Curaçao", 599),
|
|
("Uruguay", 598),
|
|
("Suriname", 597),
|
|
("Martinique", 596),
|
|
("Paraguay", 595),
|
|
("French Guiana", 594),
|
|
("Ecuador", 593),
|
|
("Guyana", 592),
|
|
("Bolivia", 591),
|
|
("Guadeloupe", 590),
|
|
("Haiti", 509),
|
|
("Saint Pierre & Miquelon", 508),
|
|
("Panama", 507),
|
|
("Costa Rica", 506),
|
|
("Nicaragua", 505),
|
|
("Honduras", 504),
|
|
("El Salvador", 503),
|
|
("Guatemala", 502),
|
|
("Belize", 501),
|
|
("Falkland Islands", 500),
|
|
("Liechtenstein", 423),
|
|
("Slovakia", 421),
|
|
("Czech Republic", 420),
|
|
("Macedonia", 389),
|
|
("Bosnia & Herzegovina", 387),
|
|
("Slovenia", 386),
|
|
("Croatia", 385),
|
|
("Montenegro", 382),
|
|
("Serbia", 381),
|
|
("Ukraine", 380),
|
|
("San Marino", 378),
|
|
("Monaco", 377),
|
|
("Andorra", 376),
|
|
("Belarus", 375),
|
|
("Armenia", 374),
|
|
("Moldova", 373),
|
|
("Estonia", 372),
|
|
("Latvia", 371),
|
|
("Lithuania", 370),
|
|
("Bulgaria", 359),
|
|
("Finland", 358),
|
|
("Cyprus", 357),
|
|
("Malta", 356),
|
|
("Albania", 355),
|
|
("Iceland", 354),
|
|
("Ireland", 353),
|
|
("Luxembourg", 352),
|
|
("Portugal", 351),
|
|
("Gibraltar", 350),
|
|
("Greenland", 299),
|
|
("Faroe Islands", 298),
|
|
("Aruba", 297),
|
|
("Eritrea", 291),
|
|
("Saint Helena", 290),
|
|
("Comoros", 269),
|
|
("Swaziland", 268),
|
|
("Botswana", 267),
|
|
("Lesotho", 266),
|
|
("Malawi", 265),
|
|
("Namibia", 264),
|
|
("Zimbabwe", 263),
|
|
("Réunion", 262),
|
|
("Madagascar", 261),
|
|
("Zambia", 260),
|
|
("Mozambique", 258),
|
|
("Burundi", 257),
|
|
("Uganda", 256),
|
|
("Tanzania", 255),
|
|
("Kenya", 254),
|
|
("Djibouti", 253),
|
|
("Somalia", 252),
|
|
("Ethiopia", 251),
|
|
("Rwanda", 250),
|
|
("Sudan", 249),
|
|
("Seychelles", 248),
|
|
("Saint Helena", 247),
|
|
("Diego Garcia", 246),
|
|
("Guinea-Bissau", 245),
|
|
("Angola", 244),
|
|
("Congo (Dem. Rep.)", 243),
|
|
("Congo (Rep.)", 242),
|
|
("Gabon", 241),
|
|
("Equatorial Guinea", 240),
|
|
("São Tomé & Príncipe", 239),
|
|
("Cape Verde", 238),
|
|
("Cameroon", 237),
|
|
("Central African Rep.", 236),
|
|
("Chad", 235),
|
|
("Nigeria", 234),
|
|
("Ghana", 233),
|
|
("Sierra Leone", 232),
|
|
("Liberia", 231),
|
|
("Mauritius", 230),
|
|
("Benin", 229),
|
|
("Togo", 228),
|
|
("Niger", 227),
|
|
("Burkina Faso", 226),
|
|
("Côte d`Ivoire", 225),
|
|
("Guinea", 224),
|
|
("Mali", 223),
|
|
("Mauritania", 222),
|
|
("Senegal", 221),
|
|
("Gambia", 220),
|
|
("Libya", 218),
|
|
("Tunisia", 216),
|
|
("Algeria", 213),
|
|
("Morocco", 212),
|
|
("South Sudan", 211),
|
|
("Iran", 98),
|
|
("Myanmar", 95),
|
|
("Sri Lanka", 94),
|
|
("Afghanistan", 93),
|
|
("Pakistan", 92),
|
|
("India", 91),
|
|
("Turkey", 90),
|
|
("China", 86),
|
|
("Vietnam", 84),
|
|
("South Korea", 82),
|
|
("Japan", 81),
|
|
("Thailand", 66),
|
|
("Singapore", 65),
|
|
("New Zealand", 64),
|
|
("Philippines", 63),
|
|
("Indonesia", 62),
|
|
("Australia", 61),
|
|
("Malaysia", 60),
|
|
("Venezuela", 58),
|
|
("Colombia", 57),
|
|
("Chile", 56),
|
|
("Brazil", 55),
|
|
("Argentina", 54),
|
|
("Cuba", 53),
|
|
("Mexico", 52),
|
|
("Peru", 51),
|
|
("Germany", 49),
|
|
("Poland", 48),
|
|
("Norway", 47),
|
|
("Sweden", 46),
|
|
("Denmark", 45),
|
|
("United Kingdom", 44),
|
|
("Austria", 43),
|
|
("Switzerland", 41),
|
|
("Romania", 40),
|
|
("Italy", 39),
|
|
("Hungary", 36),
|
|
("Spain", 34),
|
|
("France", 33),
|
|
("Belgium", 32),
|
|
("Netherlands", 31),
|
|
("Greece", 30),
|
|
("South Africa", 27),
|
|
("Egypt", 20),
|
|
("Russian Federation", 7),
|
|
("Kazakhstan", 7),
|
|
("USA", 1),
|
|
("Puerto Rico", 1),
|
|
("Dominican Rep.", 1),
|
|
("Canada", 1)
|
|
]
|
|
|
|
private final class InnerCoutrySearchResultsController: UIViewController, UITableViewDelegate, UITableViewDataSource {
|
|
private let tableView: UITableView
|
|
|
|
var searchResults: [(String, Int)] = [] {
|
|
didSet {
|
|
self.tableView.reloadData()
|
|
}
|
|
}
|
|
|
|
var itemSelected: (((String, Int)) -> Void)?
|
|
|
|
init() {
|
|
self.tableView = UITableView(frame: CGRect(), style: .plain)
|
|
|
|
super.init(nibName: nil, bundle: nil)
|
|
}
|
|
|
|
required init?(coder aDecoder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
|
|
self.view.backgroundColor = .white
|
|
|
|
self.view.addSubview(self.tableView)
|
|
self.tableView.frame = self.view.bounds
|
|
self.tableView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
|
self.tableView.dataSource = self
|
|
self.tableView.delegate = self
|
|
}
|
|
|
|
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
|
return self.searchResults.count
|
|
}
|
|
|
|
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
|
let cell: UITableViewCell
|
|
if let currentCell = tableView.dequeueReusableCell(withIdentifier: "CountryCell") {
|
|
cell = currentCell
|
|
} else {
|
|
cell = UITableViewCell()
|
|
let label = UILabel()
|
|
label.font = Font.medium(17.0)
|
|
cell.accessoryView = label
|
|
}
|
|
cell.textLabel?.text = self.searchResults[indexPath.row].0
|
|
if let label = cell.accessoryView as? UILabel {
|
|
label.text = "+\(self.searchResults[indexPath.row].1)"
|
|
label.sizeToFit()
|
|
}
|
|
return cell
|
|
}
|
|
|
|
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
|
self.itemSelected?(self.searchResults[indexPath.row])
|
|
}
|
|
}
|
|
|
|
private final class InnerCountrySelectionController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchResultsUpdating, UISearchBarDelegate {
|
|
private let tableView: UITableView
|
|
|
|
private let sections: [(String, [(String, Int)])]
|
|
private let sectionTitles: [String]
|
|
|
|
private var searchController: UISearchController!
|
|
private var searchResultsController: InnerCoutrySearchResultsController!
|
|
|
|
var dismiss: (() -> Void)?
|
|
var itemSelected: (((String, Int)) -> Void)?
|
|
|
|
init() {
|
|
self.tableView = UITableView(frame: CGRect(), style: .plain)
|
|
|
|
var sections: [(String, [(String, Int)])] = []
|
|
for (name, code) in countryNamesAndCodes.sorted(by: { lhs, rhs in
|
|
return lhs.0 < rhs.0
|
|
}) {
|
|
let title = name.substring(to: name.index(after: name.startIndex)).uppercased()
|
|
if sections.isEmpty || sections[sections.count - 1].0 != title {
|
|
sections.append((title, []))
|
|
}
|
|
sections[sections.count - 1].1.append((name, code))
|
|
}
|
|
self.sections = sections
|
|
var sectionTitles = sections.map { $0.0 }
|
|
sectionTitles.insert(UITableViewIndexSearch, at: 0)
|
|
self.sectionTitles = sectionTitles
|
|
|
|
super.init(nibName: nil, bundle: nil)
|
|
|
|
self.title = "Select Country"
|
|
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(self.cancelPressed))
|
|
|
|
self.definesPresentationContext = true
|
|
}
|
|
|
|
required init?(coder aDecoder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
|
|
self.view.backgroundColor = .white
|
|
|
|
self.searchResultsController = InnerCoutrySearchResultsController()
|
|
self.searchResultsController.itemSelected = { [weak self] item in
|
|
self?.itemSelected?(item)
|
|
}
|
|
|
|
self.searchController = UISearchController(searchResultsController: self.searchResultsController)
|
|
self.searchController.searchResultsUpdater = self
|
|
self.searchController.dimsBackgroundDuringPresentation = true
|
|
self.searchController.searchBar.delegate = self
|
|
|
|
self.view.addSubview(self.tableView)
|
|
self.tableView.tableHeaderView = self.searchController.searchBar
|
|
self.tableView.dataSource = self
|
|
self.tableView.delegate = self
|
|
|
|
self.tableView.frame = self.view.bounds
|
|
self.view.addSubview(self.tableView)
|
|
}
|
|
|
|
func numberOfSections(in tableView: UITableView) -> Int {
|
|
return self.sections.count
|
|
}
|
|
|
|
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
|
return self.sections[section].1.count
|
|
}
|
|
|
|
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
|
return self.sections[section].0
|
|
}
|
|
|
|
func sectionIndexTitles(for tableView: UITableView) -> [String]? {
|
|
return self.sectionTitles
|
|
}
|
|
|
|
func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int {
|
|
if index == 0 {
|
|
return 0
|
|
} else {
|
|
return max(0, index - 1)
|
|
}
|
|
}
|
|
|
|
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
|
let cell: UITableViewCell
|
|
if let currentCell = tableView.dequeueReusableCell(withIdentifier: "CountryCell") {
|
|
cell = currentCell
|
|
} else {
|
|
cell = UITableViewCell()
|
|
let label = UILabel()
|
|
label.font = Font.medium(17.0)
|
|
cell.accessoryView = label
|
|
}
|
|
cell.textLabel?.text = self.sections[indexPath.section].1[indexPath.row].0
|
|
if let label = cell.accessoryView as? UILabel {
|
|
label.text = "+\(self.sections[indexPath.section].1[indexPath.row].1)"
|
|
label.sizeToFit()
|
|
}
|
|
return cell
|
|
}
|
|
|
|
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
|
self.itemSelected?(self.sections[indexPath.section].1[indexPath.row])
|
|
}
|
|
|
|
func updateSearchResults(for searchController: UISearchController) {
|
|
guard let normalizedQuery = searchController.searchBar.text?.lowercased() else {
|
|
self.searchResultsController.searchResults = []
|
|
return
|
|
}
|
|
|
|
var results: [(String, Int)] = []
|
|
for (_, items) in self.sections {
|
|
for item in items {
|
|
if item.0.lowercased().hasPrefix(normalizedQuery) {
|
|
results.append(item)
|
|
}
|
|
}
|
|
}
|
|
self.searchResultsController.searchResults = results
|
|
}
|
|
|
|
@objc func cancelPressed() {
|
|
self.dismiss?()
|
|
}
|
|
}
|
|
|
|
final class AuthorizationSequenceCountrySelectionController: ViewController {
|
|
private var controllerNode: AuthorizationSequenceCountrySelectionControllerNode {
|
|
return self.displayNode as! AuthorizationSequenceCountrySelectionControllerNode
|
|
}
|
|
|
|
private let innerNavigationController: UINavigationController
|
|
private let innerController: InnerCountrySelectionController
|
|
|
|
var completeWithCountryCode: ((Int) -> Void)?
|
|
|
|
init() {
|
|
self.innerController = InnerCountrySelectionController()
|
|
self.innerNavigationController = UINavigationController(rootViewController: self.innerController)
|
|
|
|
super.init(navigationBarTheme: nil)
|
|
|
|
self.innerController.dismiss = { [weak self] in
|
|
self?.cancelPressed()
|
|
}
|
|
}
|
|
|
|
required init(coder aDecoder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
override public func loadDisplayNode() {
|
|
self.displayNode = AuthorizationSequenceCountrySelectionControllerNode()
|
|
self.displayNodeDidLoad()
|
|
|
|
self.innerNavigationController.willMove(toParentViewController: self)
|
|
self.addChildViewController(self.innerNavigationController)
|
|
self.displayNode.view.addSubview(self.innerNavigationController.view)
|
|
self.innerNavigationController.didMove(toParentViewController: self)
|
|
|
|
self.innerController.itemSelected = { [weak self] _, code in
|
|
self?.completeWithCountryCode?(code)
|
|
self?.controllerNode.animateOut()
|
|
}
|
|
|
|
self.controllerNode.dismiss = { [weak self] in
|
|
self?.presentingViewController?.dismiss(animated: true, completion: nil)
|
|
}
|
|
}
|
|
|
|
override func viewDidAppear(_ animated: Bool) {
|
|
super.viewDidAppear(animated)
|
|
|
|
self.innerNavigationController.viewWillAppear(false)
|
|
self.innerNavigationController.viewDidAppear(false)
|
|
|
|
self.controllerNode.animateIn()
|
|
}
|
|
|
|
override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
|
super.containerLayoutUpdated(layout, transition: transition)
|
|
|
|
self.innerNavigationController.view.frame = CGRect(origin: CGPoint(), size: layout.size)
|
|
self.innerController.view.frame = CGRect(origin: CGPoint(), size: layout.size)
|
|
//self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationBar.frame.maxY, transition: transition)
|
|
}
|
|
|
|
private func cancelPressed() {
|
|
self.controllerNode.animateOut()
|
|
}
|
|
}
|