// // AssetCollectionsListViewController.swift // Tusker // // Created by Shadowfacts on 1/1/20. // Copyright © 2020 Shadowfacts. All rights reserved. // import UIKit import Photos class AssetCollectionsListViewController: UITableViewController { weak var assetCollectionDelegate: AssetCollectionViewControllerDelegate? var dataSource: DataSource! init() { super.init(style: .plain) title = NSLocalizedString("Collections", comment: "asset collections list title") } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func viewDidLoad() { super.viewDidLoad() navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelPressed)) tableView.register(UINib(nibName: "AllPhotosTableViewCell", bundle: .main), forCellReuseIdentifier: "allPhotosCell") tableView.register(UINib(nibName: "AlbumTableViewCell", bundle: .main), forCellReuseIdentifier: "albumCell") tableView.allowsFocus = true tableView.backgroundColor = .appGroupedBackground dataSource = DataSource(tableView: tableView, cellProvider: { (tableView, indexPath, item) -> UITableViewCell? in switch item { case .cameraRoll: return tableView.dequeueReusableCell(withIdentifier: "allPhotosCell", for: indexPath) case let .album(collection): let cell = tableView.dequeueReusableCell(withIdentifier: "albumCell", for: indexPath) as! AlbumTableViewCell cell.updateUI(album: collection) return cell } }) var snapshot = NSDiffableDataSourceSnapshot() snapshot.appendSections([.system, .albums, .sharedAlbums, .smartAlbums]) snapshot.appendItems([.cameraRoll], toSection: .system) let smartAlbums = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .any, options: nil) var smartAlbumItems = [Item]() smartAlbums.enumerateObjects { (collection, _, _) in guard collection.assetCollectionSubtype != .smartAlbumAllHidden else { return } smartAlbumItems.append(.album(collection)) } // sort these manually, using PHFetchOptions.sortDescriptors seems like it just doesn't work with fetchAssetCollections smartAlbumItems.sort(by: { $0.title < $1.title }) snapshot.appendItems(smartAlbumItems, toSection: .smartAlbums) let albums = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: nil) var albumItems = [Item]() var sharedItems = [Item]() albums.enumerateObjects { (collection, _, _) in if collection.estimatedAssetCount > 0 { if collection.assetCollectionSubtype == .albumCloudShared { sharedItems.append(.album(collection)) } else { albumItems.append(.album(collection)) } } } albumItems.sort(by: { $0.title < $1.title }) sharedItems.sort(by: { $0.title < $1.title }) snapshot.appendItems(albumItems, toSection: .albums) snapshot.appendItems(sharedItems, toSection: .sharedAlbums) dataSource.apply(snapshot, animatingDifferences: false) } // MARK: - Table view delegate override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { switch dataSource.itemIdentifier(for: indexPath) { case nil: return case .cameraRoll: let assetCollection = AssetCollectionViewController() assetCollection.delegate = assetCollectionDelegate show(assetCollection, sender: self) case let .album(collection): let assetCollection = AlbumAssetCollectionViewController(collection: collection) assetCollection.delegate = assetCollectionDelegate show(assetCollection, sender: self) } } // MARK: - Interaction @objc func cancelPressed() { dismiss(animated: true) } } extension AssetCollectionsListViewController { enum Section { case system case albums case sharedAlbums case smartAlbums } enum Item: Hashable { case cameraRoll case album(PHAssetCollection) func hash(into hasher: inout Hasher) { switch self { case .cameraRoll: hasher.combine("cameraRoll") case let .album(collection): hasher.combine("album") hasher.combine(collection.localIdentifier) } } var title: String { switch self { case .cameraRoll: return "All Photos" case .album(let collection): return collection.localizedTitle ?? "" } } } class DataSource: UITableViewDiffableDataSource { override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { switch sectionIdentifier(for: section) { case .albums: return NSLocalizedString("Albums", comment: "albums section title") case .sharedAlbums: return NSLocalizedString("Shared Albums", comment: "shared albums section title") case .smartAlbums: return NSLocalizedString("Smart Albums", comment: "smart albums section title") default: return nil } } } }