Something went wrong. Try again.
An atproto Tilemap editor
Something went wrong. Try again.
2.3 kB · 76 lines
TSX
at main
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677import { useState } from 'react'import { Loader2 } from 'lucide-react'import { useAuthStore } from '../store/authStore'import HandleAutocomplete from './HandleAutocomplete'import { Button } from '@/components/ui/button'import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle,} from '@/components/ui/dialog'
/** A minimal, controlled atproto login prompt: a handle field that opens the * PDS OAuth popup. The parent owns `open` (typically derived so it hides once * `status === 'in'`); `onOpenChange(false)` fires only on user-initiated close * (esc / overlay), which the parent treats as cancelling whatever gated on it. */export default function LoginDialog({ open, onOpenChange, reason,}: { open: boolean onOpenChange: (open: boolean) => void reason?: string}) { const login = useAuthStore((s) => s.login) const authError = useAuthStore((s) => s.error)
const [handle, setHandle] = useState('') const [loggingIn, setLoggingIn] = useState(false)
const doLogin = async (h: string) => { if (!h.trim()) return setLoggingIn(true) try { await login(h) } catch { // error surfaced via authError } finally { setLoggingIn(false) } }
return ( <Dialog open={open} onOpenChange={onOpenChange}> <DialogContent className="max-w-md"> <DialogHeader> <DialogTitle>Log in to atproto</DialogTitle> <DialogDescription> {reason ?? 'Log in with your atproto account to continue.'} A window will open to your PDS. </DialogDescription> </DialogHeader> <div className="flex gap-2"> <HandleAutocomplete autoFocus className="flex-1" disabled={loggingIn} value={handle} onChange={setHandle} onCommit={doLogin} /> <Button type="button" disabled={!handle.trim() || loggingIn} onClick={() => doLogin(handle)} > {loggingIn ? <Loader2 className="animate-spin" /> : 'Log in'} </Button> </div> {authError && <p className="text-xs text-destructive">{authError}</p>} </DialogContent> </Dialog> )}