diff --git a/src/components/auth/LoginDialog.tsx b/src/components/auth/LoginDialog.tsx index 20ffce5..9c0c22d 100644 --- a/src/components/auth/LoginDialog.tsx +++ b/src/components/auth/LoginDialog.tsx @@ -11,7 +11,7 @@ import { Alert, AlertDescription } from '@/components/ui/alert'; import { useLoginActions } from '@/hooks/useLoginActions'; import { useToast } from '@/hooks/useToast'; import { cn } from '@/lib/utils'; -import { subscribeToAmberReturn, getAmberLogin } from '@/lib/amber'; +import { subscribeToAmberReturn } from '@/lib/amber'; interface LoginDialogProps { isOpen: boolean; @@ -95,20 +95,30 @@ const LoginDialog: React.FC = ({ isOpen, onClose, onLogin, onS // Stamp the time so we know this is a fresh attempt localStorage.setItem('amber_login_attempt_ts', String(Date.now())); - // Poll localStorage every 500ms — on Android, the page navigates away and - // AmberCallbackPage completes the login in a new page load. When user comes - // back here, polling will detect the stored amber_login pubkey and complete. + // Poll localStorage every 400ms for 'amber_pending_pubkey'. + // AmberCallbackPage writes this key when Amber approves — even if it runs + // in a separate tab (GrapheneOS opens callback in new tab). This tab picks + // it up, calls login.amber() here where React state is alive, and completes. if (pollRef.current) clearInterval(pollRef.current); pollRef.current = setInterval(() => { - const storedPubkey = getAmberLogin(); - if (storedPubkey) { + const pendingPubkey = localStorage.getItem('amber_pending_pubkey'); + if (pendingPubkey) { + // Consume it immediately so we don't process twice + localStorage.removeItem('amber_pending_pubkey'); clearInterval(pollRef.current!); pollRef.current = null; - setAmberStep('success'); - toast({ title: '🛹 Logged in', description: 'Welcome back via Amber!' }); - setTimeout(() => { onLogin(); onClose(); }, 600); + try { + login.amber(pendingPubkey); + setAmberStep('success'); + toast({ title: '🛹 Logged in', description: 'Welcome back via Amber!' }); + setTimeout(() => { onLogin(); onClose(); }, 600); + } catch (err) { + console.error('[Amber] login.amber failed in poll:', err); + setErrors(prev => ({ ...prev, amber: 'Login failed. Please try again.' })); + setAmberStep('initial'); + } } - }, 500); + }, 400); // Also try visibilitychange for browsers that keep the tab alive unsubAmberRef.current = subscribeToAmberReturn(() => { @@ -369,16 +379,22 @@ const LoginDialog: React.FC = ({ isOpen, onClose, onLogin, onS