Redirect Rules: implements redirect rules UI
This commit is contained in:
@@ -7,10 +7,52 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
class RedirectRulesSettingsViewController: UIViewController
|
||||
class RedirectRulesSettingsViewController: UICollectionViewController
|
||||
{
|
||||
private enum Section {
|
||||
case rules
|
||||
case addButton
|
||||
}
|
||||
|
||||
private enum Items: String {
|
||||
case addButton
|
||||
}
|
||||
|
||||
private lazy var dataSource: UICollectionViewDiffableDataSource<Section, String> = {
|
||||
let registry = UICollectionView.CellRegistration<UICollectionViewListCell, String> { [unowned self] cell, indexPath, item in
|
||||
var config = cell.defaultContentConfiguration()
|
||||
if item == Items.addButton.rawValue {
|
||||
config.text = "Add Redirect Rule"
|
||||
config.textProperties.font = .preferredFont(forTextStyle: .subheadline)
|
||||
config.textProperties.alignment = .center
|
||||
config.image = .init(systemName: "plus.circle")
|
||||
|
||||
cell.accessories = []
|
||||
} else {
|
||||
if let rule = Settings.shared.redirectRules[item] {
|
||||
config.text = "\(item) → \(rule)"
|
||||
}
|
||||
|
||||
let deleteOptions = UICellAccessory.DeleteOptions(isHidden: false, reservedLayoutWidth: nil, tintColor: .red, backgroundColor: nil)
|
||||
cell.accessories = [
|
||||
.delete(displayed: .always, options: deleteOptions, actionHandler: { [unowned self] in
|
||||
deleteRedirectRule(fromHost: item)
|
||||
})
|
||||
]
|
||||
}
|
||||
|
||||
cell.contentConfiguration = config
|
||||
}
|
||||
|
||||
return UICollectionViewDiffableDataSource<Section, String>(collectionView: collectionView) { (collectionView, indexPath, itemIdentifier) in
|
||||
collectionView.dequeueConfiguredReusableCell(using: registry, for: indexPath, item: itemIdentifier)
|
||||
}
|
||||
}()
|
||||
|
||||
init() {
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
let config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
|
||||
let layout = UICollectionViewCompositionalLayout.list(using: config)
|
||||
super.init(collectionViewLayout: layout)
|
||||
|
||||
tabBarItem.title = "Redirect Rules"
|
||||
tabBarItem.image = UIImage(systemName: "arrowshape.zigzag.forward")
|
||||
@@ -21,7 +63,122 @@ class RedirectRulesSettingsViewController: UIViewController
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
view.backgroundColor = .red
|
||||
var snapshot = dataSource.snapshot()
|
||||
snapshot.appendSections([ .rules, .addButton ])
|
||||
snapshot.appendItems(Settings.shared.redirectRules.keys.sorted(), toSection: .rules)
|
||||
snapshot.appendItems([ Items.addButton.rawValue ], toSection: .addButton)
|
||||
dataSource.applySnapshotUsingReloadData(snapshot)
|
||||
}
|
||||
|
||||
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
let item = dataSource.itemIdentifier(for: indexPath)
|
||||
if item == Items.addButton.rawValue {
|
||||
let createRuleViewController = CreateRedirectRuleViewController()
|
||||
createRuleViewController.finishedCreatingRule = { [unowned self] (fromHost, toHost) in
|
||||
if fromHost.count > 0 && toHost.count > 0 {
|
||||
addRedirectRule(fromHost: fromHost, toHost: toHost)
|
||||
}
|
||||
}
|
||||
|
||||
let navController = UINavigationController(rootViewController: createRuleViewController)
|
||||
present(navController, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func addRedirectRule(fromHost: String, toHost: String) {
|
||||
Settings.shared.redirectRules[fromHost] = toHost
|
||||
|
||||
var snapshot = dataSource.snapshot()
|
||||
snapshot.appendItems([ fromHost ], toSection: .rules)
|
||||
dataSource.apply(snapshot, animatingDifferences: true)
|
||||
}
|
||||
|
||||
private func deleteRedirectRule(fromHost: String) {
|
||||
Settings.shared.redirectRules.removeValue(forKey: fromHost)
|
||||
|
||||
var snapshot = dataSource.snapshot()
|
||||
snapshot.deleteItems([ fromHost ])
|
||||
dataSource.apply(snapshot, animatingDifferences: true)
|
||||
}
|
||||
}
|
||||
|
||||
class CreateRedirectRuleViewController: UICollectionViewController
|
||||
{
|
||||
enum Section {
|
||||
case hosts
|
||||
}
|
||||
|
||||
enum Item: String {
|
||||
case fromHost
|
||||
case toHost
|
||||
}
|
||||
|
||||
struct TextFieldCellConfiguration: UIContentConfiguration {
|
||||
var textField: UITextField
|
||||
|
||||
func makeContentView() -> UIView & UIContentView {
|
||||
return GenericContentView<UITextField, TextFieldCellConfiguration>(configuration: self, view: textField) { _,_ in }
|
||||
}
|
||||
|
||||
func updated(for state: UIConfigurationState) -> TextFieldCellConfiguration {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
public var finishedCreatingRule: ((_ fromHost: String, _ toHost: String) -> Void)?
|
||||
|
||||
private let fromHostField = UITextField(frame: .zero)
|
||||
private let toHostField = UITextField(frame: .zero)
|
||||
|
||||
private let doneButton = UIBarButtonItem(systemItem: .done, primaryAction: nil, menu: nil)
|
||||
|
||||
private lazy var dataSource: UICollectionViewDiffableDataSource<Section, Item> = {
|
||||
let registry = UICollectionView.CellRegistration<UICollectionViewListCell, Item> { [unowned self] cell, indexPath, item in
|
||||
if item == Item.fromHost {
|
||||
cell.contentConfiguration = TextFieldCellConfiguration(textField: fromHostField)
|
||||
} else if item == Item.toHost {
|
||||
cell.contentConfiguration = TextFieldCellConfiguration(textField: toHostField)
|
||||
}
|
||||
}
|
||||
|
||||
return UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView) { (collectionView, indexPath, itemIdentifier) in
|
||||
collectionView.dequeueConfiguredReusableCell(using: registry, for: indexPath, item: itemIdentifier)
|
||||
}
|
||||
}()
|
||||
|
||||
init() {
|
||||
let config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
|
||||
let layout = UICollectionViewCompositionalLayout.list(using: config)
|
||||
super.init(collectionViewLayout: layout)
|
||||
|
||||
preferredContentSize = CGSize(width: -1, height: 320.0)
|
||||
|
||||
self.title = "Add Redirect Rule"
|
||||
|
||||
navigationItem.leftBarButtonItem = UIBarButtonItem(systemItem: .cancel, primaryAction: UIAction { [unowned self] _ in
|
||||
dismiss(animated: true, completion: nil)
|
||||
}, menu: nil)
|
||||
|
||||
doneButton.primaryAction = UIAction { [unowned self] _ in
|
||||
finishedCreatingRule?(fromHostField.text!, toHostField.text!)
|
||||
dismiss(animated: true, completion: nil)
|
||||
}
|
||||
|
||||
navigationItem.rightBarButtonItem = doneButton
|
||||
|
||||
fromHostField.placeholder = "From Host"
|
||||
toHostField.placeholder = "To Host"
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
var snapshot = dataSource.snapshot()
|
||||
snapshot.appendSections([ Section.hosts ])
|
||||
snapshot.appendItems([ Item.fromHost, Item.toHost ], toSection: .hosts)
|
||||
dataSource.applySnapshotUsingReloadData(snapshot)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user