|
@@ -120,6 +120,10 @@ final class InAppBrowserWindowController: NSWindowController, NSWindowDelegate {
|
|
|
private var siteNameLabel: NSTextField!
|
|
private var siteNameLabel: NSTextField!
|
|
|
private var siteIconView: NSImageView!
|
|
private var siteIconView: NSImageView!
|
|
|
private var currentSiteIconURLKey: String?
|
|
private var currentSiteIconURLKey: String?
|
|
|
|
|
+ /// Keeps the center title in sync when `document.title` changes after load (e.g. SPAs).
|
|
|
|
|
+ private var titleObservation: NSKeyValueObservation?
|
|
|
|
|
+ /// Refreshes site identity when loading starts/stops.
|
|
|
|
|
+ private var loadingObservation: NSKeyValueObservation?
|
|
|
private var isPinnedOnTop = false
|
|
private var isPinnedOnTop = false
|
|
|
private var isGestureModeEnabled = true
|
|
private var isGestureModeEnabled = true
|
|
|
|
|
|
|
@@ -314,12 +318,18 @@ final class InAppBrowserWindowController: NSWindowController, NSWindowDelegate {
|
|
|
webView.uiDelegate = self
|
|
webView.uiDelegate = self
|
|
|
webView.navigationDelegate = self
|
|
webView.navigationDelegate = self
|
|
|
webView.allowsBackForwardNavigationGestures = true
|
|
webView.allowsBackForwardNavigationGestures = true
|
|
|
|
|
+ titleObservation = webView.observe(\.title, options: [.new]) { [weak self] _, _ in
|
|
|
|
|
+ self?.updateSiteNameFromWebView()
|
|
|
|
|
+ }
|
|
|
|
|
+ loadingObservation = webView.observe(\.isLoading, options: [.new]) { [weak self] _, _ in
|
|
|
|
|
+ self?.updateSiteNameFromWebView()
|
|
|
|
|
+ }
|
|
|
isGestureModeEnabled = true
|
|
isGestureModeEnabled = true
|
|
|
|
|
|
|
|
// Initialize toolbar state.
|
|
// Initialize toolbar state.
|
|
|
setToggledStyle(pinButton, isOn: isPinnedOnTop)
|
|
setToggledStyle(pinButton, isOn: isPinnedOnTop)
|
|
|
setToggledStyle(handButton, isOn: isGestureModeEnabled)
|
|
setToggledStyle(handButton, isOn: isGestureModeEnabled)
|
|
|
- siteNameLabel.stringValue = windowTitle ?? (initialURL.host ?? "Browser")
|
|
|
|
|
|
|
+ siteNameLabel.stringValue = windowTitle ?? "Browser"
|
|
|
updateToolbarState()
|
|
updateToolbarState()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -531,10 +541,36 @@ final class InAppBrowserWindowController: NSWindowController, NSWindowDelegate {
|
|
|
window?.performClose(nil)
|
|
window?.performClose(nil)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /// WKWebView often reports the requested URL as `title` until the real document title is available.
|
|
|
|
|
+ private func isLikelyURLString(_ raw: String) -> Bool {
|
|
|
|
|
+ let t = raw.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
|
|
|
+ if t.isEmpty { return false }
|
|
|
|
|
+ if t.hasPrefix("http://") || t.hasPrefix("https://") { return true }
|
|
|
|
|
+ if t.contains("://") { return true }
|
|
|
|
|
+ if let u = URL(string: t), u.scheme != nil, u.host != nil { return true }
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private func updateSiteNameFromWebView() {
|
|
private func updateSiteNameFromWebView() {
|
|
|
|
|
+ let loading = webView.isLoading
|
|
|
let host = webView.url?.host?.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
let host = webView.url?.host?.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
|
- let pageTitle = webView.title?.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
|
|
|
- let preferred = (host?.isEmpty == false) ? host! : ((pageTitle?.isEmpty == false) ? pageTitle! : "Browser")
|
|
|
|
|
|
|
+ let rawTitle = webView.title?.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
|
|
|
+ let pageTitle: String? = {
|
|
|
|
|
+ guard let rawTitle, !rawTitle.isEmpty else { return nil }
|
|
|
|
|
+ return isLikelyURLString(rawTitle) ? nil : rawTitle
|
|
|
|
|
+ }()
|
|
|
|
|
+
|
|
|
|
|
+ // Prefer document title; never show hostname or URL-like strings while a load is in progress.
|
|
|
|
|
+ let preferred: String
|
|
|
|
|
+ if let pageTitle {
|
|
|
|
|
+ preferred = pageTitle
|
|
|
|
|
+ } else if loading {
|
|
|
|
|
+ preferred = "Loading…"
|
|
|
|
|
+ } else if let host, !host.isEmpty {
|
|
|
|
|
+ preferred = host
|
|
|
|
|
+ } else {
|
|
|
|
|
+ preferred = "Browser"
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
siteNameLabel.stringValue = preferred
|
|
siteNameLabel.stringValue = preferred
|
|
|
window?.title = preferred
|
|
window?.title = preferred
|
|
@@ -602,10 +638,6 @@ extension InAppBrowserWindowController: WKNavigationDelegate {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
|
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
|
|
- if let host = webView.url?.host, !host.isEmpty {
|
|
|
|
|
- window?.title = host
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
updateToolbarState()
|
|
updateToolbarState()
|
|
|
}
|
|
}
|
|
|
|
|
|