Add first-class Actions management (#63)
This commit is contained in:
128
ios/Sources/NavigationSettingsViewController.swift
Normal file
128
ios/Sources/NavigationSettingsViewController.swift
Normal file
@@ -0,0 +1,128 @@
|
||||
import UIKit
|
||||
|
||||
@MainActor
|
||||
final class NavigationSettingsViewController: UITableViewController {
|
||||
private let context: AppContext
|
||||
private var selected: [PrimaryDestination]
|
||||
|
||||
init(context: AppContext) {
|
||||
self.context = context
|
||||
selected = context.primaryDestinations
|
||||
super.init(style: .insetGrouped)
|
||||
title = "Primary Navigation"
|
||||
navigationItem.rightBarButtonItem = editButtonItem
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder: NSCoder) { fatalError("init(coder:) is not supported") }
|
||||
|
||||
private var available: [PrimaryDestination] {
|
||||
PrimaryDestination.allCases.filter { !selected.contains($0) }
|
||||
}
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int { 2 }
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
section == 0 ? selected.count : available.count
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
section == 0 ? "Shown After Home" : "Available on Home"
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
|
||||
section == 0
|
||||
? "Choose up to four destinations. Tap Edit to reorder them. Home is always first."
|
||||
: "Destinations not in the tab bar remain available as buttons on Home."
|
||||
}
|
||||
|
||||
override func tableView(
|
||||
_ tableView: UITableView,
|
||||
cellForRowAt indexPath: IndexPath
|
||||
) -> UITableViewCell {
|
||||
let destination = indexPath.section == 0 ? selected[indexPath.row] : available[indexPath.row]
|
||||
let cell = UITableViewCell(style: .default, reuseIdentifier: nil)
|
||||
var content = cell.defaultContentConfiguration()
|
||||
content.text = destination.title
|
||||
content.image = UIImage(systemName: destination.symbolName)
|
||||
content.imageProperties.tintColor = .tintColor
|
||||
if indexPath.section == 1 && selected.count == 4 {
|
||||
content.textProperties.color = .secondaryLabel
|
||||
content.imageProperties.tintColor = .tertiaryLabel
|
||||
cell.selectionStyle = .none
|
||||
} else if indexPath.section == 1 {
|
||||
let add = UIImageView(image: UIImage(systemName: "plus.circle.fill"))
|
||||
add.tintColor = .tintColor
|
||||
cell.accessoryView = add
|
||||
cell.accessibilityHint = "Adds this destination to the tab bar"
|
||||
}
|
||||
cell.contentConfiguration = content
|
||||
return cell
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
|
||||
indexPath.section == 0
|
||||
}
|
||||
|
||||
override func tableView(
|
||||
_ tableView: UITableView,
|
||||
moveRowAt sourceIndexPath: IndexPath,
|
||||
to destinationIndexPath: IndexPath
|
||||
) {
|
||||
guard sourceIndexPath.section == 0, destinationIndexPath.section == 0 else {
|
||||
tableView.reloadData()
|
||||
return
|
||||
}
|
||||
let destination = selected.remove(at: sourceIndexPath.row)
|
||||
selected.insert(destination, at: destinationIndexPath.row)
|
||||
save()
|
||||
}
|
||||
|
||||
override func tableView(
|
||||
_ tableView: UITableView,
|
||||
targetIndexPathForMoveFromRowAt sourceIndexPath: IndexPath,
|
||||
toProposedIndexPath proposedDestinationIndexPath: IndexPath
|
||||
) -> IndexPath {
|
||||
guard proposedDestinationIndexPath.section == 0 else {
|
||||
return IndexPath(row: max(selected.count - 1, 0), section: 0)
|
||||
}
|
||||
return proposedDestinationIndexPath
|
||||
}
|
||||
|
||||
override func tableView(
|
||||
_ tableView: UITableView,
|
||||
editingStyleForRowAt indexPath: IndexPath
|
||||
) -> UITableViewCell.EditingStyle {
|
||||
indexPath.section == 0 ? .delete : .none
|
||||
}
|
||||
|
||||
override func tableView(
|
||||
_ tableView: UITableView,
|
||||
commit editingStyle: UITableViewCell.EditingStyle,
|
||||
forRowAt indexPath: IndexPath
|
||||
) {
|
||||
guard editingStyle == .delete, indexPath.section == 0 else { return }
|
||||
selected.remove(at: indexPath.row)
|
||||
save()
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
guard indexPath.section == 1, selected.count < 4 else { return }
|
||||
selected.append(available[indexPath.row])
|
||||
save()
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
private func save() {
|
||||
do {
|
||||
try context.core.setPrimaryDestinations(destinations: selected)
|
||||
context.applyPrimaryDestinations()
|
||||
} catch {
|
||||
selected = context.primaryDestinations
|
||||
tableView.reloadData()
|
||||
show(error: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user