Files
Attractor/App/Tabs/TabController.swift

100 lines
3.3 KiB
Swift
Raw Normal View History

//
// 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 tab(forWebView webView: WKWebView) -> Tab? {
tabs.first { $0.webView == webView }
}
func createNewTab(url: URL?) -> Tab {
2020-09-24 16:36:31 -07:00
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)
}
2025-09-08 21:20:15 -07:00
// Title observation: update snapshot and notify delegate.
tab.titleObservation = tab.webView.observe(\.title, changeHandler: { [weak tab, weak self] (webView, change) in
2025-09-08 21:20:15 -07:00
guard let tab = tab else { return }
if let newTitle = webView.title, !newTitle.isEmpty {
tab._tabInfo.title = newTitle
}
if let self = self, let delegate = self.controllerDelegate {
delegate.tabController(self, didUpdateTitle: webView.title ?? "", forTab: tab)
}
})
2025-09-08 21:20:15 -07:00
// URL observation: persist the latest URL in the snapshot.
tab.urlObservation = tab.webView.observe(\.url, changeHandler: { [weak tab] (webView, change) in
guard let tab = tab else { return }
tab._tabInfo.urlString = webView.url?.absoluteString ?? tab._tabInfo.urlString
})
// Favicon Observation
tab.faviconObservation = tab.$favicon.receive(on: RunLoop.main).sink { [weak tab, weak self] val in
2025-09-08 21:20:15 -07:00
guard let tab = tab else { return }
tab._tabInfo.faviconData = val?.pngData()
if 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
}
}
}
}