WebKitGTK can't serialize FormData with Blob objects through Tauri's
HTTP plugin, throwing "InvalidStateError: Unable to read form data
blob". Build the multipart/form-data body manually as raw bytes
instead. Also add void.cat and nostrimg.com to the HTTP scope.
Notifications now load instantly from SQLite on startup instead of
waiting for relay responses. New events merge in as they arrive.
Read state persists in DB across restarts.
Also: filter profile owner from WoT followers list, make "+N more"
clickable to expand, fix reaction throttle queue jamming on errors.
Query Vertex Verify Reputation API (kind 5312) for each profile and
display "Followed by people you trust" with clickable top-follower
avatars. Includes in-memory cache, request dedup, and graceful
fallback when logged out or API unreachable.
Last stabilization release before the podcast playback sprint.
- Add Supported NIPs table to README (20 NIPs documented)
- Update README features with everything since v0.8.0: NIP-46,
media feed, trending, emoji picker, keyword muting, hashtag
pages, profile media gallery, relay recommendations, data export,
reading list tracking, syntax highlighting, OS notifications
- Update ROADMAP: NIP-46 marked shipped, v0.8.x entries added,
podcast playback listed as next milestone
- Update CLAUDE.md architecture to reflect refactored file structure
- Update release notes in CI workflow
- Version bump in all 4 files
Syntax highlighting: shared markdown renderer with highlight.js
(atom-one-dark theme), 12 language grammars registered (JS, TS,
Python, Rust, Go, Bash, JSON, YAML, SQL, CSS, HTML, Markdown).
Applied to both article reader and editor preview.
OS notifications: Tauri notification plugin for mentions, DMs, and
zaps. Per-type toggles in Settings with custom toggle switches.
Fires on new unread mentions/DMs; requests OS permission on first
enable. Notification utility at src/lib/notifications.ts.
Article discovery feed with Latest/Following tabs, article search
(NIP-50 + hashtag for kind 30023), Notes/Articles tab on profiles,
reading time + bookmark + like buttons on article reader. Event
passed directly from card to reader to avoid relay re-fetch failures.
DMs now send via NIP-17 (kind 1059 gift-wrap) with self-copy for sent
messages. Receive supports both NIP-17 and legacy NIP-04 for backward
compat. Protocol indicator shown in conversation list and compose footer.
Note card context menu (⋯) now includes follow/unfollow option so users
can follow authors directly from the feed without visiting their profile.
Fix crash (black screen) when starting a new DM conversation — empty
event array caused undefined access on lastEvent.
Add inline video/audio players for direct media URLs, rich link cards
for YouTube (with thumbnails), Vimeo, Spotify, and Tidal. Fix video
clicks navigating to thread by splitting NoteContent into inline/media
modes. Fix published notes not appearing on Following tab.
Published notes now appear in the feed immediately. Thread replies
show up without waiting for the relay round-trip. Includes all
v0.2.9 fixes (image paste, sent zaps, reply-to clickable, feed
refresh on login).
Tauri 2 requires bundle.createUpdaterArtifacts: true to produce .sig
files and updater zip/tar.gz archives. Without it, TAURI_SIGNING_PRIVATE_KEY
is ignored and latest.json is never generated.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix: repost + quote buttons added to RootNote in ThreadView (Issue A)
- Fix: switchAccount no longer silently goes read-only when nsec keychain
entry is missing — nsec accounts stay logged out so the login button
handles recovery; loginType field added to SavedAccount (Issue B)
- Fix: macos-12 runner replaced with macos-13 in release.yml — macos-12
was deprecated by GitHub, causing macOS jobs to never run, which
prevented latest.json from being assembled and broke the auto-updater
for every user since v0.1.5
- Bump Cargo.toml version (was stuck at 0.1.10)
- Release notes updated with v0.2.1 + v0.2.0 Phase 2 changelog
- README: Windows unsigned installer note added
- ROADMAP: NIP-05 monetization added to brainstorm backlog
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Four features shipped in this release:
- Feed reply context: replies show "↩ replying to @name" above the
note content; clicking fetches and opens the parent thread
- NIP-65 outbox model: fetchUserRelayList + publishRelayList +
fetchUserNotesNIP65 in client.ts; profile notes fetched via the
author's write relays; "Publish relay list to Nostr" button in
Settings (kind 10002)
- Notifications: new store (notifications.ts) + NotificationsView;
🔔 sidebar nav item with unread badge; DM nav item also shows
unread conversation count; badges clear on open/select
- Keyboard shortcuts: useKeyboardShortcuts hook + HelpModal;
n=compose, /=search, j/k=feed nav with ring highlight,
Esc=back, ?=help overlay
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use justify-between on the QR section so Lightning address sits flush
left and Bitcoin address sits flush right, making them visually
impossible to confuse when scanning.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Root cause: switchAccount fetched the nsec from the OS keychain on every
switch. Any keychain failure (timeout, Windows Credential Manager quirk,
no entry yet) silently fell through to loginWithPubkey → read-only mode.
Fix: cache each NDKPrivateKeySigner in-memory (_signerCache map) the
moment loginWithNsec succeeds. switchAccount checks the cache first;
the OS keychain is now only consulted at startup (restoreSession). Signers
are pure crypto objects with no session state — safe to reuse indefinitely.
Verified with a 9-switch stress test across 3 accounts (A1→A2→A3→A1→
A2→A1→A3→A2→A1): hasSigner=true and correct pubkey on every switch.
Also adds dev tooling:
- src/lib/tauri-dev-mock.ts: localStorage-backed keychain + SQLite stubs
so the frontend can run in a plain browser for Playwright testing
- src/main.tsx: import mock first in DEV mode (no-op in production)
- test/gen-accounts.mjs: generates 3 deterministic test keypairs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix switchAccount: check signer was set after loginWithNsec before
returning; fall back to loginWithPubkey on silent failure; always
navigate to feed after switch to clear stale UI
- Fix profile edit button: hidden in read-only (npub) mode; read-only
badge shown in profile header to make state visible
- Sidebar: show version number (v0.1.8) below WRYSTR brand, auto-tracked
from package.json — no more hardcoding
- Support page: increase QR code gap (gap-8 → gap-16) to prevent
accidentally scanning the wrong address
- ROADMAP: add language/alphabet feed filter to Phase 3 backlog
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
"updater" is not a valid Tauri 2.x bundle target — the auto-updater
is configured as a plugin, not a bundle format. This was causing
exit code 1 on all three platforms for the v0.1.6 build.
Also updates release notes in the workflow for v0.1.7.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Critical:
- NWC wallet now stored per-account (wrystr_nwc_<pubkey>); switching
accounts loads the correct wallet automatically
- Clear NDK signer before account switch to prevent race where old
account could sign outgoing events
- LoginModal: add "New account" tab to create a fresh keypair inline
(same flow as onboarding, with nsec copy + confirmation checkbox)
- ThreadView: add like + zap action row to the root note (was missing)
UX:
- Zap button now conditional on lud16/lud06 (NoteCard, ProfileView,
RootNote) — no zap button shown for profiles without Lightning
- Remove "200 notes" counter from sidebar footer
- AccountSwitcher: larger active account avatar (w-8), name more
prominent; sign-out/remove moved into dropdown only
Quick wins:
- AboutView: add GitHub Sponsors link
- ComposeBox: paste image from clipboard → uploads via nostr.build,
inserts URL at cursor with "uploading image…" status
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
AppImage library bundling causes cascading compatibility failures on
rolling-release distros (Arch, mesa 26+): libwayland-egl conflicts
break EGL, removing it cascades into GLib version mismatches, and so
on. Native packages sidestep this entirely.
- tauri.conf.json: targets now ["deb","rpm","nsis","msi","dmg","updater"]
— no AppImage
- release.yml: drop LINUXDEPLOY_EXCLUDELIST workaround (no longer needed);
update install instructions in release body
- PKGBUILD: added for Arch/Manjaro users; builds from source via git tag;
desktop entry sets WEBKIT_DISABLE_DMABUF_RENDERER=1 (required on Wayland)
- README: install table updated with distro-specific commands
Arch users: build from source with PKGBUILD or `npm run tauri build`.
Ubuntu/Debian/Fedora/openSUSE: install the .deb or .rpm from Releases.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- tauri-plugin-updater + tauri-plugin-process registered (Rust + npm)
- Updater endpoint: github.com/hoornet/wrystr/releases/latest/download/latest.json
- Ed25519 signing keypair generated; public key in tauri.conf.json;
private key added to TAURI_SIGNING_PRIVATE_KEY GitHub secret
- Release workflow passes TAURI_SIGNING_PRIVATE_KEY env var so
tauri-action signs artifacts and generates latest.json manifest
- useUpdater hook: checks for updates 5 s after startup (silent on
error); exposes available, version, install(), dismiss()
- UpdateBanner: dismissible top-of-app bar shown when an update is
available — "Update & restart" downloads, installs, and relaunches
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>