// // SwipeActionsPrefsView.swift // Tusker // // Created by Shadowfacts on 11/26/22. // Copyright © 2022 Shadowfacts. All rights reserved. // import SwiftUI struct SwipeActionsPrefsView: UIViewControllerRepresentable { @Binding var selection: [StatusSwipeAction] typealias UIViewControllerType = SwipeActionsPrefsViewController func makeUIViewController(context: Context) -> SwipeActionsPrefsViewController { return SwipeActionsPrefsViewController(selection: $selection) } func updateUIViewController(_ uiViewController: SwipeActionsPrefsViewController, context: Context) { } } class SwipeActionsPrefsViewController: UIViewController, UICollectionViewDelegate { @Binding var selection: [StatusSwipeAction] private var collectionView: UICollectionView { view as! UICollectionView } private var dataSource: UICollectionViewDiffableDataSource! init(selection: Binding<[StatusSwipeAction]>) { self._selection = selection super.init(nibName: nil, bundle: nil) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func loadView() { let layout = UICollectionViewCompositionalLayout { [unowned self] sectionIndex, environment in var config = UICollectionLayoutListConfiguration(appearance: .insetGrouped) config.backgroundColor = .appGroupedBackground if dataSource.sectionIdentifier(for: sectionIndex) == .selected { config.headerMode = .supplementary } return .list(using: config, layoutEnvironment: environment) } view = UICollectionView(frame: .zero, collectionViewLayout: layout) collectionView.delegate = self dataSource = createDataSource() } private func createDataSource() -> UICollectionViewDiffableDataSource { let listCell = UICollectionView.CellRegistration { cell, indexPath, item in var config = cell.defaultContentConfiguration() config.text = item.displayName config.image = UIImage(systemName: item.systemImageName) cell.contentConfiguration = config cell.accessories = [.reorder(displayed: .always)] cell.configurationUpdateHandler = { cell, state in var config = UIBackgroundConfiguration.listGroupedCell().updated(for: state) if state.isHighlighted || state.isSelected { config.backgroundColor = .appSelectedCellBackground } else { config.backgroundColor = .appGroupedCellBackground } cell.backgroundConfiguration = config } } let dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) { collectionView, indexPath, itemIdentifier in return collectionView.dequeueConfiguredReusableCell(using: listCell, for: indexPath, item: itemIdentifier) } let headerCell = UICollectionView.SupplementaryRegistration(elementKind: UICollectionView.elementKindSectionHeader) { supplementaryView, elementKind, indexPath in var config = supplementaryView.defaultContentConfiguration() config.text = "Selected" supplementaryView.contentConfiguration = config } dataSource.supplementaryViewProvider = { collectionView, kind, indexPath in return collectionView.dequeueConfiguredReusableSupplementary(using: headerCell, for: indexPath) } dataSource.reorderingHandlers.canReorderItem = { _ in return true } dataSource.reorderingHandlers.didReorder = { [unowned self] transaction in guard let selectedSection = transaction.sectionTransactions.first(where: { $0.sectionIdentifier == .selected }) else { return } self.selection = self.selection.applying(selectedSection.difference)! } return dataSource } override func viewDidLoad() { super.viewDidLoad() setEditing(true, animated: false) applySnapshot(animated: false) } func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { collectionView.deselectItem(at: indexPath, animated: true) guard let item = dataSource.itemIdentifier(for: indexPath), let section = dataSource.sectionIdentifier(for: indexPath.section) else { return } switch section { case .selected: selection.removeAll(where: { $0 == item }) case .remainder: selection.append(item) } applySnapshot(animated: true) } private func applySnapshot(animated: Bool) { var snapshot = NSDiffableDataSourceSnapshot() snapshot.appendSections([.selected, .remainder]) snapshot.appendItems(selection, toSection: .selected) snapshot.appendItems(StatusSwipeAction.allCases.filter { !selection.contains($0) }, toSection: .remainder) dataSource.apply(snapshot, animatingDifferences: animated) } enum Section { case selected case remainder } typealias Item = StatusSwipeAction }