import { html, useState, useEffect, useCallback, } from './vendor/htm-preact.js'; import { t } from './i18n.js'; import { Icon } from './icon.js'; import { hubFetch } from './hub-client.js'; export function ProfilePage({ user, onLogout }) { const [nodeKey, setNodeKey] = useState(''); const [currentNodeKey, setCurrentNodeKey] = useState(null); const [nodeKeyStatus, setNodeKeyStatus] = useState(''); const [nodeKeyLoading, setNodeKeyLoading] = useState(false); const [email, setEmail] = useState(''); const [emailDraft, setEmailDraft] = useState(''); const [emailEditing, setEmailEditing] = useState(false); const [emailSaving, setEmailSaving] = useState(false); const [emailStatus, setEmailStatus] = useState(''); const [pinCount, setPinCount] = useState( () => (window.MeshBayTransport?.pinnedNodeCount?.() ?? 0)); const [delOpen, setDelOpen] = useState(false); const [delPass, setDelPass] = useState(''); const [delError, setDelError] = useState(''); const [deleting, setDeleting] = useState(false); const deleteAccount = useCallback(async (e) => { e.preventDefault(); setDeleting(true); setDelError(''); try { const authKey = await window.MeshBayKeys.deriveAuthKey(delPass, user.username); await hubFetch('/v1/users/me', { method: 'DELETE', token: user.token, body: { auth_key: authKey }, }); onLogout(); } catch (err) { setDelError(err.message); } finally { setDeleting(false); } }, [delPass, user]); const clearPins = useCallback(() => { window.MeshBayTransport?.clearNodePin?.(); setPinCount(window.MeshBayTransport?.pinnedNodeCount?.() ?? 0); }, []); useEffect(() => { hubFetch('/v1/users/me', { token: user.token }) .then(data => { if (data.email) { setEmail(data.email); setEmailDraft(data.email); } }) .catch(() => {}); hubFetch(`/v1/users/${user.username}/pubkeys`, { token: user.token }) .then(data => { if (data.pk_node_ed25519) setCurrentNodeKey(data.pk_node_ed25519); }) .catch(() => {}); }, [user.username, user.token]); const saveEmail = useCallback(async () => { const val = emailDraft.trim(); if (!val || val === email) { setEmailEditing(false); return; } setEmailSaving(true); setEmailStatus(''); try { await hubFetch('/v1/users/me', { method: 'PATCH', token: user.token, body: { email: val }, }); setEmail(val); setEmailEditing(false); setEmailStatus(t('settings.email_saved')); setTimeout(() => setEmailStatus(''), 3000); } catch (e) { setEmailStatus(e.message); } finally { setEmailSaving(false); } }, [emailDraft, email, user.token]); const submitNodeKey = useCallback(async () => { const key = nodeKey.trim(); if (!key) return; setNodeKeyLoading(true); setNodeKeyStatus(''); try { await hubFetch('/v1/users/me/node_key', { method: 'PUT', token: user.token, body: { pk_node_ed25519: key }, }); setCurrentNodeKey(key); setNodeKey(''); setNodeKeyStatus(t('settings.node_key_success')); } catch (e) { setNodeKeyStatus(e.message); } finally { setNodeKeyLoading(false); } }, [nodeKey, user.token]); return html`
${emailStatus}
`}${t('settings.node_key_desc')}
${currentNodeKey && html`${currentNodeKey}
${nodeKeyStatus}
`}${t('settings.node_pins_hint')}
${t('settings.delete_hint')}
${delError && html`${delError}
`} ${!delOpen ? html`` : html` `}