2026-01-08 23:04:56 +01:00

149 lines
4.3 KiB
TypeScript

import { useNostrAuth } from '@/hooks/useNostrAuth'
import { ConnectedUserMenu } from './ConnectedUserMenu'
import { RecoveryStep } from './CreateAccountModalSteps'
import { UnlockAccountModal } from './UnlockAccountModal'
import type { NostrProfile } from '@/types/nostr'
import { t } from '@/lib/i18n'
import { getConnectButtonMode } from './connectButton/connectButtonMode'
import { useAutoConnect, useConnectButtonUiState } from './connectButton/useConnectButtonUiState'
function ConnectForm({
onCreateAccount,
onUnlock,
loading,
error,
}: {
onCreateAccount: () => void
onUnlock: () => void
loading: boolean
error: string | null
}): React.ReactElement {
return (
<div className="flex flex-col gap-2">
<button
onClick={onCreateAccount}
disabled={loading}
className="px-6 py-2 bg-neon-cyan/20 hover:bg-neon-cyan/30 text-neon-cyan rounded-lg font-medium transition-all border border-neon-cyan/50 hover:shadow-glow-cyan disabled:opacity-50"
>
{t('connect.createAccount')}
</button>
<button
onClick={onUnlock}
disabled={loading}
className="px-6 py-2 bg-gray-100 hover:bg-gray-200 text-gray-700 rounded-lg font-medium transition-colors disabled:opacity-50"
>
{t('connect.connect')}
</button>
{error && <p className="text-sm text-red-400">{error}</p>}
</div>
)
}
function ConnectedState({ pubkey, profile, loading, disconnect }: { pubkey: string; profile: NostrProfile | null; loading: boolean; disconnect: () => Promise<void> }): React.ReactElement {
return (
<ConnectedUserMenu
pubkey={pubkey}
profile={profile}
onDisconnect={() => {
void disconnect()
}}
loading={loading}
/>
)
}
function UnlockState({ loading, error, onUnlock, onClose }: { loading: boolean; error: string | null; onUnlock: () => void; onClose: () => void }): React.ReactElement {
return (
<>
<ConnectForm
onCreateAccount={noop}
onUnlock={onUnlock}
loading={loading}
error={error}
/>
<UnlockAccountModal onSuccess={onClose} onClose={onClose} />
</>
)
}
function noop(): void {
// Intentionally empty: UnlockState must render ConnectForm but "create account" is not available in this mode.
}
function DisconnectedState({
loading,
error,
showUnlockModal,
setShowUnlockModal,
onCreateAccount,
}: {
loading: boolean
error: string | null
showUnlockModal: boolean
setShowUnlockModal: (show: boolean) => void
onCreateAccount: () => void
}): React.ReactElement {
return (
<>
<ConnectForm
onCreateAccount={onCreateAccount}
onUnlock={() => setShowUnlockModal(true)}
loading={loading}
error={error}
/>
{showUnlockModal && (
<UnlockAccountModal
onSuccess={() => setShowUnlockModal(false)}
onClose={() => setShowUnlockModal(false)}
/>
)}
</>
)
}
export function ConnectButton(): React.ReactElement {
const { connected, pubkey, profile, loading, error, connect, disconnect, accountExists, isUnlocked } = useNostrAuth()
const ui = useConnectButtonUiState()
useAutoConnect({
accountExists,
pubkey,
showRecoveryStep: ui.showRecoveryStep,
showUnlockModal: ui.showUnlockModal,
connect,
})
const mode = getConnectButtonMode({
connected,
pubkey,
isUnlocked,
accountExists,
showUnlockModal: ui.showUnlockModal,
})
if (mode === 'connected') {
return <ConnectedState pubkey={pubkey} profile={profile} loading={loading} disconnect={disconnect} />
}
if (mode === 'unlock_required') {
return <UnlockState loading={loading} error={error} onUnlock={ui.openUnlockModal} onClose={ui.closeUnlockModal} />
}
return (
<>
<DisconnectedState
loading={loading ?? ui.creatingAccount}
error={error ?? ui.createError}
showUnlockModal={ui.showUnlockModal}
setShowUnlockModal={ui.setShowUnlockModal}
onCreateAccount={ui.onCreateAccount}
/>
{ui.showRecoveryStep && (
<RecoveryStep recoveryPhrase={ui.recoveryPhrase} npub={ui.npub} onContinue={ui.onRecoveryContinue} />
)}
{ui.showUnlockModal && <UnlockAccountModal onSuccess={ui.onUnlockSuccess} onClose={ui.closeUnlockModal} />}
</>
)
}