TabPickerViewController: Refactor to not reference tab controller directly.

This commit is contained in:
James Magahern
2022-08-05 15:13:37 -07:00
parent ace7917080
commit 1db6cf54a9
7 changed files with 181 additions and 112 deletions

View File

@@ -137,9 +137,15 @@ class BrowserViewController: UIViewController
// Tabs button // Tabs button
toolbarController.windowButton.addAction(UIAction(handler: { [unowned self] _ in toolbarController.windowButton.addAction(UIAction(handler: { [unowned self] _ in
let tabPickerController = TabPickerViewController(tabController: self.tabController) let tabPickerController = TabPickerViewController()
tabPickerController.delegate = self tabPickerController.delegate = self
tabPickerController.selectedTab = self.tab tabPickerController.selectedTabIdentifier = self.tab.identifier
tabPickerController.tabIdentifiers = tabController.tabs.map { $0.identifier }
tabPickerController.tabObserver = tabController.$tabs
.receive(on: RunLoop.main)
.sink(receiveValue: { (newTabs: [Tab]) in
tabPickerController.tabIdentifiers = newTabs.map { $0.identifier }
})
let navController = UINavigationController(rootViewController: tabPickerController) let navController = UINavigationController(rootViewController: tabPickerController)
navController.modalPresentationStyle = .popover navController.modalPresentationStyle = .popover
@@ -611,12 +617,28 @@ extension BrowserViewController: TabDelegate
extension BrowserViewController: TabPickerViewControllerDelegate extension BrowserViewController: TabPickerViewControllerDelegate
{ {
func tabPicker(_ picker: TabPickerViewController, didSelectTab tab: Tab) { func tabPicker(_ picker: TabPickerViewController, createNewTabWithURL url: URL?) {
self.tab = tabController.createNewTab(url: url)
picker.dismiss(animated: true)
}
func tabPicker(_ picker: TabPickerViewController, tabInfoForIdentifier identifier: UUID) -> TabInfo {
guard let tab = tabController.tab(forIdentifier: identifier) else { fatalError() }
return tab.tabInfo
}
func tabPicker(_ picker: TabPickerViewController, didSelectTabIdentifier tabIdentifier: UUID) {
guard let tab = tabController.tab(forIdentifier: tabIdentifier) else { return }
self.tab = tab self.tab = tab
picker.dismiss(animated: true, completion: nil) picker.dismiss(animated: true, completion: nil)
} }
func tabPicker(_ picker: TabPickerViewController, willCloseTab tab: Tab) { func tabPicker(_ picker: TabPickerViewController, closeTabWithIdentifier tabIdentifier: UUID) {
guard let tab = tabController.tab(forIdentifier: tabIdentifier) else { return }
tabController.closeTab(tab)
// Dismiss picker if current tab is closed using the picker // Dismiss picker if current tab is closed using the picker
if tab == self.tab { if tab == self.tab {
picker.dismiss(animated: true, completion: nil) picker.dismiss(animated: true, completion: nil)

View File

@@ -17,6 +17,17 @@ class Tab: NSObject, SBRProcessBundleBridgeDelegate
{ {
public weak var delegate: TabDelegate? public weak var delegate: TabDelegate?
public var tabInfo: TabInfo {
get {
TabInfo(
title: loadedWebView?.title,
url: loadedWebView?.url ?? self.homeURL,
favicon: self.favicon,
identifier: self.identifier
)
}
}
public let homeURL: URL? public let homeURL: URL?
public let bridge: ProcessBundleBridge public let bridge: ProcessBundleBridge
public var webView: WKWebView { public var webView: WKWebView {
@@ -33,8 +44,8 @@ class Tab: NSObject, SBRProcessBundleBridgeDelegate
public var policyManager: ResourcePolicyManager public var policyManager: ResourcePolicyManager
private var loadedWebView: WKWebView? = nil private var loadedWebView: WKWebView? = nil
public var title: String? { loadedWebView?.title } public var title: String? { get { tabInfo.title } }
public var url: URL? { loadedWebView?.url ?? self.homeURL } public var url: URL? { get { tabInfo.url } }
public var javaScriptEnabled: Bool = false { public var javaScriptEnabled: Bool = false {
didSet { bridge.allowAllScripts = javaScriptEnabled } didSet { bridge.allowAllScripts = javaScriptEnabled }

View File

@@ -174,7 +174,7 @@ class TabBarView: UIView
} else { } else {
let newTabView = makeTabView(withIdentifier: identifier) let newTabView = makeTabView(withIdentifier: identifier)
if animated { newTabView.collapsed = true } if animated { newTabView.collapsed = true }
if i < tabViews.count { if i > 0 && i < tabViews.count {
tabViews.insert(newTabView, at: i - 1) tabViews.insert(newTabView, at: i - 1)
} else { } else {
tabViews.append(newTabView) tabViews.append(newTabView)

21
App/Tabs/TabInfo.swift Normal file
View File

@@ -0,0 +1,21 @@
//
// TabInfo.swift
// App
//
// Created by James Magahern on 8/5/22.
//
import Foundation
import Combine
struct TabInfo
{
public var title: String?
public var url: URL?
public var favicon: UIImage?
public var identifier = UUID()
public static func ==(lhs: TabInfo, rhs: TabInfo) -> Bool {
return lhs.identifier == rhs.identifier
}
}

View File

@@ -6,25 +6,83 @@
// //
import UIKit import UIKit
import Combine
protocol TabPickerViewControllerDelegate: AnyObject protocol TabPickerViewControllerDelegate: AnyObject
{ {
func tabPicker(_ picker: TabPickerViewController, didSelectTab tab: Tab) func tabPicker(_ picker: TabPickerViewController, createNewTabWithURL: URL?)
func tabPicker(_ picker: TabPickerViewController, willCloseTab tab: Tab) func tabPicker(_ picker: TabPickerViewController, didSelectTabIdentifier tab: UUID)
func tabPicker(_ picker: TabPickerViewController, closeTabWithIdentifier tab: UUID)
func tabPicker(_ picker: TabPickerViewController, tabInfoForIdentifier: UUID) -> TabInfo
} }
class TabPickerViewController: UIViewController, UICollectionViewDelegate class TabPickerViewController: UIViewController, UICollectionViewDelegate
{ {
let tabController: TabController!
var selectedTab: Tab?
weak var delegate: TabPickerViewControllerDelegate?
typealias TabID = UUID typealias TabID = UUID
private var selectedTabsForEditing: Set<Tab> = [] public var selectedTabIdentifier: UUID?
private var collectionView: UICollectionView? public var tabIdentifiers: [ UUID ] = [] {
private var dataSource: UICollectionViewDiffableDataSource<Int, TabID>? didSet {
var snapshot = dataSource.snapshot()
snapshot.deleteAllItems()
snapshot.appendSections([ 0 ])
snapshot.appendItems(tabIdentifiers)
dataSource.apply(snapshot)
}
}
weak var delegate: TabPickerViewControllerDelegate?
public var tabObserver: AnyCancellable?
private var selectedTabIdentifiersForEditing: Set<UUID> = []
private var listConfiguration = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
private lazy var listLayout = UICollectionViewCompositionalLayout.list(using: listConfiguration)
private lazy var collectionView = UICollectionView(frame: .zero, collectionViewLayout: listLayout).conf { collectionView in
collectionView.allowsMultipleSelectionDuringEditing = true
collectionView.backgroundColor = .systemGroupedBackground
collectionView.delegate = self
}
private lazy var cellRegistry = UICollectionView.CellRegistration<UICollectionViewListCell, TabID> { [unowned self] (listCell, indexPath, item) in
var config = listCell.defaultContentConfiguration()
if let tab = delegate?.tabPicker(self, tabInfoForIdentifier: item) {
if let title = tab.title, title.count > 0 {
config.text = title
config.secondaryText = tab.url?.absoluteString
} else if let url = tab.url {
config.text = url.absoluteString
config.secondaryText = url.absoluteString
} else {
config.text = "New Tab"
}
config.textProperties.numberOfLines = 1
config.secondaryTextProperties.numberOfLines = 1
if let image = tab.favicon {
config.image = image
} else {
config.image = UIImage(systemName: "safari")
}
config.imageProperties.maximumSize = CGSize(width: 21.0, height: 21.0)
config.imageProperties.cornerRadius = 3.0
if let selectedTabIdentifier, selectedTabIdentifier == item {
listCell.accessories = [ .checkmark() ]
} else {
listCell.accessories = []
}
}
listCell.contentConfiguration = config
}
private lazy var dataSource = UICollectionViewDiffableDataSource<Int, TabID>(collectionView: collectionView)
{ [unowned self] (collectionView, indexPath, item) -> UICollectionViewCell? in
return collectionView.dequeueConfiguredReusableCell(using: cellRegistry, for: indexPath, item: item)
}
override var traitCollection: UITraitCollection { override var traitCollection: UITraitCollection {
get { return super.traitCollection.alwaysPadLike() } get { return super.traitCollection.alwaysPadLike() }
@@ -32,8 +90,7 @@ class TabPickerViewController: UIViewController, UICollectionViewDelegate
private lazy var newTabButton: UIBarButtonItem = { private lazy var newTabButton: UIBarButtonItem = {
UIBarButtonItem(systemItem: .add, primaryAction: UIAction(handler: { [unowned self] _ in UIBarButtonItem(systemItem: .add, primaryAction: UIAction(handler: { [unowned self] _ in
let newTab = self.tabController.createNewTab(url: nil) self.delegate?.tabPicker(self, createNewTabWithURL: nil)
self.delegate?.tabPicker(self, didSelectTab: newTab)
}), menu: nil) }), menu: nil)
}() }()
@@ -43,10 +100,8 @@ class TabPickerViewController: UIViewController, UICollectionViewDelegate
}), menu: nil) }), menu: nil)
}() }()
init(tabController: TabController) { init() {
self.tabController = tabController
super.init(nibName: nil, bundle: nil) super.init(nibName: nil, bundle: nil)
self.title = "Tabs" self.title = "Tabs"
} }
@@ -55,83 +110,21 @@ class TabPickerViewController: UIViewController, UICollectionViewDelegate
} }
override func loadView() { override func loadView() {
var listConfig = UICollectionLayoutListConfiguration(appearance: .insetGrouped) // Load this lazy var now.
listConfig.trailingSwipeActionsConfigurationProvider = { [unowned self] indexPath in _ = cellRegistry.self
if self.dataSource?.snapshot().numberOfItems ?? 0 <= 1 {
return nil
}
listConfiguration.trailingSwipeActionsConfigurationProvider = { [unowned self] indexPath in
return UISwipeActionsConfiguration(actions: [ UIContextualAction(style: .destructive, title: "Close", handler: { [unowned self] (action, view, completionHandler) in return UISwipeActionsConfiguration(actions: [ UIContextualAction(style: .destructive, title: "Close", handler: { [unowned self] (action, view, completionHandler) in
if let item = self.dataSource?.itemIdentifier(for: indexPath), var snapshot = self.dataSource?.snapshot() { if let item = dataSource.itemIdentifier(for: indexPath) {
if let tab = self.tabController.tab(forIdentifier: item) { var snapshot = dataSource.snapshot()
self.delegate?.tabPicker(self, willCloseTab: tab) delegate?.tabPicker(self, closeTabWithIdentifier: item)
self.tabController.closeTab(tab) snapshot.deleteItems([ item ])
snapshot.deleteItems([ item ]) dataSource.apply(snapshot, animatingDifferences: true)
self.dataSource?.apply(snapshot, animatingDifferences: true)
}
} }
})]) })])
} }
let listLayout = UICollectionViewCompositionalLayout.list(using: listConfig)
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: listLayout)
collectionView.allowsMultipleSelectionDuringEditing = true
collectionView.backgroundColor = .systemGroupedBackground
let registry = UICollectionView.CellRegistration<UICollectionViewListCell, TabID> { [unowned self] (listCell, indexPath, item) in
var config = listCell.defaultContentConfiguration()
if let tab = self.tabController.tab(forIdentifier: item) {
if let title = tab.title, title.count > 0 {
config.text = title
config.secondaryText = tab.url?.absoluteString
} else if let url = tab.url {
config.text = url.absoluteString
config.secondaryText = url.absoluteString
} else {
config.text = "New Tab"
}
config.textProperties.numberOfLines = 1
config.secondaryTextProperties.numberOfLines = 1
if let image = tab.favicon {
config.image = image
} else {
config.image = UIImage(systemName: "safari")
}
config.imageProperties.maximumSize = CGSize(width: 21.0, height: 21.0)
config.imageProperties.cornerRadius = 3.0
if self.selectedTab == tab {
listCell.accessories = [ .checkmark() ]
} else {
listCell.accessories = []
}
}
listCell.contentConfiguration = config
}
let dataSource = UICollectionViewDiffableDataSource<Int, TabID>(collectionView: collectionView) { (collectionView, indexPath, item) -> UICollectionViewCell? in
return collectionView.dequeueConfiguredReusableCell(using: registry, for: indexPath, item: item)
}
collectionView.dataSource = dataSource
collectionView.delegate = self
var snapshot = dataSource.snapshot()
snapshot.appendSections([ 0 ])
tabController.tabs.forEach { tab in
snapshot.appendItems([ tab.identifier ])
}
dataSource.apply(snapshot)
self.dataSource = dataSource
self.collectionView = collectionView
self.view = self.collectionView self.view = self.collectionView
configureNavigationButtons(forEditing: isEditing) configureNavigationButtons(forEditing: isEditing)
@@ -141,7 +134,7 @@ class TabPickerViewController: UIViewController, UICollectionViewDelegate
if !forEditing { if !forEditing {
navigationItem.rightBarButtonItem = newTabButton navigationItem.rightBarButtonItem = newTabButton
} else { } else {
deleteTabButton.isEnabled = collectionView?.indexPathsForSelectedItems?.count ?? 0 > 0 deleteTabButton.isEnabled = collectionView.indexPathsForSelectedItems?.count ?? 0 > 0
navigationItem.rightBarButtonItem = deleteTabButton navigationItem.rightBarButtonItem = deleteTabButton
} }
@@ -150,43 +143,37 @@ class TabPickerViewController: UIViewController, UICollectionViewDelegate
override func setEditing(_ editing: Bool, animated: Bool) { override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated) super.setEditing(editing, animated: animated)
collectionView.isEditing = editing
if let collectionView = collectionView {
collectionView.isEditing = editing
}
configureNavigationButtons(forEditing: editing) configureNavigationButtons(forEditing: editing)
} }
private func deleteSelectedTabs() { private func deleteSelectedTabs() {
guard let dataSource = dataSource else { return }
var snapshot = dataSource.snapshot() var snapshot = dataSource.snapshot()
for tab in selectedTabsForEditing { for tab in selectedTabIdentifiersForEditing {
snapshot.deleteItems([ tab.identifier ]) snapshot.deleteItems([ tab ])
self.delegate?.tabPicker(self, willCloseTab: tab) delegate?.tabPicker(self, closeTabWithIdentifier: tab)
self.tabController.closeTab(tab)
} }
dataSource.apply(snapshot, animatingDifferences: true) dataSource.apply(snapshot, animatingDifferences: true)
} }
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let tab = tabController.tabs[indexPath.row] guard let tab = dataSource.itemIdentifier(for: indexPath) else { return }
if !isEditing { if !isEditing {
delegate?.tabPicker(self, didSelectTab: tab) delegate?.tabPicker(self, didSelectTabIdentifier: tab)
} else { } else {
deleteTabButton.isEnabled = collectionView.indexPathsForSelectedItems?.count ?? 0 > 0 deleteTabButton.isEnabled = collectionView.indexPathsForSelectedItems?.count ?? 0 > 0
selectedTabsForEditing.update(with: tab) selectedTabIdentifiersForEditing.update(with: tab)
} }
} }
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) { func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
if isEditing { guard let tabIdentifier = dataSource.itemIdentifier(for: indexPath) else { return }
let tab = tabController.tabs[indexPath.row]
selectedTabsForEditing.remove(tab)
if isEditing {
selectedTabIdentifiersForEditing.remove(tabIdentifier)
deleteTabButton.isEnabled = collectionView.indexPathsForSelectedItems?.count ?? 0 > 0 deleteTabButton.isEnabled = collectionView.indexPathsForSelectedItems?.count ?? 0 > 0
} }
} }

View File

@@ -0,0 +1,20 @@
//
// UIView+Utils.swift
// App
//
// Created by James Magahern on 8/5/22.
//
import UIKit
protocol Conf { }
extension Conf {
@discardableResult
func conf(_ block: (Self) -> Void) -> Self {
block(self)
return self
}
}
extension UIView: Conf {}

View File

@@ -57,6 +57,8 @@
CD853BCE24E7763900D2BDCC /* BrowserHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD853BCD24E7763900D2BDCC /* BrowserHistory.swift */; }; CD853BCE24E7763900D2BDCC /* BrowserHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD853BCD24E7763900D2BDCC /* BrowserHistory.swift */; };
CD853BD124E778B800D2BDCC /* History.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = CD853BCF24E778B800D2BDCC /* History.xcdatamodeld */; }; CD853BD124E778B800D2BDCC /* History.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = CD853BCF24E778B800D2BDCC /* History.xcdatamodeld */; };
CD853BD424E77BF900D2BDCC /* HistoryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD853BD324E77BF900D2BDCC /* HistoryItem.swift */; }; CD853BD424E77BF900D2BDCC /* HistoryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD853BD324E77BF900D2BDCC /* HistoryItem.swift */; };
CD936A3B289DB3380093A1AC /* TabInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD936A3A289DB3380093A1AC /* TabInfo.swift */; };
CD936A3D289DB88B0093A1AC /* UIView+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD936A3C289DB88B0093A1AC /* UIView+Utils.swift */; };
CD97CF9225D5BE6F00288FEE /* NavigationControlsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD97CF9125D5BE6F00288FEE /* NavigationControlsView.swift */; }; CD97CF9225D5BE6F00288FEE /* NavigationControlsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD97CF9125D5BE6F00288FEE /* NavigationControlsView.swift */; };
CD9B88C2272201E900DAAB7E /* SBRScriptPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = CD361CF5271A3718006E9CA5 /* SBRScriptPolicy.m */; }; CD9B88C2272201E900DAAB7E /* SBRScriptPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = CD361CF5271A3718006E9CA5 /* SBRScriptPolicy.m */; };
CDAD9CE8263A2DF200FF7199 /* DocumentControlsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDAD9CE7263A2DF200FF7199 /* DocumentControlsView.swift */; }; CDAD9CE8263A2DF200FF7199 /* DocumentControlsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDAD9CE7263A2DF200FF7199 /* DocumentControlsView.swift */; };
@@ -162,6 +164,8 @@
CD853BCD24E7763900D2BDCC /* BrowserHistory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserHistory.swift; sourceTree = "<group>"; }; CD853BCD24E7763900D2BDCC /* BrowserHistory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserHistory.swift; sourceTree = "<group>"; };
CD853BD024E778B800D2BDCC /* History.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = History.xcdatamodel; sourceTree = "<group>"; }; CD853BD024E778B800D2BDCC /* History.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = History.xcdatamodel; sourceTree = "<group>"; };
CD853BD324E77BF900D2BDCC /* HistoryItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryItem.swift; sourceTree = "<group>"; }; CD853BD324E77BF900D2BDCC /* HistoryItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryItem.swift; sourceTree = "<group>"; };
CD936A3A289DB3380093A1AC /* TabInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabInfo.swift; sourceTree = "<group>"; };
CD936A3C289DB88B0093A1AC /* UIView+Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Utils.swift"; sourceTree = "<group>"; };
CD97CF9125D5BE6F00288FEE /* NavigationControlsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationControlsView.swift; sourceTree = "<group>"; }; CD97CF9125D5BE6F00288FEE /* NavigationControlsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationControlsView.swift; sourceTree = "<group>"; };
CDAD9CE7263A2DF200FF7199 /* DocumentControlsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentControlsView.swift; sourceTree = "<group>"; }; CDAD9CE7263A2DF200FF7199 /* DocumentControlsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentControlsView.swift; sourceTree = "<group>"; };
CDAD9CE9263A318F00FF7199 /* ShareableURL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareableURL.swift; sourceTree = "<group>"; }; CDAD9CE9263A318F00FF7199 /* ShareableURL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareableURL.swift; sourceTree = "<group>"; };
@@ -227,6 +231,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
1A14FC2724D26749009B3F83 /* Tab.swift */, 1A14FC2724D26749009B3F83 /* Tab.swift */,
CD936A3A289DB3380093A1AC /* TabInfo.swift */,
CD01D5A4254A10BB00189CDC /* TabBarView.swift */, CD01D5A4254A10BB00189CDC /* TabBarView.swift */,
CD01D5AA254A206D00189CDC /* TabBarViewController.swift */, CD01D5AA254A206D00189CDC /* TabBarViewController.swift */,
1AB88EFC24D3BA560006F850 /* TabController.swift */, 1AB88EFC24D3BA560006F850 /* TabController.swift */,
@@ -375,6 +380,7 @@
1ADFF4C624CA6DEB006DC7AE /* UIEdgeInsets+Layout.swift */, 1ADFF4C624CA6DEB006DC7AE /* UIEdgeInsets+Layout.swift */,
1AB88F0524D4D3A90006F850 /* UIGestureRecognizer+Actions.swift */, 1AB88F0524D4D3A90006F850 /* UIGestureRecognizer+Actions.swift */,
CDEDD8A925D62ADB00862605 /* UITraitCollection+MacLike.swift */, CDEDD8A925D62ADB00862605 /* UITraitCollection+MacLike.swift */,
CD936A3C289DB88B0093A1AC /* UIView+Utils.swift */,
); );
path = Utilities; path = Utilities;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -585,6 +591,7 @@
CD470C4225DE056600AFBE0E /* BrowserViewController+WebKitDelegate.swift in Sources */, CD470C4225DE056600AFBE0E /* BrowserViewController+WebKitDelegate.swift in Sources */,
CDEDD8AA25D62ADB00862605 /* UITraitCollection+MacLike.swift in Sources */, CDEDD8AA25D62ADB00862605 /* UITraitCollection+MacLike.swift in Sources */,
CD7A8919251989C90075991E /* UIKeyCommand+ConvInit.swift in Sources */, CD7A8919251989C90075991E /* UIKeyCommand+ConvInit.swift in Sources */,
CD936A3B289DB3380093A1AC /* TabInfo.swift in Sources */,
1ADFF4C724CA6DEB006DC7AE /* UIEdgeInsets+Layout.swift in Sources */, 1ADFF4C724CA6DEB006DC7AE /* UIEdgeInsets+Layout.swift in Sources */,
1ADFF4AE24C8ED32006DC7AE /* ResourcePolicyManager.swift in Sources */, 1ADFF4AE24C8ED32006DC7AE /* ResourcePolicyManager.swift in Sources */,
1ADFF47424C7DE9C006DC7AE /* BrowserViewController.swift in Sources */, 1ADFF47424C7DE9C006DC7AE /* BrowserViewController.swift in Sources */,
@@ -592,6 +599,7 @@
CDCE2668251AAA9A007FE92A /* FontSizeAdjustView.swift in Sources */, CDCE2668251AAA9A007FE92A /* FontSizeAdjustView.swift in Sources */,
CD01D5A5254A10BB00189CDC /* TabBarView.swift in Sources */, CD01D5A5254A10BB00189CDC /* TabBarView.swift in Sources */,
1A03810D24E71CA700826501 /* ToolbarView.swift in Sources */, 1A03810D24E71CA700826501 /* ToolbarView.swift in Sources */,
CD936A3D289DB88B0093A1AC /* UIView+Utils.swift in Sources */,
CD470C4425DE070400AFBE0E /* BrowserViewController+Keyboard.swift in Sources */, CD470C4425DE070400AFBE0E /* BrowserViewController+Keyboard.swift in Sources */,
CDD0522425F8055700DD1771 /* SearchProvider.swift in Sources */, CDD0522425F8055700DD1771 /* SearchProvider.swift in Sources */,
CD853BD424E77BF900D2BDCC /* HistoryItem.swift in Sources */, CD853BD424E77BF900D2BDCC /* HistoryItem.swift in Sources */,