diff options
| author | 2026-01-15 18:17:49 +0800 | |
|---|---|---|
| committer | 2026-01-15 18:17:49 +0800 | |
| commit | 314ce0e656107ab43a8e8681d85525a551f83f21 (patch) | |
| tree | 3beffaf90afc62221eca10dbfd72695800290843 /ui/src/stores/auth.svelte.ts | |
| parent | 20cd97d8b3af67050fbe7b5f8d6d5fb1c1f3237b (diff) | |
| download | DropOut-314ce0e656107ab43a8e8681d85525a551f83f21.tar.gz DropOut-314ce0e656107ab43a8e8681d85525a551f83f21.zip | |
feat: Implement logout confirmation dialog and enhance account status display in BottomBar for improved user experience
Diffstat (limited to 'ui/src/stores/auth.svelte.ts')
| -rw-r--r-- | ui/src/stores/auth.svelte.ts | 54 |
1 files changed, 51 insertions, 3 deletions
diff --git a/ui/src/stores/auth.svelte.ts b/ui/src/stores/auth.svelte.ts index 3d58245..eb9dccd 100644 --- a/ui/src/stores/auth.svelte.ts +++ b/ui/src/stores/auth.svelte.ts @@ -1,11 +1,14 @@ import { invoke } from "@tauri-apps/api/core"; import { open } from "@tauri-apps/plugin-shell"; +import { listen, type UnlistenFn } from "@tauri-apps/api/event"; import type { Account, DeviceCodeResponse } from "../types"; import { uiState } from "./ui.svelte"; +import { logsState } from "./logs.svelte"; export class AuthState { currentAccount = $state<Account | null>(null); isLoginModalOpen = $state(false); + isLogoutConfirmOpen = $state(false); loginMode = $state<"select" | "offline" | "microsoft">("select"); offlineUsername = $state(""); deviceCodeData = $state<DeviceCodeResponse | null>(null); @@ -14,6 +17,7 @@ export class AuthState { private pollInterval: ReturnType<typeof setInterval> | null = null; private isPollingRequestActive = false; + private authProgressUnlisten: UnlistenFn | null = null; async checkAccount() { try { @@ -26,15 +30,29 @@ export class AuthState { openLoginModal() { if (this.currentAccount) { - if (confirm("Logout " + this.currentAccount.username + "?")) { - invoke("logout").then(() => (this.currentAccount = null)); - } + // Show custom logout confirmation dialog + this.isLogoutConfirmOpen = true; return; } this.resetLoginState(); this.isLoginModalOpen = true; } + cancelLogout() { + this.isLogoutConfirmOpen = false; + } + + async confirmLogout() { + this.isLogoutConfirmOpen = false; + try { + await invoke("logout"); + this.currentAccount = null; + uiState.setStatus("Logged out successfully"); + } catch (e) { + console.error("Logout failed:", e); + } + } + closeLoginModal() { this.stopPolling(); this.isLoginModalOpen = false; @@ -65,6 +83,9 @@ export class AuthState { this.msLoginStatus = "Waiting for authorization..."; this.stopPolling(); + // Setup auth progress listener + this.setupAuthProgressListener(); + try { this.deviceCodeData = (await invoke( "start_microsoft_login" @@ -78,6 +99,7 @@ export class AuthState { } open(this.deviceCodeData.verification_uri); + logsState.addLog("info", "Auth", "Microsoft login started, waiting for browser authorization..."); console.log("Starting polling for token..."); const intervalMs = (this.deviceCodeData.interval || 5) * 1000; @@ -87,6 +109,7 @@ export class AuthState { ); } } catch (e) { + logsState.addLog("error", "Auth", `Failed to start Microsoft login: ${e}`); alert("Failed to start Microsoft login: " + e); this.loginMode = "select"; } finally { @@ -94,6 +117,27 @@ export class AuthState { } } + private async setupAuthProgressListener() { + // Clean up previous listener if exists + if (this.authProgressUnlisten) { + this.authProgressUnlisten(); + this.authProgressUnlisten = null; + } + + this.authProgressUnlisten = await listen<string>("auth-progress", (event) => { + const message = event.payload; + this.msLoginStatus = message; + logsState.addLog("info", "Auth", message); + }); + } + + private cleanupAuthListener() { + if (this.authProgressUnlisten) { + this.authProgressUnlisten(); + this.authProgressUnlisten = null; + } + } + stopPolling() { if (this.pollInterval) { clearInterval(this.pollInterval); @@ -113,7 +157,9 @@ export class AuthState { console.log("Login Successful!", this.currentAccount); this.stopPolling(); + this.cleanupAuthListener(); this.isLoginModalOpen = false; + logsState.addLog("info", "Auth", `Login successful! Welcome, ${this.currentAccount.username}`); uiState.setStatus("Welcome back, " + this.currentAccount.username); } catch (e: any) { const errStr = e.toString(); @@ -122,12 +168,14 @@ export class AuthState { } else { console.error("Polling Error:", errStr); this.msLoginStatus = "Error: " + errStr; + logsState.addLog("error", "Auth", `Login error: ${errStr}`); if ( errStr.includes("expired_token") || errStr.includes("access_denied") ) { this.stopPolling(); + this.cleanupAuthListener(); alert("Login failed: " + errStr); this.loginMode = "select"; } |