import { useState, useEffect, useRef } from 'react' import * as configService from '../services/config' import { ArrowRight, Fingerprint, Lock, ScanFace, ShieldCheck } from 'lucide-react' import './LockScreen.scss' interface LockScreenProps { onUnlock: () => void avatar?: string useHello?: boolean } async function sha256(message: string) { const msgBuffer = new TextEncoder().encode(message) const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer) const hashArray = Array.from(new Uint8Array(hashBuffer)) const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('') return hashHex } export default function LockScreen({ onUnlock, avatar, useHello = false }: LockScreenProps) { const [password, setPassword] = useState('') const [error, setError] = useState('') const [isVerifying, setIsVerifying] = useState(false) const [isUnlocked, setIsUnlocked] = useState(false) const [showHello, setShowHello] = useState(false) const [helloAvailable, setHelloAvailable] = useState(false) // 用于取消 WebAuthn 请求 const abortControllerRef = useRef(null) const inputRef = useRef(null) useEffect(() => { // 快速检查配置并启动 quickStartHello() inputRef.current?.focus() return () => { // 组件卸载时取消请求 abortControllerRef.current?.abort() } }, []) const handleUnlock = () => { setIsUnlocked(true) setTimeout(() => { onUnlock() }, 1500) } const quickStartHello = async () => { try { // 如果父组件已经告诉我们要用 Hello,直接开始,不等待 IPC let shouldUseHello = useHello // 为了稳健,如果 prop 没传(虽然现在都传了),再 check 一次 config if (!shouldUseHello) { shouldUseHello = await configService.getAuthUseHello() } if (shouldUseHello) { // 标记为可用,显示按钮 setHelloAvailable(true) setShowHello(true) // 立即执行验证 (0延迟) verifyHello() } } catch (e) { console.error('Quick start hello failed', e) } } const verifyHello = async () => { if (isVerifying || isUnlocked) return setIsVerifying(true) setError('') try { const result = await window.electronAPI.auth.hello() if (result.success) { handleUnlock() } else { console.error('Hello verification failed:', result.error) setError(result.error || '验证失败') } } catch (e: any) { console.error('Hello verification error:', e) setError(`验证失败: ${e.message || String(e)}`) } finally { setIsVerifying(false) } } const handlePasswordSubmit = async (e?: React.FormEvent) => { e?.preventDefault() if (!password || isUnlocked) return // 如果正在进行 Hello 验证,它会自动失败或被取代,UI上不用特意取消 // 因为 native 调用是模态的或者独立的,我们只要让 JS 状态不对锁住即可 // 不再检查 isVerifying,因为我们允许打断 Hello setIsVerifying(true) setError('') try { const storedHash = await configService.getAuthPassword() const inputHash = await sha256(password) if (inputHash === storedHash) { handleUnlock() } else { setError('密码错误') setPassword('') setIsVerifying(false) // 如果密码错误,是否重新触发 Hello? // 用户可能想重试密码,暂时不自动触发 } } catch (e) { setError('验证失败') setIsVerifying(false) } } return (
{avatar ? ( User ) : ( )}

WeFlow 已锁定

setPassword(e.target.value)} // 移除 disabled,允许用户随时输入 />
{showHello && ( )}
{error &&
{error}
}
) }