ux: Friend-button default + profile-rename plumbing + export/import clarity
Three of the v0.7.0 device-testing feedback items, deferred for later rebuild/redeploy (Scott opted to batch UI fixes). (#1) Friend button on bio modal: - Primary action when neither following nor vouched: [Friend] (= follow + vouch in one click) plus secondary [Follow only]. - When following without a vouch: [Add Vouch] primary, [Unfollow] secondary. - When both follow + vouch (= friends): [Unfriend] (= revoke vouch + unfollow, with the rotation-cost confirm wording). - The standalone [Vouch] / [Revoke Vouch] flows stay reachable from the existing Vouches list in Settings. (#2) Profile shows "unnamed" — bug fix: - set_profile updated the profiles table + emitted a profile post, but never updated posting_identities.display_name. list_posting_ identities returns from the latter, so the Personas list kept showing "(unnamed)" forever after the first-run auto-persona was named. - Now set_profile also upserts the posting_identities row with the new display_name (secret_seed + created_at preserved). (#5) Export/import + persona-vs-device clarity: - Settings reorder: new "Your data on this device" explainer card up top (Personas = who you are to peers; Identities = device's network address, rarely useful to touch). - "Move to another device" section renamed + given a plain-English description; primary [Export personas] / [Import from another device] buttons. - "Identities (advanced)" demoted below; warning text added. - Export wizard heading: "Export your personas"; radio labels use persona/keys language consistently. - Import wizard heading: "Import from another device"; explainer notes that the default action restores personas. Tracking memory created at memory/project_v071_followups.md for deferred items (#4 PQ vouch delivery, #6 rename, #7 redundancy, #8/#9/#10 awaiting clarification). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f714a17385
commit
346d23d4d8
3 changed files with 79 additions and 30 deletions
|
|
@ -1687,12 +1687,13 @@ async function openBioModal(nodeId, preloadedName) {
|
|||
${bio ? `<p style="font-size:0.9rem;line-height:1.45;margin:0 0 0.75rem">${escapeHtml(bio)}</p>` : '<p class="empty-hint" style="margin:0 0 0.75rem">No bio.</p>'}
|
||||
<div style="display:flex;gap:0.4rem;flex-wrap:wrap">
|
||||
<button id="bio-view-posts" class="btn btn-primary btn-sm">View Posts</button>
|
||||
${following
|
||||
? `<button id="bio-unfollow" class="btn btn-ghost btn-sm">Unfollow</button>`
|
||||
: `<button id="bio-follow" class="btn btn-primary btn-sm">Follow</button>`}
|
||||
${isVouched
|
||||
? `<button id="bio-revoke-vouch" class="btn btn-ghost btn-sm">Revoke Vouch</button>`
|
||||
: `<button id="bio-vouch" class="btn btn-ghost btn-sm">Vouch</button>`}
|
||||
${(following && isVouched)
|
||||
? `<button id="bio-unfriend" class="btn btn-ghost btn-sm">Unfriend</button>`
|
||||
: (following
|
||||
? `<button id="bio-vouch" class="btn btn-primary btn-sm">Add Vouch</button>
|
||||
<button id="bio-unfollow" class="btn btn-ghost btn-sm">Unfollow</button>`
|
||||
: `<button id="bio-friend" class="btn btn-primary btn-sm">Friend</button>
|
||||
<button id="bio-follow" class="btn btn-ghost btn-sm">Follow only</button>`)}
|
||||
<button id="bio-message" class="btn btn-ghost btn-sm">Message</button>
|
||||
${isIgnored
|
||||
? `<button id="bio-unignore" class="btn btn-ghost btn-sm">Unignore</button>`
|
||||
|
|
@ -1749,16 +1750,34 @@ async function openBioModal(nodeId, preloadedName) {
|
|||
} catch (e) { toast('Error: ' + e); }
|
||||
finally { vouch.disabled = false; }
|
||||
};
|
||||
const revokeVouch = document.getElementById('bio-revoke-vouch');
|
||||
if (revokeVouch) revokeVouch.onclick = async () => {
|
||||
if (!confirm(`Revoke vouch for ${name}? This rotates your vouch key — they keep access to existing posts but not future ones.`)) return;
|
||||
revokeVouch.disabled = true;
|
||||
// Friend = follow + vouch in one click. Default action per v0.7.x UX.
|
||||
const friend = document.getElementById('bio-friend');
|
||||
if (friend) friend.onclick = async () => {
|
||||
friend.disabled = true;
|
||||
try {
|
||||
await invoke('follow_node', { nodeIdHex: nodeId });
|
||||
await invoke('vouch_for_peer', { nodeIdHex: nodeId });
|
||||
toast(`Friended ${name}`);
|
||||
close();
|
||||
loadFollows();
|
||||
loadFeed(true);
|
||||
} catch (e) { toast('Error: ' + e); }
|
||||
finally { friend.disabled = false; }
|
||||
};
|
||||
// Unfriend = revoke vouch + unfollow. Rotation cost is real; confirm.
|
||||
const unfriend = document.getElementById('bio-unfriend');
|
||||
if (unfriend) unfriend.onclick = async () => {
|
||||
if (!confirm(`Unfriend ${name}? This revokes your vouch (rotates your vouch key — they keep access to existing posts but not future ones) AND unfollows them.`)) return;
|
||||
unfriend.disabled = true;
|
||||
try {
|
||||
await invoke('revoke_vouch_for_peer', { nodeIdHex: nodeId });
|
||||
toast('Revoked and rotated');
|
||||
await invoke('unfollow_node', { nodeIdHex: nodeId });
|
||||
toast(`Unfriended ${name}`);
|
||||
close();
|
||||
loadFollows();
|
||||
loadFeed(true);
|
||||
} catch (e) { toast('Error: ' + e); }
|
||||
finally { revokeVouch.disabled = false; }
|
||||
finally { unfriend.disabled = false; }
|
||||
};
|
||||
} catch (e) {
|
||||
bodyEl.innerHTML = `<p class="status-err">Error: ${e}</p>`;
|
||||
|
|
@ -4041,14 +4060,14 @@ $('#export-btn').addEventListener('click', () => {
|
|||
overlay.className = 'image-lightbox';
|
||||
overlay.style.cursor = 'default';
|
||||
overlay.innerHTML = `
|
||||
<div style="background:#1a1a2e;border:1px solid #333;border-radius:12px;padding:1.5rem;max-width:400px;width:90%;text-align:center">
|
||||
<h3 style="color:#7fdbca;margin:0 0 0.75rem">Export Data</h3>
|
||||
<p style="font-size:0.75rem;color:#888;margin-bottom:0.75rem">Choose what to include in the export ZIP.</p>
|
||||
<div style="background:#1a1a2e;border:1px solid #333;border-radius:12px;padding:1.5rem;max-width:420px;width:90%;text-align:center">
|
||||
<h3 style="color:#7fdbca;margin:0 0 0.5rem">Export your personas</h3>
|
||||
<p style="font-size:0.75rem;color:#888;margin-bottom:0.75rem">Save your personas + (optionally) your posts to a ZIP file so you can import them on another device.</p>
|
||||
<div style="display:flex;flex-direction:column;gap:0.5rem;text-align:left;margin-bottom:1rem">
|
||||
<label class="checkbox-label"><input type="radio" name="export-scope" value="identity_only" /> Identity key only (tiny backup)</label>
|
||||
<label class="checkbox-label"><input type="radio" name="export-scope" value="posts_only" /> Posts + media (no key — safe to share)</label>
|
||||
<label class="checkbox-label"><input type="radio" name="export-scope" value="posts_with_identity" checked /> Posts + media + identity key</label>
|
||||
<label class="checkbox-label"><input type="radio" name="export-scope" value="everything" /> Everything (posts, key, follows, settings)</label>
|
||||
<label class="checkbox-label"><input type="radio" name="export-scope" value="identity_only" /> Persona keys only (tiny backup — restores your identity but not your posts)</label>
|
||||
<label class="checkbox-label"><input type="radio" name="export-scope" value="posts_only" /> Posts + media only (no keys — safe to share publicly)</label>
|
||||
<label class="checkbox-label"><input type="radio" name="export-scope" value="posts_with_identity" checked /> Posts + media + persona keys (typical “move to new device”)</label>
|
||||
<label class="checkbox-label"><input type="radio" name="export-scope" value="everything" /> Everything (posts, keys, follows, settings)</label>
|
||||
</div>
|
||||
<div style="margin-bottom:0.75rem">
|
||||
<label style="font-size:0.75rem;color:#888">Save to folder:</label>
|
||||
|
|
@ -4118,8 +4137,8 @@ $('#import-btn').addEventListener('click', () => {
|
|||
overlay.style.cursor = 'default';
|
||||
overlay.innerHTML = `
|
||||
<div style="background:#1a1a2e;border:1px solid #333;border-radius:12px;padding:1.5rem;max-width:420px;width:90%;text-align:center">
|
||||
<h3 style="color:#7fdbca;margin:0 0 0.75rem">Import Data</h3>
|
||||
<p style="font-size:0.75rem;color:#888;margin-bottom:0.75rem">Select an ItsGoin export ZIP file.</p>
|
||||
<h3 style="color:#7fdbca;margin:0 0 0.5rem">Import from another device</h3>
|
||||
<p style="font-size:0.75rem;color:#888;margin-bottom:0.75rem">Select an ItsGoin export ZIP. Default action restores the exported personas onto this device so you can post as them.</p>
|
||||
<div style="display:flex;gap:0.25rem;margin-bottom:0.75rem">
|
||||
<input id="import-zip-path" type="text" placeholder="/path/to/itsgoin-export.zip" style="flex:1;font-size:0.8rem" />
|
||||
<button class="btn btn-ghost btn-sm" id="import-browse">Browse</button>
|
||||
|
|
|
|||
|
|
@ -231,13 +231,13 @@
|
|||
<button id="check-updates-btn" class="btn btn-ghost btn-sm" style="margin-top:0.5rem">Check now</button>
|
||||
</div>
|
||||
|
||||
<div class="section-card" style="text-align:center">
|
||||
<h3 style="margin-bottom:0.5rem">Identities</h3>
|
||||
<div id="identities-list" style="margin-bottom:0.5rem"></div>
|
||||
<div style="display:flex;gap:0.5rem;justify-content:center;flex-wrap:wrap">
|
||||
<button id="create-identity-btn" class="btn btn-ghost btn-sm">New Identity</button>
|
||||
<button id="import-identity-btn" class="btn btn-ghost btn-sm">Import Key</button>
|
||||
</div>
|
||||
<div class="section-card" style="text-align:left">
|
||||
<h3 style="margin-bottom:0.4rem;text-align:center">Your data on this device</h3>
|
||||
<p class="empty-hint" style="margin-bottom:0.5rem;font-size:0.78rem;line-height:1.5">
|
||||
<strong style="color:#7fdbca">Personas</strong> are who you are to peers — the keys you post and message with. Most people only need one. To move your account to a new device, you <em>export your personas</em> from this device and <em>import them</em> on the new one.
|
||||
<br><br>
|
||||
<strong style="color:#888">Identities</strong> below are this device's own network address — usually not what you want to move. Leave them alone unless you know why you're touching them.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="section-card" style="text-align:center">
|
||||
|
|
@ -248,9 +248,25 @@
|
|||
</div>
|
||||
|
||||
<div class="section-card" style="text-align:center">
|
||||
<h3 style="margin-bottom:0.4rem">Move to another device</h3>
|
||||
<p class="empty-hint" style="margin-bottom:0.5rem;font-size:0.78rem">
|
||||
Export creates a ZIP containing your personas (and optionally posts/follows). Import on the other device's Settings > Move to another device.
|
||||
</p>
|
||||
<div style="display:flex;gap:0.5rem;justify-content:center;flex-wrap:wrap">
|
||||
<button id="export-btn" class="btn btn-ghost btn-sm">Export</button>
|
||||
<button id="import-btn" class="btn btn-ghost btn-sm">Import</button>
|
||||
<button id="export-btn" class="btn btn-primary btn-sm">Export personas</button>
|
||||
<button id="import-btn" class="btn btn-ghost btn-sm">Import from another device</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section-card" style="text-align:center">
|
||||
<h3 style="margin-bottom:0.4rem;font-size:0.85rem;color:#888">Identities (advanced)</h3>
|
||||
<p class="empty-hint" style="margin-bottom:0.5rem;font-size:0.72rem">
|
||||
This device's network address. Changing this is rarely useful — it lets you move the device's QUIC endpoint, NOT your posting identity.
|
||||
</p>
|
||||
<div id="identities-list" style="margin-bottom:0.5rem"></div>
|
||||
<div style="display:flex;gap:0.5rem;justify-content:center;flex-wrap:wrap">
|
||||
<button id="create-identity-btn" class="btn btn-ghost btn-sm">New Identity</button>
|
||||
<button id="import-identity-btn" class="btn btn-ghost btn-sm">Import Key</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue