From fb83c4d70616ec23d8a5397409a5d31c70b70d66 Mon Sep 17 00:00:00 2001 From: Gab Virebent Date: Mon, 3 Aug 2026 17:35:07 +0200 Subject: Add Usenet-style line wrapping, optional identity save/load, update README --- internal/assets/web/templates/index.html | 42 ++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) (limited to 'internal/assets') diff --git a/internal/assets/web/templates/index.html b/internal/assets/web/templates/index.html index 0d2d820..60df055 100644 --- a/internal/assets/web/templates/index.html +++ b/internal/assets/web/templates/index.html @@ -608,7 +608,9 @@
+
+

Saving is optional: skip it for a fresh throwaway identity each time, or save the file to reuse the same identicon later and prove later posts are from the same author. Keep the file private, whoever holds it can sign as you.

@@ -830,6 +832,8 @@ function resetEphemeralState(messageID) { genKeyBtn.disabled = false; genKeyBtn.textContent = '🔑 Generate New Keypair'; } + const saveIdentityBtn = document.getElementById('saveIdentityBtn'); + if (saveIdentityBtn) saveIdentityBtn.disabled = true; const signBtn = document.getElementById('signMsgBtn'); if (signBtn) signBtn.disabled = true; const sendBtn = document.getElementById('sendBtn'); @@ -1215,15 +1219,48 @@ document.getElementById('genKeyBtn').onclick = async function() { pubOutput.classList.remove('empty'); document.getElementById('x-ed25519-pub').value = pubB64; document.getElementById('signMsgBtn').disabled = false; + document.getElementById('saveIdentityBtn').disabled = false; const username = document.getElementById('fromName').value || 'Anonymous'; const email = document.getElementById('hcEmail').value || ''; document.getElementById('identityLoadedPow').style.display = 'flex'; document.getElementById('loadedIdentityName').textContent = username; document.getElementById('loadedIdentityEmail').textContent = email || 'Identity active only in memory'; - + await updateIdenticonPreview(); - showNotification('✓ Identity generated in memory. Now write and sign your message.', 'success', 6000); + showNotification('✓ Identity generated in memory. Save it now if you want to reuse this identicon later, then write and sign your message.', 'success', 6000); + } catch (error) { + showNotification('✗ Error: ' + error.message, 'error'); + } +}; + +document.getElementById('saveIdentityBtn').onclick = function() { + try { + if (!keyPair) { + showNotification('⚠ Generate or load an identity first!', 'warning'); + return; + } + const username = document.getElementById('fromName').value || 'Anonymous'; + const email = document.getElementById('hcEmail').value || ''; + const data = { + version: 2, + type: 'n2usenet-identity', + publicKey: nacl.util.encodeBase64(keyPair.publicKey), + secretKey: nacl.util.encodeBase64(keyPair.secretKey), + username: username, + email: email, + created: new Date().toISOString() + }; + const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = 'n2usenet-identity.json'; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + showNotification('✓ Identity file downloaded. Keep it private, it contains your secret key. Load it next time to keep the same identicon.', 'success', 8000); } catch (error) { showNotification('✗ Error: ' + error.message, 'error'); } @@ -1260,6 +1297,7 @@ document.getElementById('identityFileInput').onchange = async function(e) { pubOutput.classList.remove('empty'); document.getElementById('x-ed25519-pub').value = pubB64; document.getElementById('signMsgBtn').disabled = false; + document.getElementById('saveIdentityBtn').disabled = false; if (data.username) { document.getElementById('fromName').value = data.username; -- cgit v1.2.3