diff --git a/App/Browser View/BrowserViewController.swift b/App/Browser View/BrowserViewController.swift index a239ebe..4c448cc 100644 --- a/App/Browser View/BrowserViewController.swift +++ b/App/Browser View/BrowserViewController.swift @@ -386,8 +386,9 @@ class BrowserViewController: UIViewController let userActivity = NSUserActivity(activityType: SessionActivityType.SettingsWindow.rawValue) UIApplication.shared.requestSceneSessionActivation(nil, userActivity: userActivity, options: .none, errorHandler: nil) #else - let settingsVC = SettingsViewController() - present(settingsVC, animated: true, completion: nil) + let settingsVC = SettingsViewController(windowScene: view.window!.windowScene!) + let wrapperNC = UINavigationController(rootViewController: settingsVC) + present(wrapperNC, animated: true, completion: nil) #endif } diff --git a/App/Common UI/GenericContentView.swift b/App/Common UI/GenericContentView.swift new file mode 100644 index 0000000..53b5e0a --- /dev/null +++ b/App/Common UI/GenericContentView.swift @@ -0,0 +1,47 @@ +// +// GenericContentView.swift +// GenericContentView +// +// Created by James Magahern on 6/29/21. +// + +import UIKit + +class GenericContentView : UIView, UIContentView + where View: UIView, Configuration: UIContentConfiguration +{ + typealias Applicator = (Configuration, View) -> Void + + var insets: UIEdgeInsets = .zero + let applicator: Applicator + let view: View + + var configuration: UIContentConfiguration { + didSet { + guard let config = configuration as? Configuration else { return } + apply(config) + } + } + + init(configuration: Configuration, view: View, applicator: @escaping Applicator) { + self.configuration = configuration + self.view = view + self.applicator = applicator + super.init(frame: .zero) + addSubview(view) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func layoutSubviews() { + super.layoutSubviews() + view.frame = bounds.inset(by: insets) + } + + internal func apply(_ configuration: Configuration) { + applicator(configuration, view) + } +} + diff --git a/App/SceneDelegate.swift b/App/SceneDelegate.swift index baf1252..6d8cc46 100644 --- a/App/SceneDelegate.swift +++ b/App/SceneDelegate.swift @@ -25,10 +25,10 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { let window = UIWindow(windowScene: windowScene) if let userActivity = connectionOptions.userActivities.first { if userActivity.activityType == SessionActivityType.SettingsWindow.rawValue { - let settingsViewController = SettingsViewController() + let settingsViewController = SettingsViewController(windowScene: windowScene) self.settingsViewController = settingsViewController window.rootViewController = settingsViewController - windowScene.sizeRestrictions?.maximumSize = CGSize(width: 500.0, height: 1200.0) + windowScene.sizeRestrictions?.maximumSize = CGSize(width: 760.0, height: 400.0) } } else { let browserViewController = BrowserViewController() @@ -39,15 +39,15 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { let url = urlContext.url browserViewController.tab.beginLoadingURL(url) } + + #if targetEnvironment(macCatalyst) + windowScene.titlebar?.titleVisibility = .hidden + windowScene.titlebar?.separatorStyle = .none + #endif } window.makeKeyAndVisible() self.window = window - - #if targetEnvironment(macCatalyst) - windowScene.titlebar?.titleVisibility = .hidden - windowScene.titlebar?.separatorStyle = .none - #endif } func scene(_ scene: UIScene, openURLContexts URLContexts: Set) diff --git a/App/Settings/SettingsView.swift b/App/Settings/Amber/AmberSettingsView.swift similarity index 96% rename from App/Settings/SettingsView.swift rename to App/Settings/Amber/AmberSettingsView.swift index d9ccad9..c0d080d 100644 --- a/App/Settings/SettingsView.swift +++ b/App/Settings/Amber/AmberSettingsView.swift @@ -19,7 +19,7 @@ struct SettingsCategoryCell: View { } } -struct SettingsView: View { +struct AmberSettingsView: View { @Environment(\.presentationMode) @Binding private var presentationMode @@ -62,6 +62,6 @@ struct SettingsView: View { struct SettingsView_Previews: PreviewProvider { static var previews: some View { - SettingsView() + AmberSettingsView() } } diff --git a/App/Settings/Amber/AmberSettingsViewController.swift b/App/Settings/Amber/AmberSettingsViewController.swift new file mode 100644 index 0000000..d15ed34 --- /dev/null +++ b/App/Settings/Amber/AmberSettingsViewController.swift @@ -0,0 +1,22 @@ +// +// SettingsViewController.swift +// App +// +// Created by James Magahern on 3/3/21. +// + +import SwiftUI +import UIKit + +class AmberSettingsViewController: UIHostingController +{ + var settingsView = AmberSettingsView() + + init() { + super.init(rootView: settingsView) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/App/Settings/GeneralSettingsViewController.swift b/App/Settings/GeneralSettingsViewController.swift new file mode 100644 index 0000000..0c4339d --- /dev/null +++ b/App/Settings/GeneralSettingsViewController.swift @@ -0,0 +1,195 @@ +// +// GeneralSettingsViewController.swift +// GeneralSettingsViewController +// +// Created by James Magahern on 6/25/21. +// + +import UIKit + +struct LabelContentConfiguration : UIContentConfiguration +{ + var text: String = "" + var insets: UIEdgeInsets = .zero + var textAlignment: NSTextAlignment = .natural + + func makeContentView() -> UIView & UIContentView { + let label = UILabel(frame: .zero) + let contentView = GenericContentView(configuration: self, view: label) { config, label in + label.text = config.text + label.textAlignment = config.textAlignment + } + contentView.insets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10) + return contentView + } + + func updated(for state: UIConfigurationState) -> Self { + self + } +} + +struct ButtonContentConfiguration : UIContentConfiguration +{ + var menu: UIMenu + + func makeContentView() -> UIView & UIContentView { + let button = UIButton(primaryAction: nil) + return GenericContentView(configuration: self, view: button) { config, button in + button.menu = menu + button.showsMenuAsPrimaryAction = true + if #available(macCatalyst 15.0, iOS 15.0, *) { + var buttonConfiguration = UIButton.Configuration.plain() + buttonConfiguration.titleAlignment = .trailing + + button.configuration = buttonConfiguration + button.changesSelectionAsPrimaryAction = true + } + } + } + + func updated(for state: UIConfigurationState) -> ButtonContentConfiguration { + self + } +} + +class GeneralSettingsViewController: UIViewController +{ + enum Section: String, CaseIterable { + case searchEngine = "Search Engine" + } + + typealias Item = String + + static let SearchProviderPopupItem = "searchProvider.popup" + + let dataSource: UICollectionViewDiffableDataSource + let collectionView: UICollectionView + + static func createLayout(forIdiom idiom: UIUserInterfaceIdiom) -> UICollectionViewLayout { + if idiom == .mac { + let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), + heightDimension: .fractionalHeight(1.0)) + let item = NSCollectionLayoutItem(layoutSize: itemSize) + + let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.60), + heightDimension: .absolute(44)) + + let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: 1) + group.edgeSpacing = NSCollectionLayoutEdgeSpacing(leading: .flexible(1.0), top: nil, trailing: nil, bottom: nil) + + let insets = NSDirectionalEdgeInsets(top: 24.0, leading: 64.0, bottom: 24.0, trailing: 64.0) + + let headerFooterSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.40), + heightDimension: .estimated(44.0)) + let sectionHeader = NSCollectionLayoutBoundarySupplementaryItem( + layoutSize: headerFooterSize, + elementKind: UICollectionView.elementKindSectionHeader, + alignment: .topLeading, + absoluteOffset: CGPoint(x: insets.leading, y: insets.top) + ) + sectionHeader.extendsBoundary = false + sectionHeader.contentInsets = insets + + let section = NSCollectionLayoutSection(group: group) + // section.interGroupSpacing = spacing + section.contentInsets = insets + section.supplementariesFollowContentInsets = true + section.boundarySupplementaryItems = [ sectionHeader ] + + let layout = UICollectionViewCompositionalLayout(section: section) + return layout + } else { + var listConfiguration = UICollectionLayoutListConfiguration(appearance: .insetGrouped) + listConfiguration.headerMode = .supplementary + return UICollectionViewCompositionalLayout.list(using: listConfiguration) + } + } + + static func sectionHeaderConfiguration(forIdiom idiom: UIUserInterfaceIdiom, sectionName: String) -> UIContentConfiguration { + if idiom == .mac { + return LabelContentConfiguration( + text: sectionName + ": ", + insets: UIEdgeInsets(top: 0, left: 10.0, bottom: 0, right: 10.0), + textAlignment: .right + ) + } else { + var config = UIListContentConfiguration.plainHeader() + config.text = sectionName + return config + } + } + + #if targetEnvironment(macCatalyst) + static let staticIdiom = UIUserInterfaceIdiom.mac + #else + static let staticIdiom = UIUserInterfaceIdiom.pad + #endif + + init() { + let actionHandler = { (action: UIAction) in + let providerString = action.title + let provider = Settings.SearchProviderSetting(rawValue: providerString)! + Settings.shared.searchProvider = provider + } + + let itemCellRegistry = UICollectionView.CellRegistration { cell, indexPath, identifier in + if identifier == Self.SearchProviderPopupItem { + let menu = UIMenu(children: Settings.SearchProviderSetting.allCases.map { provider in + let action = UIAction(title: provider.rawValue, handler: actionHandler) + action.state = Settings.shared.searchProvider == provider ? .on : .off + return action + }) + + cell.contentConfiguration = ButtonContentConfiguration(menu: menu) + + #if !targetEnvironment(macCatalyst) + cell.backgroundConfiguration = UIBackgroundConfiguration.listGroupedCell() + #endif + } + } + + let sectionHeaderRegistry = UICollectionView.SupplementaryRegistration(elementKind: UICollectionView.elementKindSectionHeader, handler: { + (cell, string, indexPath) in + let sectionName = Section.allCases[indexPath.section].rawValue + cell.contentConfiguration = Self.sectionHeaderConfiguration(forIdiom: Self.staticIdiom, sectionName: sectionName) + }) + + let layout = Self.createLayout(forIdiom: Self.staticIdiom) + collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) + collectionView.backgroundColor = .systemGroupedBackground + + dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) { + (collectionView, indexPath, identifier) in + return collectionView.dequeueConfiguredReusableCell(using: itemCellRegistry, for: indexPath, item: identifier) + } + + dataSource.supplementaryViewProvider = { collectionView, elementKind, indexPath in + return collectionView.dequeueConfiguredReusableSupplementary(using: sectionHeaderRegistry, for: indexPath) + } + + super.init(nibName: nil, bundle: nil) + + tabBarItem.title = "General" + tabBarItem.image = UIImage(systemName: "gear") + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func loadView() { + self.view = collectionView + } + + override func viewDidLoad() { + super.viewDidLoad() + + var snapshot = dataSource.snapshot() + snapshot.appendSections(Section.allCases) + // iOS + // snapshot.appendItems(Settings.SearchProviderSetting.allCases.map { $0.rawValue }, toSection: .searchEngine) + snapshot.appendItems([ Self.SearchProviderPopupItem ], toSection: .searchEngine) + dataSource.apply(snapshot, animatingDifferences: false) + } + +} diff --git a/App/Settings/RedirectRulesSettingsViewController.swift b/App/Settings/RedirectRulesSettingsViewController.swift new file mode 100644 index 0000000..b6eafe9 --- /dev/null +++ b/App/Settings/RedirectRulesSettingsViewController.swift @@ -0,0 +1,27 @@ +// +// RedirectRulesSettingsViewController.swift +// RedirectRulesSettingsViewController +// +// Created by James Magahern on 6/25/21. +// + +import UIKit + +class RedirectRulesSettingsViewController: UIViewController +{ + init() { + super.init(nibName: nil, bundle: nil) + + tabBarItem.title = "Redirect Rules" + tabBarItem.image = UIImage(systemName: "arrowshape.zigzag.forward") + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidLoad() { + view.backgroundColor = .red + } +} + diff --git a/App/Settings/SettingsViewController.swift b/App/Settings/SettingsViewController.swift index d94b05d..ec5622c 100644 --- a/App/Settings/SettingsViewController.swift +++ b/App/Settings/SettingsViewController.swift @@ -1,22 +1,104 @@ // // SettingsViewController.swift -// App +// SettingsViewController // -// Created by James Magahern on 3/3/21. +// Created by James Magahern on 6/25/21. // -import SwiftUI import UIKit -class SettingsViewController: UIHostingController +#if targetEnvironment(macCatalyst) +fileprivate extension NSToolbarItem.Identifier { + static let categories = NSToolbarItem.Identifier("preferences.categories") +} +#endif + +#if !targetEnvironment(macCatalyst) +protocol NSToolbarDelegate {} +#endif + +class SettingsViewController: UITabBarController, NSToolbarDelegate { - var settingsView = SettingsView() + #if targetEnvironment(macCatalyst) + let toolbar = NSToolbar(identifier: NSToolbar.Identifier("net.buzzert.rossler-attix.preferences-toolbar")) + #endif - init() { - super.init(rootView: settingsView) + init(windowScene: UIWindowScene) { + super.init(nibName: nil, bundle: nil) + self.title = "Preferences" + + self.viewControllers = [ + GeneralSettingsViewController(), + RedirectRulesSettingsViewController(), + ] + + navigationItem.rightBarButtonItem = UIBarButtonItem(systemItem: .done, primaryAction: UIAction { [unowned self] _ in + self.dismiss(animated: true, completion: nil) + }, menu: nil) + + #if targetEnvironment(macCatalyst) + configureTabsForMacIdiom(windowScene: windowScene) + #endif } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + +#if targetEnvironment(macCatalyst) + internal func configureTabsForMacIdiom(windowScene: UIWindowScene) { + self.tabBar.isHidden = true + + guard let titlebar = windowScene.titlebar else { return } + titlebar.toolbarStyle = .preference + + toolbar.delegate = self + toolbar.displayMode = .iconAndLabel + + titlebar.toolbar = toolbar + + windowScene.title = self.title + + toolbar.selectedItemIdentifier = toolbarAllowedItemIdentifiers(toolbar).first + } + + // MARK: NSToolbarDelegate + @objc + func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { + return viewControllers!.map { NSToolbarItem.Identifier($0.tabBarItem.title!) } + } + + @objc + func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { + return toolbarAllowedItemIdentifiers(toolbar) + } + + @objc + func toolbarSelectableItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { + return toolbarAllowedItemIdentifiers(toolbar) + } + + @objc + func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? + { + guard let viewController = viewControllers!.first(where: { $0.tabBarItem.title == itemIdentifier.rawValue }) + else { return nil } + + let item = NSToolbarItem(itemIdentifier: itemIdentifier) + item.label = viewController.tabBarItem.title! + item.image = viewController.tabBarItem.image! + item.action = #selector(didSelectToolbarItem(_:)) + + return item + } + + @objc + internal func didSelectToolbarItem(_ sender: NSToolbarItem) { + guard let viewController = viewControllers!.first(where: { $0.tabBarItem.title == sender.itemIdentifier.rawValue }) else { return } + + selectedViewController = viewController + toolbar.selectedItemIdentifier = sender.itemIdentifier + } +#endif // targetEnvironment(macCatalyst) } + diff --git a/SBrowser.xcodeproj/project.pbxproj b/SBrowser.xcodeproj/project.pbxproj index 5e70655..2ae30a6 100644 --- a/SBrowser.xcodeproj/project.pbxproj +++ b/SBrowser.xcodeproj/project.pbxproj @@ -41,8 +41,12 @@ 1ADFF4CD24CBB0C8006DC7AE /* ScriptPolicyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ADFF4CC24CBB0C8006DC7AE /* ScriptPolicyViewController.swift */; }; CD01D5A5254A10BB00189CDC /* TabBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD01D5A4254A10BB00189CDC /* TabBarView.swift */; }; CD01D5AB254A206D00189CDC /* TabBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD01D5AA254A206D00189CDC /* TabBarViewController.swift */; }; + CD19576D268BE95900E8089B /* GenericContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD19576C268BE95900E8089B /* GenericContentView.swift */; }; CD470C4225DE056600AFBE0E /* BrowserViewController+WebKitDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD470C4125DE056600AFBE0E /* BrowserViewController+WebKitDelegate.swift */; }; CD470C4425DE070400AFBE0E /* BrowserViewController+Keyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD470C4325DE070400AFBE0E /* BrowserViewController+Keyboard.swift */; }; + CD7A7E9D2686A9A500E20BA3 /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD7A7E9C2686A9A500E20BA3 /* SettingsViewController.swift */; }; + CD7A7E9F2686B29100E20BA3 /* GeneralSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD7A7E9E2686B29100E20BA3 /* GeneralSettingsViewController.swift */; }; + CD7A7EA12686B2E600E20BA3 /* RedirectRulesSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD7A7EA02686B2E600E20BA3 /* RedirectRulesSettingsViewController.swift */; }; CD7A8915251975B70075991E /* AutocompleteViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD7A8914251975B70075991E /* AutocompleteViewController.swift */; }; CD7A89172519872D0075991E /* KeyboardShortcuts.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD7A89162519872D0075991E /* KeyboardShortcuts.swift */; }; CD7A8919251989C90075991E /* UIKeyCommand+ConvInit.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD7A8918251989C90075991E /* UIKeyCommand+ConvInit.swift */; }; @@ -62,8 +66,8 @@ CDCE2668251AAA9A007FE92A /* FontSizeAdjustView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDCE2667251AAA9A007FE92A /* FontSizeAdjustView.swift */; }; CDD0522125F8023700DD1771 /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDD0522025F8023700DD1771 /* Settings.swift */; }; CDD0522425F8055700DD1771 /* SearchProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDD0522325F8055700DD1771 /* SearchProvider.swift */; }; - CDE6A30425F023BC00E912A4 /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE6A30325F023BC00E912A4 /* SettingsViewController.swift */; }; - CDE6A30625F023EA00E912A4 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE6A30525F023EA00E912A4 /* SettingsView.swift */; }; + CDE6A30425F023BC00E912A4 /* AmberSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE6A30325F023BC00E912A4 /* AmberSettingsViewController.swift */; }; + CDE6A30625F023EA00E912A4 /* AmberSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE6A30525F023EA00E912A4 /* AmberSettingsView.swift */; }; CDEDD8AA25D62ADB00862605 /* UITraitCollection+MacLike.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDEDD8A925D62ADB00862605 /* UITraitCollection+MacLike.swift */; }; /* End PBXBuildFile section */ @@ -135,8 +139,12 @@ 1ADFF4CC24CBB0C8006DC7AE /* ScriptPolicyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScriptPolicyViewController.swift; sourceTree = ""; }; CD01D5A4254A10BB00189CDC /* TabBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarView.swift; sourceTree = ""; }; CD01D5AA254A206D00189CDC /* TabBarViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarViewController.swift; sourceTree = ""; }; + CD19576C268BE95900E8089B /* GenericContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenericContentView.swift; sourceTree = ""; }; CD470C4125DE056600AFBE0E /* BrowserViewController+WebKitDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BrowserViewController+WebKitDelegate.swift"; sourceTree = ""; }; CD470C4325DE070400AFBE0E /* BrowserViewController+Keyboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BrowserViewController+Keyboard.swift"; sourceTree = ""; }; + CD7A7E9C2686A9A500E20BA3 /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = ""; }; + CD7A7E9E2686B29100E20BA3 /* GeneralSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralSettingsViewController.swift; sourceTree = ""; }; + CD7A7EA02686B2E600E20BA3 /* RedirectRulesSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedirectRulesSettingsViewController.swift; sourceTree = ""; }; CD7A8914251975B70075991E /* AutocompleteViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutocompleteViewController.swift; sourceTree = ""; }; CD7A89162519872D0075991E /* KeyboardShortcuts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardShortcuts.swift; sourceTree = ""; }; CD7A8918251989C90075991E /* UIKeyCommand+ConvInit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIKeyCommand+ConvInit.swift"; sourceTree = ""; }; @@ -156,8 +164,8 @@ CDCE2667251AAA9A007FE92A /* FontSizeAdjustView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontSizeAdjustView.swift; sourceTree = ""; }; CDD0522025F8023700DD1771 /* Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = ""; }; CDD0522325F8055700DD1771 /* SearchProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchProvider.swift; sourceTree = ""; }; - CDE6A30325F023BC00E912A4 /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = ""; }; - CDE6A30525F023EA00E912A4 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; }; + CDE6A30325F023BC00E912A4 /* AmberSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AmberSettingsViewController.swift; sourceTree = ""; }; + CDE6A30525F023EA00E912A4 /* AmberSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AmberSettingsView.swift; sourceTree = ""; }; CDEDD8A925D62ADB00862605 /* UITraitCollection+MacLike.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITraitCollection+MacLike.swift"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -183,6 +191,7 @@ 1A03810E24E71CCA00826501 /* Common UI */ = { isa = PBXGroup; children = ( + CD19576C268BE95900E8089B /* GenericContentView.swift */, 1A03811124E71EAA00826501 /* GradientView.swift */, 1A03810F24E71CF000826501 /* ReliefButton.swift */, 1A03811324E73EB300826501 /* SegmentedReliefButton.swift */, @@ -364,6 +373,15 @@ path = "Script Policy UI"; sourceTree = ""; }; + CD7A7E9B2686A99600E20BA3 /* Amber */ = { + isa = PBXGroup; + children = ( + CDE6A30325F023BC00E912A4 /* AmberSettingsViewController.swift */, + CDE6A30525F023EA00E912A4 /* AmberSettingsView.swift */, + ); + path = Amber; + sourceTree = ""; + }; CD7A89132519759D0075991E /* Autocomplete */ = { isa = PBXGroup; children = ( @@ -422,9 +440,11 @@ CDE6A30225F023A000E912A4 /* Settings */ = { isa = PBXGroup; children = ( - CDE6A30325F023BC00E912A4 /* SettingsViewController.swift */, - CDE6A30525F023EA00E912A4 /* SettingsView.swift */, + CD7A7E9B2686A99600E20BA3 /* Amber */, CDD0522025F8023700DD1771 /* Settings.swift */, + CD7A7E9C2686A9A500E20BA3 /* SettingsViewController.swift */, + CD7A7E9E2686B29100E20BA3 /* GeneralSettingsViewController.swift */, + CD7A7EA02686B2E600E20BA3 /* RedirectRulesSettingsViewController.swift */, ); path = Settings; sourceTree = ""; @@ -562,10 +582,12 @@ 1ADFF46224C7DE53006DC7AE /* SceneDelegate.swift in Sources */, CD853BCE24E7763900D2BDCC /* BrowserHistory.swift in Sources */, 1A03810B24E71C5600826501 /* ToolbarButtonContainerView.swift in Sources */, + CD7A7EA12686B2E600E20BA3 /* RedirectRulesSettingsViewController.swift in Sources */, 1ADFF4CB24CB8278006DC7AE /* ScriptControllerIconView.swift in Sources */, CD7A8915251975B70075991E /* AutocompleteViewController.swift in Sources */, CDC5DA3E25DB7C2C00BA8D99 /* ReaderViewController.swift in Sources */, - CDE6A30625F023EA00E912A4 /* SettingsView.swift in Sources */, + CDE6A30625F023EA00E912A4 /* AmberSettingsView.swift in Sources */, + CD7A7E9D2686A9A500E20BA3 /* SettingsViewController.swift in Sources */, 1AB88EFD24D3BA560006F850 /* TabController.swift in Sources */, 1ADFF4C324CA6AF6006DC7AE /* Geometry.swift in Sources */, CD7F2135265DAD010001D042 /* MFMailComposeViewControllerFix.m in Sources */, @@ -573,12 +595,14 @@ 1ADFF4C924CA793E006DC7AE /* ToolbarViewController.swift in Sources */, CD7A89172519872D0075991E /* KeyboardShortcuts.swift in Sources */, 1ADFF4CD24CBB0C8006DC7AE /* ScriptPolicyViewController.swift in Sources */, - CDE6A30425F023BC00E912A4 /* SettingsViewController.swift in Sources */, + CDE6A30425F023BC00E912A4 /* AmberSettingsViewController.swift in Sources */, 1A14FC2824D26749009B3F83 /* Tab.swift in Sources */, + CD7A7E9F2686B29100E20BA3 /* GeneralSettingsViewController.swift in Sources */, CD01D5AB254A206D00189CDC /* TabBarViewController.swift in Sources */, 1ADFF47924C7DFF8006DC7AE /* BrowserView.swift in Sources */, CDCE2664251AA80F007FE92A /* DocumentControlViewController.swift in Sources */, 1AB88EFF24D3BBA50006F850 /* TabPickerViewController.swift in Sources */, + CD19576D268BE95900E8089B /* GenericContentView.swift in Sources */, 1A14FC2324D203D9009B3F83 /* TitlebarView.swift in Sources */, 1AD310452525586B00A4A952 /* DocumentControlItemView.swift in Sources */, CD97CF9225D5BE6F00288FEE /* NavigationControlsView.swift in Sources */,