149 lines
4.3 KiB
TypeScript
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} />}
|
|
</>
|
|
)
|
|
}
|