Pārlūkot izejas kodu

Move in-app browser controls into titlebar

Hide the old browser toolbar, center the page title in the titlebar, and add back/forward/reload/home controls next to the traffic lights for a cleaner native macOS browser window.

Made-with: Cursor
huzaifahayat12 1 nedēļu atpakaļ
vecāks
revīzija
47c64e1330
1 mainītis faili ar 104 papildinājumiem un 2 dzēšanām
  1. 104 2
      classroom_app/ViewController.swift

+ 104 - 2
classroom_app/ViewController.swift

@@ -6967,6 +6967,12 @@ private final class InAppBrowserContainerViewController: NSViewController, WKNav
6967
     private var reloadStopButton: NSButton!
6967
     private var reloadStopButton: NSButton!
6968
     private var goButton: NSButton!
6968
     private var goButton: NSButton!
6969
     private var progressBar: NSProgressIndicator!
6969
     private var progressBar: NSProgressIndicator!
6970
+    private weak var centeredTitleLabel: NSTextField?
6971
+    private weak var titlebarButtonsContainer: NSStackView?
6972
+    private weak var titlebarBackButton: NSButton?
6973
+    private weak var titlebarForwardButton: NSButton?
6974
+    private weak var titlebarReloadButton: NSButton?
6975
+    private weak var titlebarHomeButton: NSButton?
6970
 
6976
 
6971
     private var lastLoadedURL: URL?
6977
     private var lastLoadedURL: URL?
6972
     private var navigationPolicy: InAppBrowserURLPolicy = .allowAll
6978
     private var navigationPolicy: InAppBrowserURLPolicy = .allowAll
@@ -7008,6 +7014,7 @@ private final class InAppBrowserContainerViewController: NSViewController, WKNav
7008
         toolbar.spacing = 8
7014
         toolbar.spacing = 8
7009
         toolbar.alignment = .centerY
7015
         toolbar.alignment = .centerY
7010
         toolbar.edgeInsets = NSEdgeInsets(top: 6, left: 10, bottom: 6, right: 10)
7016
         toolbar.edgeInsets = NSEdgeInsets(top: 6, left: 10, bottom: 6, right: 10)
7017
+        toolbar.isHidden = true
7011
 
7018
 
7012
         backButton = makeToolbarButton(title: "◀", symbolName: "chevron.backward", accessibilityDescription: "Back")
7019
         backButton = makeToolbarButton(title: "◀", symbolName: "chevron.backward", accessibilityDescription: "Back")
7013
         backButton.target = self
7020
         backButton.target = self
@@ -7037,6 +7044,7 @@ private final class InAppBrowserContainerViewController: NSViewController, WKNav
7037
         toolbar.addArrangedSubview(field)
7044
         toolbar.addArrangedSubview(field)
7038
         toolbar.addArrangedSubview(goButton)
7045
         toolbar.addArrangedSubview(goButton)
7039
         field.widthAnchor.constraint(greaterThanOrEqualToConstant: 240).isActive = true
7046
         field.widthAnchor.constraint(greaterThanOrEqualToConstant: 240).isActive = true
7047
+        toolbar.heightAnchor.constraint(equalToConstant: 0).isActive = true
7040
 
7048
 
7041
         let bar = NSProgressIndicator()
7049
         let bar = NSProgressIndicator()
7042
         bar.translatesAutoresizingMaskIntoConstraints = false
7050
         bar.translatesAutoresizingMaskIntoConstraints = false
@@ -7067,7 +7075,7 @@ private final class InAppBrowserContainerViewController: NSViewController, WKNav
7067
 
7075
 
7068
             bar.leadingAnchor.constraint(equalTo: root.leadingAnchor),
7076
             bar.leadingAnchor.constraint(equalTo: root.leadingAnchor),
7069
             bar.trailingAnchor.constraint(equalTo: root.trailingAnchor),
7077
             bar.trailingAnchor.constraint(equalTo: root.trailingAnchor),
7070
-            bar.topAnchor.constraint(equalTo: toolbar.bottomAnchor),
7078
+            bar.topAnchor.constraint(equalTo: root.topAnchor),
7071
             bar.heightAnchor.constraint(equalToConstant: 3),
7079
             bar.heightAnchor.constraint(equalToConstant: 3),
7072
 
7080
 
7073
             separator.leadingAnchor.constraint(equalTo: root.leadingAnchor),
7081
             separator.leadingAnchor.constraint(equalTo: root.leadingAnchor),
@@ -7085,6 +7093,16 @@ private final class InAppBrowserContainerViewController: NSViewController, WKNav
7085
         syncToolbarFromWebView()
7093
         syncToolbarFromWebView()
7086
     }
7094
     }
7087
 
7095
 
7096
+    override func viewDidAppear() {
7097
+        super.viewDidAppear()
7098
+        if let window = view.window {
7099
+            installTitlebarButtonsIfNeeded(on: window)
7100
+            installCenteredTitleIfNeeded(on: window)
7101
+            syncWindowTitle()
7102
+            syncToolbarFromWebView()
7103
+        }
7104
+    }
7105
+
7088
     private func makeWebView() -> WKWebView {
7106
     private func makeWebView() -> WKWebView {
7089
         let wv = WKWebView(frame: .zero, configuration: InAppBrowserWebKitSupport.makeWebViewConfiguration())
7107
         let wv = WKWebView(frame: .zero, configuration: InAppBrowserWebKitSupport.makeWebViewConfiguration())
7090
         wv.translatesAutoresizingMaskIntoConstraints = false
7108
         wv.translatesAutoresizingMaskIntoConstraints = false
@@ -7157,21 +7175,31 @@ private final class InAppBrowserContainerViewController: NSViewController, WKNav
7157
     private func syncToolbarFromWebView() {
7175
     private func syncToolbarFromWebView() {
7158
         backButton?.isEnabled = webView.canGoBack
7176
         backButton?.isEnabled = webView.canGoBack
7159
         forwardButton?.isEnabled = webView.canGoForward
7177
         forwardButton?.isEnabled = webView.canGoForward
7178
+        titlebarBackButton?.isEnabled = webView.canGoBack
7179
+        titlebarForwardButton?.isEnabled = webView.canGoForward
7160
         if webView.isLoading {
7180
         if webView.isLoading {
7161
             if #available(macOS 11.0, *), let img = NSImage(systemSymbolName: "xmark", accessibilityDescription: "Stop") {
7181
             if #available(macOS 11.0, *), let img = NSImage(systemSymbolName: "xmark", accessibilityDescription: "Stop") {
7162
                 reloadStopButton.image = img
7182
                 reloadStopButton.image = img
7163
                 reloadStopButton.imagePosition = .imageOnly
7183
                 reloadStopButton.imagePosition = .imageOnly
7164
                 reloadStopButton.title = ""
7184
                 reloadStopButton.title = ""
7185
+                titlebarReloadButton?.image = img
7186
+                titlebarReloadButton?.imagePosition = .imageOnly
7187
+                titlebarReloadButton?.title = ""
7165
             } else {
7188
             } else {
7166
                 reloadStopButton.title = "Stop"
7189
                 reloadStopButton.title = "Stop"
7190
+                titlebarReloadButton?.title = "Stop"
7167
             }
7191
             }
7168
         } else {
7192
         } else {
7169
             if #available(macOS 11.0, *), let img = NSImage(systemSymbolName: "arrow.clockwise", accessibilityDescription: "Reload") {
7193
             if #available(macOS 11.0, *), let img = NSImage(systemSymbolName: "arrow.clockwise", accessibilityDescription: "Reload") {
7170
                 reloadStopButton.image = img
7194
                 reloadStopButton.image = img
7171
                 reloadStopButton.imagePosition = .imageOnly
7195
                 reloadStopButton.imagePosition = .imageOnly
7172
                 reloadStopButton.title = ""
7196
                 reloadStopButton.title = ""
7197
+                titlebarReloadButton?.image = img
7198
+                titlebarReloadButton?.imagePosition = .imageOnly
7199
+                titlebarReloadButton?.title = ""
7173
             } else {
7200
             } else {
7174
                 reloadStopButton.title = "Reload"
7201
                 reloadStopButton.title = "Reload"
7202
+                titlebarReloadButton?.title = "Reload"
7175
             }
7203
             }
7176
         }
7204
         }
7177
         syncProgressFromWebView()
7205
         syncProgressFromWebView()
@@ -7196,7 +7224,76 @@ private final class InAppBrowserContainerViewController: NSViewController, WKNav
7196
     private func syncWindowTitle() {
7224
     private func syncWindowTitle() {
7197
         let t = webView.title?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
7225
         let t = webView.title?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
7198
         let host = webView.url?.host ?? ""
7226
         let host = webView.url?.host ?? ""
7199
-        view.window?.title = t.isEmpty ? (host.isEmpty ? "Browser" : host) : t
7227
+        let title = t.isEmpty ? (host.isEmpty ? "Browser" : host) : t
7228
+        view.window?.title = title
7229
+        centeredTitleLabel?.stringValue = title
7230
+    }
7231
+
7232
+    private func installCenteredTitleIfNeeded(on window: NSWindow) {
7233
+        guard centeredTitleLabel == nil else { return }
7234
+        guard let titlebarView = window.standardWindowButton(.closeButton)?.superview else { return }
7235
+
7236
+        let label = NSTextField(labelWithString: window.title)
7237
+        label.translatesAutoresizingMaskIntoConstraints = false
7238
+        label.alignment = .center
7239
+        label.font = NSFont.titleBarFont(ofSize: 0)
7240
+        label.textColor = .labelColor
7241
+        label.lineBreakMode = .byTruncatingTail
7242
+        label.maximumNumberOfLines = 1
7243
+
7244
+        titlebarView.addSubview(label)
7245
+
7246
+        NSLayoutConstraint.activate([
7247
+            label.centerXAnchor.constraint(equalTo: titlebarView.centerXAnchor),
7248
+            label.centerYAnchor.constraint(equalTo: titlebarView.centerYAnchor),
7249
+            label.leadingAnchor.constraint(greaterThanOrEqualTo: titlebarView.leadingAnchor, constant: 220),
7250
+            label.trailingAnchor.constraint(lessThanOrEqualTo: titlebarView.trailingAnchor, constant: -90)
7251
+        ])
7252
+
7253
+        window.titleVisibility = .hidden
7254
+        centeredTitleLabel = label
7255
+    }
7256
+
7257
+    private func installTitlebarButtonsIfNeeded(on window: NSWindow) {
7258
+        guard titlebarButtonsContainer == nil else { return }
7259
+        guard let titlebarView = window.standardWindowButton(.closeButton)?.superview else { return }
7260
+        guard let zoomButton = window.standardWindowButton(.zoomButton) else { return }
7261
+
7262
+        let stack = NSStackView()
7263
+        stack.translatesAutoresizingMaskIntoConstraints = false
7264
+        stack.orientation = .horizontal
7265
+        stack.alignment = .centerY
7266
+        stack.spacing = 6
7267
+
7268
+        let back = makeToolbarButton(title: "◀", symbolName: "chevron.backward", accessibilityDescription: "Back")
7269
+        back.target = self
7270
+        back.action = #selector(goBack)
7271
+        let forward = makeToolbarButton(title: "▶", symbolName: "chevron.forward", accessibilityDescription: "Forward")
7272
+        forward.target = self
7273
+        forward.action = #selector(goForward)
7274
+        let reload = makeToolbarButton(title: "Reload", symbolName: "arrow.clockwise", accessibilityDescription: "Reload")
7275
+        reload.target = self
7276
+        reload.action = #selector(reloadOrStop)
7277
+        let home = makeToolbarButton(title: "Home", symbolName: "house", accessibilityDescription: "Home")
7278
+        home.target = self
7279
+        home.action = #selector(goHome)
7280
+
7281
+        stack.addArrangedSubview(back)
7282
+        stack.addArrangedSubview(forward)
7283
+        stack.addArrangedSubview(reload)
7284
+        stack.addArrangedSubview(home)
7285
+        titlebarView.addSubview(stack)
7286
+
7287
+        NSLayoutConstraint.activate([
7288
+            stack.leadingAnchor.constraint(equalTo: zoomButton.trailingAnchor, constant: 12),
7289
+            stack.centerYAnchor.constraint(equalTo: zoomButton.centerYAnchor)
7290
+        ])
7291
+
7292
+        titlebarButtonsContainer = stack
7293
+        titlebarBackButton = back
7294
+        titlebarForwardButton = forward
7295
+        titlebarReloadButton = reload
7296
+        titlebarHomeButton = home
7200
     }
7297
     }
7201
 
7298
 
7202
     func load(url: URL) {
7299
     func load(url: URL) {
@@ -7223,6 +7320,11 @@ private final class InAppBrowserContainerViewController: NSViewController, WKNav
7223
         }
7320
         }
7224
     }
7321
     }
7225
 
7322
 
7323
+    @objc private func goHome() {
7324
+        guard let homeURL = URL(string: "https://classroom.google.com/") else { return }
7325
+        load(url: homeURL)
7326
+    }
7327
+
7226
     @objc private func addressFieldSubmitted() {
7328
     @objc private func addressFieldSubmitted() {
7227
         let raw = urlField?.stringValue.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
7329
         let raw = urlField?.stringValue.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
7228
         guard raw.isEmpty == false else { return }
7330
         guard raw.isEmpty == false else { return }