113 lines
4.2 KiB
Swift
113 lines
4.2 KiB
Swift
//
|
|
// PhotoPickerAlbumView.swift
|
|
// QuickLocation
|
|
//
|
|
|
|
import UIKit
|
|
import Photos
|
|
|
|
final class PhotoPickerAlbumView: UIView, UITableViewDataSource, UITableViewDelegate {
|
|
|
|
var onSelect: ((Int) -> Void)?
|
|
|
|
private var albums: [PhotoAlbum] = []
|
|
private var selectedIndex = 0
|
|
private var store: PhotoPickerStore?
|
|
|
|
private lazy var tableView: UITableView = {
|
|
let tv = UITableView(frame: .zero, style: .plain)
|
|
tv.backgroundColor = UIColor(hexStr: "#2C2C2E")
|
|
tv.separatorColor = UIColor.white.withAlphaComponent(0.12)
|
|
tv.separatorInset = UIEdgeInsets(top: 0, left: 76, bottom: 0, right: 0)
|
|
tv.rowHeight = 64
|
|
tv.dataSource = self
|
|
tv.delegate = self
|
|
tv.tableFooterView = UIView()
|
|
tv.register(PhotoPickerAlbumCell.self, forCellReuseIdentifier: "cell")
|
|
return tv
|
|
}()
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
backgroundColor = UIColor(hexStr: "#2C2C2E")
|
|
addSubview(tableView)
|
|
tableView.layoutChain.edges()
|
|
}
|
|
|
|
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
|
|
|
func reload(albums: [PhotoAlbum], selectedIndex: Int) {
|
|
self.albums = albums
|
|
self.selectedIndex = selectedIndex
|
|
tableView.reloadData()
|
|
}
|
|
|
|
func bindStore(_ store: PhotoPickerStore) {
|
|
self.store = store
|
|
}
|
|
|
|
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
|
albums.count
|
|
}
|
|
|
|
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
|
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! PhotoPickerAlbumCell
|
|
let album = albums[indexPath.row]
|
|
cell.configure(album: album, selected: indexPath.row == selectedIndex, store: store)
|
|
return cell
|
|
}
|
|
|
|
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
|
selectedIndex = indexPath.row
|
|
tableView.reloadData()
|
|
onSelect?(indexPath.row)
|
|
}
|
|
}
|
|
|
|
private final class PhotoPickerAlbumCell: UITableViewCell {
|
|
private let coverView = UIImageView()
|
|
private let titleLab = UILabel()
|
|
private let tickView = UIImageView()
|
|
private var assetId = ""
|
|
private var requestId: PHImageRequestID = PHInvalidImageRequestID
|
|
|
|
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
|
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
|
backgroundColor = UIColor(hexStr: "#2C2C2E")
|
|
selectionStyle = .none
|
|
coverView.contentMode = .scaleAspectFill
|
|
coverView.clipsToBounds = true
|
|
coverView.cornerRadius = 4
|
|
coverView.backgroundColor = UIColor.white.withAlphaComponent(0.08)
|
|
titleLab.font = .systemFont(ofSize: 16)
|
|
titleLab.textColor = .white
|
|
let config = UIImage.SymbolConfiguration(pointSize: 15, weight: .semibold)
|
|
tickView.image = UIImage(systemName: "checkmark", withConfiguration: config)
|
|
tickView.tintColor = UIColor(hexStr: "#007AFF")
|
|
tickView.contentMode = .scaleAspectFit
|
|
contentView.addSubview(coverView)
|
|
contentView.addSubview(titleLab)
|
|
contentView.addSubview(tickView)
|
|
coverView.layoutChain.left(16).centerY().width(48).height(48)
|
|
titleLab.layoutChain.leftToRightOfView(coverView, offset: 12).centerY().right(40)
|
|
tickView.layoutChain.right(16).centerY().width(18).height(18)
|
|
}
|
|
|
|
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
|
|
|
func configure(album: PhotoAlbum, selected: Bool, store: PhotoPickerStore?) {
|
|
titleLab.text = "\(album.title) (\(album.count))"
|
|
tickView.isHidden = !selected
|
|
coverView.image = nil
|
|
assetId = album.coverAsset?.localIdentifier ?? ""
|
|
guard let store, let asset = album.coverAsset else { return }
|
|
if requestId != PHInvalidImageRequestID {
|
|
store.cancelRequest(requestId)
|
|
}
|
|
requestId = store.requestThumbnail(for: asset, size: CGSize(width: 48, height: 48)) { [weak self] image in
|
|
guard let self, self.assetId == asset.localIdentifier else { return }
|
|
self.coverView.image = image
|
|
}
|
|
}
|
|
}
|