143 lines
5.1 KiB
Swift
143 lines
5.1 KiB
Swift
//
|
|
// SelectActivityVC.swift
|
|
// QuickLocation
|
|
//
|
|
|
|
import UIKit
|
|
import RxSwift
|
|
import RxCocoa
|
|
import Kingfisher
|
|
|
|
final class SelectActivityCell: UITableViewCell {
|
|
static let reuseId = "SelectActivityCell"
|
|
|
|
private let iconView = UIImageView()
|
|
|
|
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
|
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
|
iconView.contentMode = .scaleAspectFill
|
|
iconView.layer.cornerRadius = 10
|
|
iconView.clipsToBounds = true
|
|
contentView.addSubview(iconView)
|
|
iconView.layoutChain.left(16).centerY().width(40).height(40)
|
|
textLabel?.layoutChain.leftToRightOfView(iconView, offset: 12).centerY().right(16)
|
|
selectionStyle = .default
|
|
}
|
|
|
|
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
|
|
|
func configure(item: AppCatalogItem) {
|
|
textLabel?.text = item.name
|
|
textLabel?.font = .systemFont(ofSize: 16, weight: .medium)
|
|
textLabel?.textColor = UIColor(hexStr: "#293445")
|
|
AppCatalogStore.setIcon(for: iconView, item: item)
|
|
}
|
|
|
|
override func prepareForReuse() {
|
|
super.prepareForReuse()
|
|
iconView.kf.cancelDownloadTask()
|
|
iconView.image = nil
|
|
}
|
|
}
|
|
|
|
final class SelectActivityVC: BaseViewController {
|
|
var onSelect: ((AppCatalogItem) -> Void)?
|
|
|
|
private let searchField = UITextField()
|
|
private let tableView = UITableView(frame: .zero, style: .plain)
|
|
private let activityIndicator = UIActivityIndicatorView(style: .medium)
|
|
private var items: [AppCatalogItem] = AppCatalogStore.sharedItems
|
|
private var searchTask: Task<Void, Never>?
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
view.backgroundColor = .white
|
|
title = "选取应用"
|
|
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "取消", style: .plain, target: self, action: #selector(cancel))
|
|
|
|
searchField.placeholder = "搜索应用"
|
|
searchField.borderStyle = .roundedRect
|
|
searchField.font = .systemFont(ofSize: 15)
|
|
searchField.clearButtonMode = .whileEditing
|
|
searchField.returnKeyType = .search
|
|
searchField.addTarget(self, action: #selector(searchChanged), for: .editingChanged)
|
|
view.addSubview(searchField)
|
|
searchField.layoutChain.top(12).left(16).right(16).height(40)
|
|
|
|
activityIndicator.hidesWhenStopped = true
|
|
view.addSubview(activityIndicator)
|
|
activityIndicator.layoutChain.centerX().topToBottomOfView(searchField, offset: 8)
|
|
|
|
tableView.register(SelectActivityCell.self, forCellReuseIdentifier: SelectActivityCell.reuseId)
|
|
tableView.dataSource = self
|
|
tableView.delegate = self
|
|
tableView.rowHeight = 56
|
|
tableView.keyboardDismissMode = .onDrag
|
|
view.addSubview(tableView)
|
|
tableView.layoutChain.topToBottomOfView(searchField, offset: 12).edgesHorzontal().bottom()
|
|
}
|
|
|
|
@objc private func cancel() {
|
|
dismiss(animated: true)
|
|
}
|
|
|
|
@objc private func searchChanged() {
|
|
let query = searchField.text ?? ""
|
|
searchTask?.cancel()
|
|
|
|
let trimmed = query.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
if trimmed.isEmpty {
|
|
activityIndicator.stopAnimating()
|
|
items = AppCatalogStore.sharedItems
|
|
tableView.reloadData()
|
|
return
|
|
}
|
|
|
|
let localHits = AppCatalogStore.search(query)
|
|
items = localHits
|
|
tableView.reloadData()
|
|
activityIndicator.startAnimating()
|
|
|
|
searchTask = Task { [weak self] in
|
|
try? await Task.sleep(nanoseconds: 300_000_000)
|
|
guard let self, !Task.isCancelled else { return }
|
|
do {
|
|
let remote = try await ITunesSearchService.search(term: trimmed)
|
|
guard !Task.isCancelled else { return }
|
|
await MainActor.run {
|
|
self.activityIndicator.stopAnimating()
|
|
self.items = ITunesSearchService.mergedResults(local: localHits, remote: remote)
|
|
self.tableView.reloadData()
|
|
}
|
|
} catch {
|
|
await MainActor.run {
|
|
self.activityIndicator.stopAnimating()
|
|
if self.items.isEmpty {
|
|
self.items = localHits
|
|
self.tableView.reloadData()
|
|
}
|
|
DLToast.show(text: "搜索失败,请检查网络")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
extension SelectActivityVC: UITableViewDataSource, UITableViewDelegate {
|
|
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
|
items.count
|
|
}
|
|
|
|
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
|
let cell = tableView.dequeueReusableCell(withIdentifier: SelectActivityCell.reuseId, for: indexPath) as! SelectActivityCell
|
|
cell.configure(item: items[indexPath.row])
|
|
return cell
|
|
}
|
|
|
|
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
|
let item = items[indexPath.row]
|
|
onSelect?(item)
|
|
dismiss(animated: true)
|
|
}
|
|
}
|