diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b0c88df..e4f03c4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -69,21 +69,19 @@ jobs: > **Windows note:** The installer is not yet code-signed. Windows SmartScreen will show an "Unknown publisher" warning — click "More info → Run anyway" to install. - ### New in v0.8.3 — Trending, Remote Signer, Media - - **Trending feed polish** — 24h time window with engagement decay scoring; articles (kind 30023) appear alongside notes in trending; better empty state - - **NIP-46 remote signer** — connect via bunker:// URI (nsecBunker, Amber, etc.); session persistence across restarts; third login tab in onboarding and add-account modal - - **Media feed** — new "Media" view in sidebar; All/Videos/Images/Audio tabs filter notes by embedded media type - - **Profile media gallery** — new "Media" tab on profiles shows a grid of the user's images, videos, and audio; images open in lightbox, videos/audio navigate to thread - - **Syntax highlighting** — code blocks in notes and articles render with syntax highlighting - - **OS push notifications** — background poller (60s) for mentions, zaps, new followers; each type independently toggleable - - **Zen writing mode** — distraction-free article editing with auto-save indicator - - **NIP-05 verification badges** — cached verification with green checkmark on note cards - - **Dedicated hashtag pages** — clicking #tag opens a live feed, not generic search - - **Keyword muting** — word/phrase mute list, client-side filtering across all views - - **Follow suggestion dismissal** — persistent "don't suggest again" per person + ### New in v0.8.4 — Codebase Refactor & Bug Fixes + This is the stabilization release before the upcoming podcast playback feature. + - **Codebase refactor** — split 5 overgrown files into focused modules for easier navigation and extension: `client.ts` (1036 lines) into 11 domain files; `ProfileView`, `NoteContent`, `NoteCard` into sub-components + - **Documentation** — added Supported NIPs table to README; updated all feature lists, roadmap, and architecture docs + - **Bug fixes from v0.8.3 testing:** + - Mute filtering now works in Media Feed + - Notification toggle labels no longer overlap on narrow windows + - External links open in system browser via Tauri opener plugin + - Emoji picker works correctly in compose box, inline reply, and reaction picker + - Trending feed shows visual feedback on force refresh - ### Previous: v0.8.2 — Writing & Reading Polish - - No more 280-char limit, serif reading font, reading progress bar, article TOC, connection indicator fix + ### Previous: v0.8.3 — Trending, Remote Signer, Media + - Trending feed (24h engagement decay), NIP-46 remote signer (bunker://), media feed (All/Videos/Images/Audio tabs), profile media gallery, syntax highlighting, OS push notifications, zen writing mode, NIP-05 badges, hashtag pages, keyword muting, emoji picker ### Previous: v0.8.0 — Polish, Portability & Discovery - Profile banner polish, data export, relay recommendations, reading list tracking, trending hashtags diff --git a/CLAUDE.md b/CLAUDE.md index bd49512..67cb755 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -46,11 +46,11 @@ CI triggers on the tag and builds all three platforms (Ubuntu, Windows, macOS AR - `src/App.tsx` — root component; shows `OnboardingFlow` for new users, then view routing via UI store - `src/stores/` — Zustand stores per domain: `feed.ts`, `user.ts`, `ui.ts`, `lightning.ts`, `drafts.ts`, `relayHealth.ts`, `bookmark.ts` -- `src/lib/nostr/` — NDK wrapper (`client.ts` + `index.ts`); all Nostr calls go through here +- `src/lib/nostr/` — NDK wrapper split into domain modules (`core.ts`, `notes.ts`, `social.ts`, `articles.ts`, `engagement.ts`, `dms.ts`, `bookmarks.ts`, `muting.ts`, `search.ts`, `relays.ts`, `trending.ts`); barrel `index.ts` re-exports all; all Nostr calls go through here - `src/lib/lightning/` — NWC client (`nwc.ts`); Lightning payment logic - `src/hooks/` — `useProfile.ts`, `useReactionCount.ts` -- `src/components/feed/` — Feed, NoteCard, NoteContent, ComposeBox -- `src/components/profile/` — ProfileView (own + others, edit form) +- `src/components/feed/` — Feed, NoteCard, NoteContent, NoteActions, InlineReplyBox, TextSegments, MediaCards, ComposeBox +- `src/components/profile/` — ProfileView, EditProfileForm, ImageField, Nip05Field, ProfileMediaGallery - `src/components/thread/` — ThreadView - `src/components/search/` — SearchView (advanced search with modifiers, NIP-50, hashtag, people, articles) - `src/lib/search.ts` — Advanced search query parser (by:, has:, is:, kind:, since:, until:, OR) diff --git a/PKGBUILD b/PKGBUILD index 2732868..04aae15 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: hoornet pkgname=wrystr -pkgver=0.8.3 +pkgver=0.8.4 pkgrel=1 pkgdesc="Cross-platform Nostr desktop client with Lightning integration" arch=('x86_64') diff --git a/README.md b/README.md index 315d5d9..77a9caa 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ sudo dnf install gstreamer1-plugins-base gstreamer1-plugins-good gstreamer1-liba - In-app key generation with plain-language nsec backup — no browser extension required - **Create new account** from the account switcher — no need to restart or go through onboarding again - Login with nsec (full access) or npub (read-only) +- **NIP-46 remote signer** — connect via `bunker://` URI (nsecBunker, Amber, etc.) with session persistence across restarts - **Multi-account switcher** — save multiple identities, switch instantly from the sidebar - **OS keychain integration** — nsec stored in macOS Keychain / Windows Credential Manager / Linux Secret Service; sessions survive restarts @@ -54,12 +55,17 @@ sudo dnf install gstreamer1-plugins-base gstreamer1-plugins-good gstreamer1-liba - **Mute users** (NIP-51) — muted list synced to relays, filtered from feed - **Long-form article experience** (NIP-23) — **markdown toolbar** (bold, italic, heading, link, image, quote, code, list) with keyboard shortcuts (Ctrl+B/I/K); **multi-draft management** with draft list, resume, delete; **cover image file picker**; dedicated article feed with Latest/Following tabs; article search by keyword or hashtag; article reader with reading time, bookmark, like, and zap; profile Articles tab - **Quoted note inline preview** — `nostr:note1…` / `nostr:nevent1…` renders as an inline card +- **Syntax highlighting** — code blocks in notes and articles render with syntax highlighting - Note rendering: images, video, mentions, hashtags, njump.me link interception -- **Direct Messages** (NIP-04) — conversation list, thread view, per-message decryption; unread badge in sidebar -- **Notifications** — mentions view (🔔 in sidebar) with unread badge; clears on open +- **External links** — all http(s) links open in your system browser via Tauri opener +- **Emoji reactions** — reaction picker with common emojis on note cards; emoji insertion in compose and reply boxes via categorized emoji picker +- **Keyword muting** — word/phrase mute list with client-side filtering across all views +- **Direct Messages** (NIP-04 + NIP-17 gift wrap) — conversation list, thread view, per-message decryption; unread badge in sidebar +- **Notifications** — background poller (60s) for mentions, zaps, new followers; each type independently toggleable; OS push notifications; 🔔 in sidebar with unread badge **Relay & network** - **Relay health checker** — NIP-11 info fetch, WebSocket latency probing, online/slow/offline classification; expandable cards show supported NIPs, software, description; "Remove dead" strips offline relays, "Republish list" publishes cleaned NIP-65 relay list; auto-checks on mount +- **Relay recommendations** — discover relays based on your follows' NIP-65 relay lists; shows follow count, one-click "Add" - Relay management: add/remove relays with live connection status - **NIP-65 outbox model** — reads user relay lists (kind 10002) so you see notes from people who publish to their own relays; publish your own relay list to Nostr from Settings @@ -72,18 +78,52 @@ sudo dnf install gstreamer1-plugins-base gstreamer1-plugins-good gstreamer1-liba - **Support / About page** — zap the developer, Lightning + Bitcoin QR codes, Ko-fi and GitHub links **Discovery** -- **Discover people** — "follows of follows" suggestions on the Search page with mutual follow counts and one-click follow +- **Trending feed** — trending notes and articles from the last 24h, ranked by engagement with time decay scoring +- **Media feed** — dedicated "Media" view in sidebar with All/Videos/Images/Audio tab filtering +- **Dedicated hashtag pages** — clicking any #tag opens a live feed for that hashtag +- **Trending hashtags** — popular hashtags shown as clickable pills on the search idle screen +- **Discover people** — "follows of follows" suggestions on the Search page with mutual follow counts and one-click follow; persistent "don't suggest again" per person - **Advanced search** — `by:author`, `mentions:npub`, `kind:number`, `is:article`, `has:image`, `since:2026-01-01`, `until:2026-12-31`, `#hashtag`, `"exact phrase"`, boolean `OR`; NIP-05 resolution for author lookups; client-side content filters for media types; search help panel with modifier reference - Search: NIP-50 full-text, `#hashtag`, people search with inline follow, **article search** (kind 30023) +- **NIP-05 verification badges** — cached verification with green checkmark on note cards **Performance & UX** - **Auto-updater** — "Update & restart" banner when a new version is available - **SQLite note cache** — feed loads instantly from local cache on startup; profiles cached for immediate avatar display +- **Data export** — export bookmarks, follows, and relay list as JSON via native save dialog +- **Profile media gallery** — "Media" tab on profiles shows a grid of the user's images, videos, and audio; images open in lightbox +- **Reading list tracking** — read/unread state on bookmarked articles with unread dot indicators and sidebar badge +- **Profile banner polish** — hero-height banner with click-to-lightbox, avatar overlaps banner edge with ring - **System tray** — close button hides to tray; "Quit" in tray menu to fully exit - Collapsible sidebar (icon-only mode) - **Keyboard shortcuts** — `n` compose, `/` search, `j`/`k` navigate feed, `Esc` back, `?` help overlay - Skeleton loading placeholders, view fade transitions +## Supported NIPs + +| NIP | Description | Status | +|-----|-------------|--------| +| [NIP-01](https://github.com/nostr-protocol/nips/blob/master/01.md) | Basic protocol flow | Full | +| [NIP-02](https://github.com/nostr-protocol/nips/blob/master/02.md) | Follow list | Full | +| [NIP-04](https://github.com/nostr-protocol/nips/blob/master/04.md) | Encrypted direct messages (legacy) | Full | +| [NIP-05](https://github.com/nostr-protocol/nips/blob/master/05.md) | DNS-based verification | Full (display + live verify in editor) | +| [NIP-10](https://github.com/nostr-protocol/nips/blob/master/10.md) | Reply threading | Full | +| [NIP-11](https://github.com/nostr-protocol/nips/blob/master/11.md) | Relay information | Full (health checker) | +| [NIP-17](https://github.com/nostr-protocol/nips/blob/master/17.md) | Private direct messages (gift wrap) | Full | +| [NIP-18](https://github.com/nostr-protocol/nips/blob/master/18.md) | Reposts | Full | +| [NIP-19](https://github.com/nostr-protocol/nips/blob/master/19.md) | bech32-encoded entities | Full (npub, nsec, note, nevent, nprofile, naddr) | +| [NIP-21](https://github.com/nostr-protocol/nips/blob/master/21.md) | `nostr:` URI scheme | Full | +| [NIP-23](https://github.com/nostr-protocol/nips/blob/master/23.md) | Long-form content (articles) | Full (editor, reader, feed, search) | +| [NIP-25](https://github.com/nostr-protocol/nips/blob/master/25.md) | Reactions | Full (emoji reactions) | +| [NIP-27](https://github.com/nostr-protocol/nips/blob/master/27.md) | Text note references | Full | +| [NIP-46](https://github.com/nostr-protocol/nips/blob/master/46.md) | Nostr Connect (remote signer) | Full (bunker:// login) | +| [NIP-47](https://github.com/nostr-protocol/nips/blob/master/47.md) | Wallet Connect (NWC) | Full | +| [NIP-50](https://github.com/nostr-protocol/nips/blob/master/50.md) | Search | Full (notes, articles, people) | +| [NIP-51](https://github.com/nostr-protocol/nips/blob/master/51.md) | Lists | Partial (bookmarks, mute list) | +| [NIP-57](https://github.com/nostr-protocol/nips/blob/master/57.md) | Zaps | Full | +| [NIP-65](https://github.com/nostr-protocol/nips/blob/master/65.md) | Relay list metadata | Full (outbox model) | +| [NIP-98](https://github.com/nostr-protocol/nips/blob/master/98.md) | HTTP Auth | Full (image uploads) | + ## Stack | Layer | Technology | @@ -111,8 +151,8 @@ npm run tauri build # production binary See [ROADMAP.md](./ROADMAP.md) for the full prioritised next steps. Up next: +- Podcast playback with background audio and V4V streaming sats - Web of Trust scoring -- NIP-46 remote signer support - Custom feeds / lists ## Support diff --git a/ROADMAP.md b/ROADMAP.md index 1fead38..df9d009 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -59,6 +59,15 @@ Bugs found during testing are fixed before Phase N+1 starts. A release is cut be --- +## Up next — Podcast playback + +- Persistent `` with background audio +- Fountain.fm integration for podcast discovery +- V4V streaming sats via NWC (value-for-value) +- Episode progress tracking + +--- + ## Brainstorm backlog (not yet scheduled) ### Relay health checker — ✓ SHIPPED (v0.7.1) @@ -92,9 +101,11 @@ Bugs found during testing are fixed before Phase N+1 starts. A release is cut be - Remaining: reading history, table of contents, trending articles, tag suggestions - Cross-posting to other platforms -### NIP-46 remote signer -- Sign events via a remote signer (Nsecbunker, Amber, etc.) -- Would complete the multi-account story for users who don't want nsec in keychain +### NIP-46 remote signer — ✓ SHIPPED (v0.8.3) +- ✓ Connect via bunker:// URI (nsecBunker, Amber, etc.) +- ✓ Session persistence across restarts via toPayload/fromPayload +- ✓ Third login tab in onboarding and add-account modal +- ✓ Account switching between local nsec and remote signer accounts ### NIP-05 monetization (Phase 4 idea) - Offer a paid "Verified NIP-05 name" service (e.g. name@wrystr.app) @@ -105,6 +116,32 @@ Bugs found during testing are fixed before Phase N+1 starts. A release is cut be ## What's already shipped +### v0.8.4 — Codebase Refactor & Docs +- **Codebase refactor** — split 5 overgrown files into focused modules: `client.ts` (1036 lines) into 11 domain files under `lib/nostr/`; `ProfileView`, `NoteContent`, and `NoteCard` split into sub-components. All component files now ≤270 lines, all lib files ≤300 +- **Documentation** — Supported NIPs table in README, updated features list, current roadmap +- **Bug fixes** (from v0.8.3 testing) — mute filtering in media feed, notification toggle sizing, external links via Tauri opener, emoji picker in compose/reply/reactions, trending refresh visual feedback + +### v0.8.3 — Trending, Remote Signer, Media +- **Trending feed** — 24h time window with engagement decay scoring; articles mixed with notes +- **NIP-46 remote signer** — connect via bunker:// URI; session persistence; third login tab +- **Media feed** — new "Media" view with All/Videos/Images/Audio tab filtering +- **Profile media gallery** — "Media" tab on profiles with grid layout; images open lightbox +- **Syntax highlighting** — code blocks render with syntax highlighting +- **OS push notifications** — background poller (60s) for mentions, zaps, new followers; each type toggleable +- **Zen writing mode** — distraction-free article editing with auto-save indicator +- **NIP-05 verification badges** — cached verification with green checkmark on note cards +- **Dedicated hashtag pages** — clicking #tag opens a live feed +- **Keyword muting** — word/phrase mute list, client-side filtering across all views +- **Follow suggestion dismissal** — persistent "don't suggest again" per person +- **Emoji picker** — categorized emoji picker in compose, reply, and reactions + +### v0.8.0 — Polish, Portability & Discovery +- **Profile banner polish** — hero-height banner, click-to-lightbox, avatar overlaps with ring +- **Data export** — bookmarks, follows, relay list as JSON via native save dialog +- **Relay recommendations** — suggest relays from follows' NIP-65 lists with follow count +- **Reading list tracking** — read/unread state on bookmarked articles, unread dot indicators, sidebar badge +- **Trending hashtags** — #t tag frequency analysis from recent events; clickable tag pills + ### v0.7.1 — Relay Health Checker & Advanced Search - **Relay health checker** — NIP-11 info fetch + WebSocket latency probing; relays classified as online/slow/offline; expandable cards show software, description, supported NIPs (badges for 1, 4, 11, 17, 23, 25, 50, 57, 65, 96, 98); header summary counts; "Remove dead" strips offline relays; "Republish list" publishes cleaned NIP-65 relay list; auto-checks on mount - **Advanced search** — full query parser inspired by ants (dergigi/ants); modifiers: `by:author`, `mentions:npub`, `kind:N`, `is:article`, `has:image`, `since:2026-01-01`, `until:2026-12-31`, `#hashtag`, `"exact phrase"`, boolean `OR`; NIP-05 resolution for author lookups; client-side content filters for media types; search help panel with modifier reference diff --git a/package.json b/package.json index aa192da..05161d1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wrystr", "private": true, - "version": "0.8.3", + "version": "0.8.4", "type": "module", "scripts": { "dev": "vite", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 0688ffa..1ac7848 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wrystr" -version = "0.8.3" +version = "0.8.4" description = "Cross-platform Nostr desktop client with Lightning integration" authors = ["hoornet"] edition = "2021" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index e1626eb..d6cc8c0 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "Wrystr", - "version": "0.8.3", + "version": "0.8.4", "identifier": "com.hoornet.wrystr", "build": { "beforeDevCommand": "npm run dev",