diff --git a/Tusker/Screens/Onboarding/InstanceSelectorTableViewController.swift b/Tusker/Screens/Onboarding/InstanceSelectorTableViewController.swift index fecc7125..5f98b37e 100644 --- a/Tusker/Screens/Onboarding/InstanceSelectorTableViewController.swift +++ b/Tusker/Screens/Onboarding/InstanceSelectorTableViewController.swift @@ -29,6 +29,8 @@ class InstanceSelectorTableViewController: UITableViewController { var urlHandler: AnyCancellable? var currentQuery: String? + private var activityIndicator: UIActivityIndicatorView! + override var supportedInterfaceOrientations: UIInterfaceOrientationMask { if UIDevice.current.userInterfaceIdiom == .phone { return .portrait @@ -56,9 +58,9 @@ class InstanceSelectorTableViewController: UITableViewController { navigationItem.scrollEdgeAppearance = appearance tableView.register(UINib(nibName: "InstanceTableViewCell", bundle: .main), forCellReuseIdentifier: instanceCell) - tableView.rowHeight = UITableView.automaticDimension tableView.estimatedRowHeight = 120 + createActivityIndicatorHeader() dataSource = DataSource(tableView: tableView, cellProvider: { (tableView, indexPath, item) -> UITableViewCell? in switch item { @@ -78,12 +80,19 @@ class InstanceSelectorTableViewController: UITableViewController { searchController.obscuresBackgroundDuringPresentation = false searchController.searchBar.searchTextField.autocapitalizationType = .none navigationItem.searchController = searchController + navigationItem.hidesSearchBarWhenScrolling = false definesPresentationContext = true urlHandler = urlCheckerSubject - .debounce(for: .seconds(1), scheduler: RunLoop.main) .compactMap { $0?.trimmingCharacters(in: .whitespacesAndNewlines) } - .sink(receiveValue: updateSpecificInstance) + .map { [weak self] (s) -> String in + if !s.isEmpty { + self?.activityIndicator.startAnimating() + } + return s + } + .debounce(for: .seconds(1), scheduler: RunLoop.main) + .sink { [weak self] in self?.updateSpecificInstance(domain: $0) } loadRecommendedInstances() } @@ -117,6 +126,8 @@ class InstanceSelectorTableViewController: UITableViewController { } private func updateSpecificInstance(domain: String) { + activityIndicator.startAnimating() + let components = parseURLComponents(input: domain) let url = components.url! @@ -138,7 +149,13 @@ class InstanceSelectorTableViewController: UITableViewController { snapshot.appendItems([.selected(url, instance)], toSection: .selected) DispatchQueue.main.async { - self.dataSource.apply(snapshot) + self.dataSource.apply(snapshot) { + self.activityIndicator.stopAnimating() + } + } + } else { + DispatchQueue.main.async { + self.activityIndicator.stopAnimating() } } } @@ -158,6 +175,28 @@ class InstanceSelectorTableViewController: UITableViewController { } } + private func createActivityIndicatorHeader() { + let header = UITableViewHeaderFooterView() + header.translatesAutoresizingMaskIntoConstraints = false + header.contentView.backgroundColor = .secondarySystemBackground + + activityIndicator = UIActivityIndicatorView(style: .large) + activityIndicator.translatesAutoresizingMaskIntoConstraints = false + header.contentView.addSubview(activityIndicator) + + NSLayoutConstraint.activate([ + activityIndicator.centerXAnchor.constraint(equalTo: header.contentView.centerXAnchor), + activityIndicator.topAnchor.constraint(equalTo: header.contentView.topAnchor, constant: 4), + activityIndicator.bottomAnchor.constraint(equalTo: header.contentView.bottomAnchor, constant: -4), + ]) + + let fittingSize = CGSize(width: tableView.bounds.width - (tableView.safeAreaInsets.left + tableView.safeAreaInsets.right), height: 0) + let size = header.systemLayoutSizeFitting(fittingSize, withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel) + header.frame = CGRect(origin: .zero, size: size) + + tableView.tableHeaderView = header + } + private func showRecommendationsError(_ error: Client.Error) { let footer = UITableViewHeaderFooterView() footer.translatesAutoresizingMaskIntoConstraints = false