Selaa lähdekoodia

Show home for logged-in users and add logout flow.

Persist login state to route startup directly to Home, and add a Logout control that clears saved OAuth tokens and returns to Login.

Made-with: Cursor
huzaifahayat12 3 kuukautta sitten
vanhempi
sitoutus
fd311d1562
1 muutettua tiedostoa jossa 43 lisäystä ja 2 poistoa
  1. 43 2
      zoom_app/ViewController.swift

+ 43 - 2
zoom_app/ViewController.swift

@@ -13,6 +13,7 @@ import WebKit
 class ViewController: NSViewController {
     private let googleOAuth = GoogleOAuthService.shared
     private let zoomOAuth = ZoomOAuthService.shared
+    private let loginStateKey = "zoom_app.isLoggedIn"
     private let sidebarWidth: CGFloat = 78
     private let appBackground = NSColor(calibratedRed: 10 / 255, green: 11 / 255, blue: 12 / 255, alpha: 1)
     private let sidebarBackground = NSColor(calibratedRed: 16 / 255, green: 17 / 255, blue: 19 / 255, alpha: 1)
@@ -49,7 +50,11 @@ class ViewController: NSViewController {
         super.viewDidAppear()
         view.window?.setContentSize(NSSize(width: 1020, height: 690))
         view.window?.title = "zoom Workplace"
-        showLoginView()
+        if isUserLoggedIn() {
+            showHomeView(profile: nil)
+        } else {
+            showLoginView()
+        }
     }
 
     private func setupUI() {
@@ -87,10 +92,19 @@ class ViewController: NSViewController {
         homeView?.removeFromSuperview()
         homeView = makeHomeView(profile: profile)
         if let homeView { attachToRoot(homeView) }
+        persistLoggedInState(true)
         startClock()
         Task { await loadScheduledMeetings() }
     }
 
+    private func isUserLoggedIn() -> Bool {
+        UserDefaults.standard.bool(forKey: loginStateKey)
+    }
+
+    private func persistLoggedInState(_ loggedIn: Bool) {
+        UserDefaults.standard.set(loggedIn, forKey: loginStateKey)
+    }
+
     private func attachToRoot(_ subview: NSView) {
         subview.translatesAutoresizingMaskIntoConstraints = false
         if subview.superview != rootContainer {
@@ -173,6 +187,13 @@ class ViewController: NSViewController {
         }
     }
 
+    @objc private func logoutTapped() {
+        googleOAuth.clearSavedTokens()
+        zoomOAuth.clearSavedTokens()
+        persistLoggedInState(false)
+        showLoginView()
+    }
+
     @MainActor
     private func resetLoginSigningInState() {
         isSigningIn = false
@@ -556,6 +577,13 @@ class ViewController: NSViewController {
         profileChip.layer?.backgroundColor = accentBlue.withAlphaComponent(0.22).cgColor
         profileChip.layer?.cornerRadius = 9
         let name = makeLabel(profile?.name ?? "User", size: 13, color: primaryText, weight: .semibold, centered: false)
+        let logoutButton = NSButton(title: "Logout", target: self, action: #selector(logoutTapped))
+        logoutButton.isBordered = false
+        logoutButton.font = .systemFont(ofSize: 13, weight: .semibold)
+        logoutButton.contentTintColor = primaryText
+        logoutButton.wantsLayer = true
+        logoutButton.layer?.backgroundColor = NSColor.white.withAlphaComponent(0.07).cgColor
+        logoutButton.layer?.cornerRadius = 8
 
         let welcome = makeLabel("Home", size: 15, color: secondaryText, weight: .medium, centered: false)
         let timeTitle = makeLabel("--:--", size: 50, color: primaryText, weight: .bold, centered: true)
@@ -610,7 +638,7 @@ class ViewController: NSViewController {
         contentColumn.translatesAutoresizingMaskIntoConstraints = false
         content.addSubview(contentColumn)
 
-        [topBar, searchPill, search, profileChip, name, welcome, timeTitle, dateTitle, actions, panel, panelHeader, meetingsStatus, noMeeting, meetingsScrollView, openRecordings].forEach {
+        [topBar, searchPill, search, profileChip, name, logoutButton, welcome, timeTitle, dateTitle, actions, panel, panelHeader, meetingsStatus, noMeeting, meetingsScrollView, openRecordings].forEach {
             $0.translatesAutoresizingMaskIntoConstraints = false
             contentColumn.addSubview($0)
         }
@@ -646,6 +674,11 @@ class ViewController: NSViewController {
             name.trailingAnchor.constraint(equalTo: profileChip.trailingAnchor, constant: -12),
             name.centerYAnchor.constraint(equalTo: profileChip.centerYAnchor),
 
+            logoutButton.trailingAnchor.constraint(equalTo: profileChip.leadingAnchor, constant: -10),
+            logoutButton.centerYAnchor.constraint(equalTo: topBar.centerYAnchor),
+            logoutButton.widthAnchor.constraint(equalToConstant: 76),
+            logoutButton.heightAnchor.constraint(equalToConstant: 32),
+
             welcome.topAnchor.constraint(equalTo: topBar.bottomAnchor, constant: 18),
             welcome.centerXAnchor.constraint(equalTo: contentColumn.centerXAnchor),
 
@@ -1154,6 +1187,10 @@ final class GoogleOAuthService: NSObject {
 
     func loadTokens() -> GoogleOAuthTokens? { try? tokenStore.readTokens() }
 
+    func clearSavedTokens() {
+        tokenStore.clearTokens()
+    }
+
     func fetchUserProfile(accessToken: String) async throws -> GoogleUserProfile {
         var request = URLRequest(url: URL(string: "https://openidconnect.googleapis.com/v1/userinfo")!)
         request.httpMethod = "GET"
@@ -1299,6 +1336,10 @@ final class KeychainTokenStore {
         let data = try JSONEncoder().encode(tokens)
         defaults.set(data, forKey: defaultsKey)
     }
+
+    func clearTokens() {
+        defaults.removeObject(forKey: defaultsKey)
+    }
 }
 
 private final class OAuthLoopbackServer {