jsdw_ios/QuickLocation/Section/AppRestrict/SelectActivityVC.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)
}
}