import { useState, useRef, useEffect } from 'react' import { nostrAuthService } from '@/lib/nostrAuth' import { getWordSuggestions } from '@/lib/keyManagementBIP39' interface UnlockAccountModalProps { onSuccess: () => void onClose: () => void } function WordInputWithAutocomplete({ index, value, onChange, onFocus, onBlur, }: { index: number value: string onChange: (value: string) => void onFocus: () => void onBlur: () => void }) { const [suggestions, setSuggestions] = useState([]) const [showSuggestions, setShowSuggestions] = useState(false) const [selectedIndex, setSelectedIndex] = useState(-1) const inputRef = useRef(null) const suggestionsRef = useRef(null) useEffect(() => { if (value.length > 0) { const newSuggestions = getWordSuggestions(value, 5) setSuggestions(newSuggestions) setShowSuggestions(newSuggestions.length > 0) setSelectedIndex(-1) } else { setSuggestions([]) setShowSuggestions(false) } }, [value]) const handleChange = (e: React.ChangeEvent) => { const newValue = e.target.value.trim().toLowerCase() onChange(newValue) } const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'ArrowDown') { e.preventDefault() setSelectedIndex((prev) => (prev < suggestions.length - 1 ? prev + 1 : prev)) } else if (e.key === 'ArrowUp') { e.preventDefault() setSelectedIndex((prev) => (prev > 0 ? prev - 1 : -1)) } else if (e.key === 'Enter' && selectedIndex >= 0 && suggestions[selectedIndex]) { e.preventDefault() onChange(suggestions[selectedIndex] ?? '') setShowSuggestions(false) inputRef.current?.blur() } else if (e.key === 'Escape') { setShowSuggestions(false) inputRef.current?.blur() } } const handleSuggestionClick = (suggestion: string) => { onChange(suggestion) setShowSuggestions(false) inputRef.current?.blur() } return (
{ // Delay to allow click on suggestion setTimeout(() => { setShowSuggestions(false) onBlur() }, 200) }} className="w-full px-3 py-2 border border-gray-300 rounded-lg font-mono text-lg text-center" autoComplete="off" autoCapitalize="off" autoCorrect="off" spellCheck="false" /> {showSuggestions && suggestions.length > 0 && (
{suggestions.map((suggestion, idx) => ( ))}
)}
) } function WordInputs({ words, onWordChange, }: { words: string[] onWordChange: (index: number, value: string) => void }) { const [, setFocusedIndex] = useState(null) return (
{words.map((word, index) => ( onWordChange(index, value)} onFocus={() => setFocusedIndex(index)} onBlur={() => setFocusedIndex(null)} /> ))}
) } function useUnlockAccount(words: string[], setWords: (words: string[]) => void, setError: (error: string | null) => void) { const handleWordChange = (index: number, value: string) => { const newWords = [...words] newWords[index] = value.trim().toLowerCase() setWords(newWords) setError(null) } const handlePaste = async () => { try { const text = await navigator.clipboard.readText() const pastedWords = text.trim().split(/\s+/).slice(0, 4) if (pastedWords.length === 4) { setWords(pastedWords.map((w) => w.toLowerCase())) setError(null) } } catch (_e) { // Ignore clipboard errors } } return { handleWordChange, handlePaste } } function UnlockAccountButtons({ loading, words, onUnlock, onClose, }: { loading: boolean words: string[] onUnlock: () => void onClose: () => void }) { return (
) } function UnlockAccountForm({ words, handleWordChange, handlePaste, }: { words: string[] handleWordChange: (index: number, value: string) => void handlePaste: () => void }) { return (
) } export function UnlockAccountModal({ onSuccess, onClose }: UnlockAccountModalProps) { const [words, setWords] = useState(['', '', '', '']) const [loading, setLoading] = useState(false) const [error, setError] = useState(null) const { handleWordChange, handlePaste } = useUnlockAccount(words, setWords, setError) const handleUnlock = async () => { if (words.some((word) => !word)) { setError('Veuillez remplir tous les mots-clés') return } setLoading(true) setError(null) try { await nostrAuthService.unlockAccount(words) onSuccess() onClose() } catch (e) { setError(e instanceof Error ? e.message : 'Échec du déverrouillage. Vérifiez vos mots-clés.') } finally { setLoading(false) } } return (

Déverrouiller votre compte

Entrez vos 4 mots-clés de récupération (dictionnaire BIP39) pour déverrouiller votre compte. Ces mots déchiffrent la clé de chiffrement (KEK) stockée dans l'API Credentials, qui déchiffre ensuite votre clé privée.

{error &&

{error}

}
) }