Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
signalapp
GitHub Repository: signalapp/Signal-iOS
Path: blob/main/SignalUI/RecipientPickers/CountryCodeViewController.swift
1 views
//
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//

import Combine
import SignalServiceKit
public import SwiftUI

public protocol CountryCodeViewControllerDelegate: AnyObject {
    func countryCodeViewController(_ vc: CountryCodeViewController, didSelectCountry: PhoneNumberCountry)
}

private class ViewModel: NSObject, ObservableObject {
    let didSelectCountry = PassthroughSubject<PhoneNumberCountry, Never>()
    @Published var countries: [PhoneNumberCountry] = []

    func buildCountries(searchText: String? = nil) {
        countries = PhoneNumberCountry.buildCountries(searchText: searchText)
    }
}

extension ViewModel: UISearchBarDelegate {
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        buildCountries(searchText: searchBar.text)
    }

    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        buildCountries()
    }
}

public class CountryCodeViewController: HostingController<CountryCodePicker> {
    private var didSelectCountrySink: AnyCancellable?

    public var interfaceOrientationMask: UIInterfaceOrientationMask = UIDevice.current.defaultSupportedOrientations

    override public var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        interfaceOrientationMask
    }

    public init(delegate: CountryCodeViewControllerDelegate) {
        let viewModel = ViewModel()
        super.init(wrappedView: CountryCodePicker(viewModel: viewModel))

        let searchController = UISearchController()
        searchController.hidesNavigationBarDuringPresentation = false
        searchController.searchBar.delegate = viewModel
        searchController.searchBar.placeholder = OWSLocalizedString(
            "SEARCH_BYNAMEORNUMBER_PLACEHOLDER_TEXT",
            comment: "Placeholder text indicating the user can search for contacts by name or phone number.",
        )
        self.navigationItem.searchController = searchController

        self.title = OWSLocalizedString("COUNTRYCODE_SELECT_TITLE", comment: "")
        self.navigationItem.rightBarButtonItem = .systemItem(.stop) { [weak self] in
            self?.dismiss(animated: true)
        }

        didSelectCountrySink = viewModel.didSelectCountry.sink { [weak delegate, weak self] country in
            guard let self else { return }
            delegate?.countryCodeViewController(self, didSelectCountry: country)
            self.navigationItem.searchController?.isActive = false
            self.dismiss(animated: true)
        }
    }
}

public struct CountryCodePicker: View {
    @ObservedObject fileprivate var viewModel: ViewModel

    public var body: some View {
        SignalList {
            SignalSection {
                ForEach(viewModel.countries) { country in
                    Button {
                        viewModel.didSelectCountry.send(country)
                    } label: {
                        HStack {
                            Text(country.countryName)
                            Spacer()
                            Text(country.plusPrefixedCallingCode)
                                .foregroundStyle(Color.Signal.secondaryLabel)
                        }
                    }
                    .foregroundStyle(Color.Signal.label)
                }
            }
        }
        .onAppear {
            viewModel.buildCountries()
        }
    }
}