From 32a4d85af937e4fd882fa671aee8b72878cc564f Mon Sep 17 00:00:00 2001 From: 苏向夜 Date: Sun, 29 Mar 2026 00:58:15 +0800 Subject: feat(ui): remove all stores --- packages/ui/src/stores/auth-store.ts | 296 ----------------------------------- 1 file changed, 296 deletions(-) delete mode 100644 packages/ui/src/stores/auth-store.ts (limited to 'packages/ui/src/stores/auth-store.ts') diff --git a/packages/ui/src/stores/auth-store.ts b/packages/ui/src/stores/auth-store.ts deleted file mode 100644 index bf7e3c5..0000000 --- a/packages/ui/src/stores/auth-store.ts +++ /dev/null @@ -1,296 +0,0 @@ -import { invoke } from "@tauri-apps/api/core"; -import { listen, type UnlistenFn } from "@tauri-apps/api/event"; -import { open } from "@tauri-apps/plugin-shell"; -import { toast } from "sonner"; -import { create } from "zustand"; -import type { Account, DeviceCodeResponse } from "../types/bindings/auth"; - -interface AuthState { - // State - currentAccount: Account | null; - isLoginModalOpen: boolean; - isLogoutConfirmOpen: boolean; - loginMode: "select" | "offline" | "microsoft"; - offlineUsername: string; - deviceCodeData: DeviceCodeResponse | null; - msLoginLoading: boolean; - msLoginStatus: string; - - // Private state - pollInterval: ReturnType | null; - isPollingRequestActive: boolean; - authProgressUnlisten: UnlistenFn | null; - - // Actions - checkAccount: () => Promise; - openLoginModal: () => void; - openLogoutConfirm: () => void; - cancelLogout: () => void; - confirmLogout: () => Promise; - closeLoginModal: () => void; - resetLoginState: () => void; - performOfflineLogin: () => Promise; - startMicrosoftLogin: () => Promise; - checkLoginStatus: (deviceCode: string) => Promise; - stopPolling: () => void; - cancelMicrosoftLogin: () => void; - setLoginMode: (mode: "select" | "offline" | "microsoft") => void; - setOfflineUsername: (username: string) => void; -} - -export const useAuthStore = create((set, get) => ({ - // Initial state - currentAccount: null, - isLoginModalOpen: false, - isLogoutConfirmOpen: false, - loginMode: "select", - offlineUsername: "", - deviceCodeData: null, - msLoginLoading: false, - msLoginStatus: "Waiting for authorization...", - - // Private state - pollInterval: null, - isPollingRequestActive: false, - authProgressUnlisten: null, - - // Actions - checkAccount: async () => { - try { - const acc = await invoke("get_active_account"); - set({ currentAccount: acc }); - } catch (error) { - console.error("Failed to check account:", error); - } - }, - - openLoginModal: () => { - const { currentAccount } = get(); - if (currentAccount) { - // Show custom logout confirmation dialog - set({ isLogoutConfirmOpen: true }); - return; - } - get().resetLoginState(); - set({ isLoginModalOpen: true }); - }, - - openLogoutConfirm: () => { - set({ isLogoutConfirmOpen: true }); - }, - - cancelLogout: () => { - set({ isLogoutConfirmOpen: false }); - }, - - confirmLogout: async () => { - set({ isLogoutConfirmOpen: false }); - try { - await invoke("logout"); - set({ currentAccount: null }); - } catch (error) { - console.error("Logout failed:", error); - } - }, - - closeLoginModal: () => { - get().stopPolling(); - set({ isLoginModalOpen: false }); - }, - - resetLoginState: () => { - set({ - loginMode: "select", - offlineUsername: "", - deviceCodeData: null, - msLoginLoading: false, - msLoginStatus: "Waiting for authorization...", - }); - }, - - performOfflineLogin: async () => { - const { offlineUsername } = get(); - if (!offlineUsername.trim()) return; - - try { - const account = await invoke("login_offline", { - username: offlineUsername, - }); - set({ - currentAccount: account, - isLoginModalOpen: false, - offlineUsername: "", - }); - } catch (error) { - // Keep UI-friendly behavior consistent with prior code - alert("Login failed: " + String(error)); - } - }, - - startMicrosoftLogin: async () => { - // Prepare UI state - set({ - msLoginLoading: true, - msLoginStatus: "Waiting for authorization...", - loginMode: "microsoft", - deviceCodeData: null, - }); - - // Listen to general launcher logs so we can display progress to the user. - // The backend emits logs via "launcher-log"; using that keeps this store decoupled - // from a dedicated auth event channel (backend may reuse launcher-log). - try { - const unlisten = await listen("launcher-log", (event) => { - const payload = event.payload; - // Normalize payload to string if possible - const message = - typeof payload === "string" - ? payload - : (payload?.toString?.() ?? JSON.stringify(payload)); - set({ msLoginStatus: message }); - }); - set({ authProgressUnlisten: unlisten }); - } catch (err) { - console.warn("Failed to attach launcher-log listener:", err); - } - - try { - const deviceCodeData = await invoke( - "start_microsoft_login", - ); - set({ deviceCodeData }); - - if (deviceCodeData) { - // Try to copy user code to clipboard for convenience (best-effort) - try { - await navigator.clipboard?.writeText(deviceCodeData.userCode ?? ""); - } catch (err) { - // ignore clipboard errors - console.debug("Clipboard copy failed:", err); - } - - // Open verification URI in default browser - try { - if (deviceCodeData.verificationUri) { - await open(deviceCodeData.verificationUri); - } - } catch (err) { - console.debug("Failed to open verification URI:", err); - } - - // Start polling for completion - // `interval` from the bindings is a bigint (seconds). Convert safely to number. - const intervalSeconds = - deviceCodeData.interval !== undefined && - deviceCodeData.interval !== null - ? Number(deviceCodeData.interval) - : 5; - const intervalMs = intervalSeconds * 1000; - const pollInterval = setInterval( - () => get().checkLoginStatus(deviceCodeData.deviceCode), - intervalMs, - ); - set({ pollInterval }); - } - } catch (error) { - toast.error(`Failed to start Microsoft login: ${error}`); - set({ loginMode: "select" }); - // cleanup listener if present - const { authProgressUnlisten } = get(); - if (authProgressUnlisten) { - authProgressUnlisten(); - set({ authProgressUnlisten: null }); - } - } finally { - set({ msLoginLoading: false }); - } - }, - - checkLoginStatus: async (deviceCode: string) => { - const { isPollingRequestActive } = get(); - if (isPollingRequestActive) return; - - set({ isPollingRequestActive: true }); - - try { - const account = await invoke("complete_microsoft_login", { - deviceCode, - }); - - // On success, stop polling and cleanup listener - get().stopPolling(); - const { authProgressUnlisten } = get(); - if (authProgressUnlisten) { - authProgressUnlisten(); - set({ authProgressUnlisten: null }); - } - - set({ - currentAccount: account, - isLoginModalOpen: false, - }); - } catch (error: unknown) { - const errStr = String(error); - if (errStr.includes("authorization_pending")) { - // Still waiting — keep polling - } else { - set({ msLoginStatus: "Error: " + errStr }); - - if ( - errStr.includes("expired_token") || - errStr.includes("access_denied") - ) { - // Terminal errors — stop polling and reset state - get().stopPolling(); - const { authProgressUnlisten } = get(); - if (authProgressUnlisten) { - authProgressUnlisten(); - set({ authProgressUnlisten: null }); - } - alert("Login failed: " + errStr); - set({ loginMode: "select" }); - } - } - } finally { - set({ isPollingRequestActive: false }); - } - }, - - stopPolling: () => { - const { pollInterval, authProgressUnlisten } = get(); - if (pollInterval) { - try { - clearInterval(pollInterval); - } catch (err) { - console.debug("Failed to clear poll interval:", err); - } - set({ pollInterval: null }); - } - if (authProgressUnlisten) { - try { - authProgressUnlisten(); - } catch (err) { - console.debug("Failed to unlisten auth progress:", err); - } - set({ authProgressUnlisten: null }); - } - }, - - cancelMicrosoftLogin: () => { - get().stopPolling(); - set({ - deviceCodeData: null, - msLoginLoading: false, - msLoginStatus: "", - loginMode: "select", - }); - }, - - setLoginMode: (mode: "select" | "offline" | "microsoft") => { - set({ loginMode: mode }); - }, - - setOfflineUsername: (username: string) => { - set({ offlineUsername: username }); - }, -})); -- cgit v1.2.3-70-g09d2