// // TabController.swift // SBrowser // // Created by James Magahern on 7/30/20. // import Foundation protocol TabControllerDelegate: AnyObject { func tabController(_ controller: TabController, didUpdateTitle: String, forTab: Tab) func tabController(_ controller: TabController, didUpdateFavicon: UIImage?, forTab: Tab) } class TabController { @Published var tabs: [Tab] = [] @Published var activeTabIndex: Int = 0 var policyManager = ResourcePolicyManager() weak var controllerDelegate: TabControllerDelegate? init() { // TODO: load tabs from disk. _ = createNewTab(url: nil) } func tab(forURL url: URL) -> Tab? { tabs.first { $0.url == url } } func tab(forIdentifier identifier: UUID) -> Tab? { tabs.first { $0.identifier == identifier } } func createNewTab(url: URL?) -> Tab { return self.createNewTab(url: url, webViewConfiguration: nil) } func createNewTab(url: URL?, webViewConfiguration: WKWebViewConfiguration?) -> Tab { let tab = Tab(url: url, policyManager: policyManager, webViewConfiguration: webViewConfiguration) if tabs.count > 0 { tabs.insert(tab, at: activeTabIndex + 1) } else { tabs.append(tab) } // Title observation tab.titleObservation = tab.webView.observe(\.title, changeHandler: { [weak tab, weak self] (webView, change) in if let tab = tab, let self = self, let delegate = self.controllerDelegate { delegate.tabController(self, didUpdateTitle: webView.title ?? "", forTab: tab) } }) // Favicon Observation tab.faviconObservation = tab.$favicon.receive(on: RunLoop.main).sink { [weak tab, weak self] val in if let tab = tab, let self = self, let delegate = self.controllerDelegate { delegate.tabController(self, didUpdateFavicon: val, forTab: tab) } } return tab } func closeTab(_ tab: Tab) { if let index = tabs.firstIndex(of: tab) { tabs.remove(at: index) if tabs.count > 0 { if (index - 1) >= 0 { activeTabIndex = index - 1 } else if index < tabs.count { activeTabIndex = index } else { activeTabIndex = tabs.count - 1 } } else { _ = createNewTab(url: nil) activeTabIndex = 0 } } } }