TabPickerViewController: Refactor to not reference tab controller directly.
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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 }
|
||||||
|
|||||||
@@ -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
21
App/Tabs/TabInfo.swift
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
20
App/Utilities/UIView+Utils.swift
Normal file
20
App/Utilities/UIView+Utils.swift
Normal 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 {}
|
||||||
@@ -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 */,
|
||||||
|
|||||||
Reference in New Issue
Block a user