Reset All Data:
- Sentinel now written at the app-level data_dir instead of the
active identity's subdir. On Android the subdir path was never
checked at startup, so reset silently did nothing.
- On detection, wipe EVERYTHING under the app data_dir: identity.key,
itsgoin.db + WAL + SHM, blobs, all identity subdirs. Next launch
is truly fresh — new network key, new posting key, no prior data.
First-run name:
- Display name is optional. Blank submits as anonymous.
- First-run modal + profile overlay placeholder updated to say
"Display name (optional)".
Android file picker:
- pick_file on Android now uses tauri-plugin-android-fs'
show_open_file_dialog (Storage Access Framework OPEN_DOCUMENT).
Read the picked URI's bytes, stage them in the app's private cache
as a timestamped file, return the staged path so existing
import_* code can read it as a regular filesystem path.
- Zip filter passes application/zip + application/octet-stream (some
file providers report the latter for .zip).
Android auto-backup off:
- AndroidManifest: allowBackup="false", fullBackupContent="false",
dataExtractionRules pointing at new data_extraction_rules.xml
- New data_extraction_rules.xml excludes all domains from both
cloud-backup and device-transfer. Prior default (allowBackup=true)
silently replicated identity.key to Google Drive for any user with
cloud backup on — which effectively published the root secret to
a third party without asking. Users who want off-device backup use
Settings -> Export (explicit zip they control).
Import as personas:
- New import_as_personas function in core/import.rs + new
import_as_personas_cmd Tauri IPC.
- Reads identity.key from the bundle and adds it to posting_identities
as a persona. Also reads posting_identities.json (v0.6+ bundles)
and adds each entry. Dedupes by node_id.
- Posts stay AS-AUTHORED — original post_id, original author,
original signatures, original wrapped_key recipients. No
re-encryption. Content encrypted to any of the imported keys
becomes decryptable because we now hold the secrets.
- Blobs, follows, profiles copied across.
- If current device has <=1 posting identity (the fresh-install one)
and the bundle brings more, auto-switch the default to the first
imported persona. Covers first-run-then-import flow cleanly.
Import wizard UI:
- New default option: "Restore as personas" — posts keep original
authors; source's keys become personas you can post as.
- Old "Merge with decryption key" retained as "Consolidate under
current default persona (requires source key)" for the case where
a user intentionally abandons a persona.
- "Public posts only" and "Add as separate identity" retained.
deploy.sh made executable (chmod +x tracked).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Feed pagination:
- Cursor-based pagination: get_feed_page/get_all_posts_page (20 posts/page)
- Batched engagement queries (3 bulk SQL queries instead of 4 per post)
- IntersectionObserver for infinite scroll (sentinel at midpoint)
- Viewport-based media loading (blobs only load when post enters view)
- Pre-fetch next page immediately after current page renders
Duplicate identity detection:
- Anchor detects when a NodeId is already mesh-connected during initial
exchange and sets duplicate_active flag in response
- Client skips sync tasks when duplicate detected
- Frontend shows red warning banner
Privacy:
- Fixed pkarr leak: clear_address_lookup() removes default dns.iroh.link
publishing. Only mDNS (local network) discovery enabled.
Android:
- SAF integration via tauri-plugin-android-fs: exports open native "Save As"
dialog so users can save to Downloads/Drive/etc.
- Download/export paths use app data dir on Android (writable)
- File picker gated behind desktop cfg (blocking_pick not on Android)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- bundleMediaFramework: true — bundles full GStreamer plugin set in AppImage.
Fixes WebKit hang on video/audio (missing appsink/autoaudiosink plugins).
MSDK/VA plugins removed post-build to avoid Ubuntu DMA assertion crash.
- Import creates complete posts: BlobHeader, VisibilityIntent, pinned blobs,
self-follow. Imported posts now indistinguishable from locally created ones.
- First-run chooser: Start Fresh or Import Identity on fresh install only.
Profile setup shown for existing identities without display name.
- File pickers: native Browse buttons on export (folder) and import (ZIP)
via tauri-plugin-dialog.
- Export path: relative paths resolved against home dir.
- Lightbox close: only on overlay/image click, not inner form content.
- Growth loop skips self as N2 candidate.
- Node shutdown on identity switch (prevents zombie background tasks).
- media-src CSP includes asset protocol.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment edit & delete:
- EditComment/DeleteComment BlobHeaderDiffOps with upstream+downstream propagation
- Trust-based: comment author can edit/delete, post author can delete
- Storage: edit_comment(), delete_comment() methods
- Frontend: inline edit (Enter/Escape), delete with confirm
Native notifications:
- tauri-plugin-notification for system notifications on all platforms
- Triggers for messages, new posts, reactions, and comments
- notif_reacts setting added, button-group toggles replace dropdowns
- _notifReady flag prevents startup spam
Protocol hardening:
- BlobHeaderDiffOp::Unknown variant with #[serde(other)] for forward compatibility
- Old nodes silently skip unknown ops instead of crashing
UI fixes:
- Self removed from Following list
- Offline follows in lightbox popup (auto-show if no one online)
- Sent DMs filtered from My Posts
- Comment threading scoped to closest .post (fixes duplicate ID issue)
- Select dropdown text legible in WebKitGTK (black on white options)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>