Phase 5 (0.6.4-beta) frontend: Personas UI + compose picker + feed pills

Settings > Personas:
- List all held posting identities with display_name + truncated nodeId
- Default badge; Set-default / Delete buttons per non-default persona
- "New Persona" modal prompts for a display name and creates via IPC

Compose box:
- A #persona-select dropdown appears when 2+ personas exist
- doPost attaches postingIdHex to create_post / create_post_with_files
  when a non-default persona is selected

Tauri:
- create_post and create_post_with_files take an optional
  posting_id_hex; when present they route through create_post_as,
  otherwise through the default create_post_with_visibility
- PostDto gains asPersona: name of the authoring posting identity if
  the author matches any of our held personas
- is_me now recognises ALL our posting identities, not just the
  network key (both post_to_dto and post_to_dto_batch)

Feed:
- Per-post "(you) as <PersonaName>" label on own posts authored by a
  non-default persona
- Persona filter pill row above the feed (hidden for single-persona
  users); pills toggle between All and each persona; matches when
  post.author or post.recipients contains the selected posting id
- Applied after loadFeed initial render and after appendFeedPage so
  filter survives infinite-scroll

App.js:
- personasCache + loadPersonas() loaded on startup so compose picker
  is populated before the Feed tab mounts
- loadPersonas() also called when Settings tab opens

Backend was unchanged; only the UI and IPC surface expanded.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Scott Reimers 2026-04-21 23:09:06 -04:00
parent 7bdb2eb736
commit eea868b4cc
3 changed files with 245 additions and 15 deletions

View file

@ -60,6 +60,7 @@
<!-- Feed tab -->
<section id="view-feed" class="view">
<div id="persona-filter-row" class="hidden" style="display:flex;gap:0.4rem;flex-wrap:wrap;padding:0.3rem 0.5rem;border-bottom:1px solid #222;overflow-x:auto"></div>
<div id="feed-list"></div>
</section>
@ -86,6 +87,7 @@
<div class="compose-left">
<span class="hint">Ctrl+Enter to post</span>
<div id="visibility-row">
<select id="persona-select" title="Post as" class="hidden"></select>
<select id="visibility-select">
<option value="public">Public</option>
<option value="friends">Friends</option>
@ -197,6 +199,13 @@
</div>
</div>
<div class="section-card" style="text-align:center">
<h3 style="margin-bottom:0.25rem">Personas</h3>
<p class="empty-hint" style="margin-bottom:0.5rem">Separate posting identities on this device. Peers see each persona as a distinct author.</p>
<div id="personas-list" style="margin-bottom:0.5rem;text-align:left"></div>
<button id="create-persona-btn" class="btn btn-ghost btn-sm">New Persona</button>
</div>
<div class="section-card" style="text-align:center">
<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>