Commit Graph

70 Commits

Author SHA1 Message Date
Vitor Pamplona 280f21159f v1.10.0 2026-05-16 16:53:00 -04:00
Vitor Pamplona 7e922692d5 removes ammolite from plans 2026-05-16 12:37:14 -04:00
Vitor Pamplona 8a498695a9 v1.09.2 2026-05-16 12:06:32 -04:00
Vitor Pamplona 5a30b10a77 v1.09.1 2026-05-15 18:25:17 -04:00
nrobi144 46caa4d795 fix(desktop): harden account security — NWC to keychain, single source of truth
CRITICAL: Move NWC wallet secret from plaintext nwc_connection.txt to OS
keychain. The NWC secret is a private key that can authorize Lightning
payments — storing it in plaintext allowed any process to steal funds.

Security fixes:
- NWC secret stored in OS keychain as "nwc_<npub>" (per-account)
- accounts.json.enc is now the sole source of truth for cold boot
- Eliminate bunker_uri.txt, last_account.txt, nwc_connection.txt
- Legacy files deleted on first startup (one-time cleanup)
- logout(deleteKey=true) now removes account from accounts.json.enc
- Corrupted accounts.json.enc backed up as .corrupt.<timestamp>

Cold boot rewrite:
- loadSavedAccount() routes by SignerType from accounts.json.enc
- No longer reads stale bunker_uri.txt (fixes nsec→bunker confusion)
- No longer reads last_account.txt (uses activeNpub from metadata)

Multi-account improvements:
- NWC connections are per-account (switch account = switch wallet)
- Each account type (Internal/Remote/ViewOnly) loads correctly
- saveBunkerAccount() no longer writes to bunker_uri.txt

Updated 8 existing test files to use accountStorage instead of
writing legacy files directly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-15 11:29:42 +03:00
nrobi144 fd34105439 merge: resolve conflicts with upstream/main
Merge upstream main into feat/desktop-multi-account, resolving:
- Main.kt: Surface wrapper + CompositionLocalProvider + nip11Fetcher from upstream, multi-account DeckSidebar/LoginScreen from HEAD
- FeedScreen.kt: viewport-aware scroll from HEAD + contentPadding from upstream
- DeckSidebar.kt: merged imports (multi-account + titleBarInsetTop + MaterialSymbols)
- Migrated AccountSwitcherDropdown + AddAccountDialog from material.icons to MaterialSymbols

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-04 07:29:20 +03:00
nrobi144 250bb5a1ad feat(multi-account): display names, middle-truncated npub, npub-only account fix
Account switcher dropdown improvements:
- Two-row display: Display Name on top, npub (middle-truncated) below
  e.g. 'Alice' / 'npub1abc...wxyz · Bunker'
- Middle-truncation for npub: shows first 10 + last 6 chars
- Resolves display names from DesktopLocalCache user metadata
- Confirmation dialog also shows display name
- npub-only (view-only) accounts now persist to encrypted storage
  (ensureCurrentAccountInStorage called in onLoginSuccess)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-29 09:35:33 +03:00
Claude 8b5af5d496 docs(audio-rooms): refresh against shipped state + nostrnests gap audit
Existing plan docs were written before the moq-lite swap, the
create-space + kind-10112 work, and the harness / submodule findings.
This refresh aligns them with what's actually live on the branch and
captures the work still ahead.

  - 2026-04-26-audio-rooms-completion.md — flipped to a STATUS-FIRST
    layout: implementation table for every protocol/transport/UI
    surface, "pending" table for the remaining items (reconnect,
    level meters, Desktop / iOS, Nests parity), pointers section
    refreshed.
  - 2026-04-26-moq-lite-gap.md — marked DONE with the commit range
    that landed it (fb47a4c71cf99d015b0d7); "When picking up"
    section now points at the shipped surface first, raw protocol
    references second.
  - 2026-04-22-nip-audio-rooms-draft.md — major surgery to match
    today's nostrnests reality:
      * status banner up top calling out the revision
      * dependencies dropped IETF MoQ-transport, added moq-lite
        Lite-03 + ALPN "moq-lite-03"
      * HTTP control plane: GET <service>/<room-d-tag> → POST /auth
        with {namespace, publish}, returning {token}; documented the
        JWT claim shape (root, get, put), 600 s lifetime, regex
        on `namespace`, JWKS endpoint, error matrix
      * Audio transport: replaced IETF SETUP / TrackNamespace tuples
        / OBJECT_DATAGRAM with moq-lite Lite-03 (ControlType varint,
        per-bidi message types, group uni streams, audio/data track,
        no in-band SETUP, FIN-as-unsubscribe semantics)
      * New event-kind sections: kind 4312 (admin command / kick),
        kind 10112 (audio-room server list)
      * Reconciliation section explaining what changed from the
        original draft and why
  - NEW: 2026-04-26-nostrnests-integration-audit.md — punchlist of
    every nostrnests/NestsUI feature we don't yet ship, sourced from
    a code-walk of the React app + moq-auth + API.md (which is
    LiveKit-era and dead). Tier 1 (low-effort, visible): chat,
    reactions, role parsing + promotion, hand-raise queue, kick
    (kind 4312), edit/close room, scheduled rooms, listener counter.
    Tier 2: participant grid, augmented presence tags
    (publishing/onstage), per-avatar context menu + zap, share via
    naddr. Tier 3: room theming. Tier 4: token-refresh +
    Connection.Reload sanity checks.

Verified `:nestsClient:jvmTest` + `:amethyst:compilePlayDebugKotlin`
both still green after the doc changes (no code touched).
2026-04-26 19:23:41 +00:00
Vitor Pamplona 6d8b75c7a2 Merge pull request #2519 from nrobi144/feat/relay-power-tools
feat(desktop): Relay Power Tools — Dashboard, Config Editors, Subscription Wiring
2026-04-23 08:41:22 -04:00
nrobi144 835947d611 feat(desktop): relay config persistence, correct counts, per-screen picker
- Persist relay list events (kinds 10050/10007/10006) as JSON to
  java.util.prefs.Preferences with per-account key isolation
- Load persisted relay configs on startup before bootstrap subscription
- Validate loaded events (kind + pubkey check), 8KB guard on writes
- Fix SearchScreen relay count: "0 of 1" not "0 of 7" — uses searchRelays
- Fix FeedScreen relay count: shows feed relay count, not all connected
- Per-screen relay picker dialogs: Dns icon on Feed and Search screens
  opens AlertDialog wrapping existing editors (Nip65RelayEditor,
  SearchRelayEditor) — no new composable files
- Fix created_at dedup: use >= for replaceable event semantics
- Fix setters: use TimeUtils.now() not Long.MAX_VALUE
- Add consumePublishedEvent() for local immediate update after publish
- Remove stale "not loaded" warnings from Search/Blocked editors
- Fix FeedHeader type: Set<NormalizedRelayUrl> not Set<Any>
- Fix picker LaunchedEffect(Unit) to not overwrite user edits

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-23 12:00:03 +03:00
Claude ac1e751bec docs: draft NIP-XX — Interactive Audio Rooms Join Protocol
Captures the gap between NIP-53's room discovery and what audio-capable
clients/servers must actually agree on to interop. NIP-53 defines the
30312 event but leaves the HTTP control plane + MoQ namespacing +
audio codec params entirely to individual implementations. With Nests
going generic-server, this is the moment to standardize.

What the draft covers:

1. HTTP control plane:
   - Path convention: GET <service>/<d-tag>
   - NIP-98 `Authorization: Nostr <base64>` header required
   - JSON response shape (endpoint, token, transport, codec,
     sample_rate, frame_duration_ms, moq_version)
   - Canonical error-status map (401/403/404/410/503)
2. WebTransport + MoQ handshake requirements (Extended CONNECT,
   required HTTP/3 settings, Bearer token passing).
3. MoQ track naming — vendor-neutral one-element namespace
   `[<d-tag>]` with track-name = speaker-pubkey-hex. Explicit
   rejection of the `["nests", <d-tag>]` prefix for new deployments.
4. Audio object format: raw Opus packets (no Ogg, no TOC), 48 kHz
   mono, 20 ms default, mono PCM 16-bit decode target. Both
   OBJECT_DATAGRAM and STREAM_HEADER_SUBGROUP accepted; listeners
   MUST handle both.
5. Per-track access control: server MUST verify publishing pubkey is
   a host/speaker in the current 30312 event (which is replaceable —
   revocation cascade is spec'd).
6. Leave procedure (UNSUBSCRIBE, UNANNOUNCE, final 10312 presence,
   WT_CLOSE_SESSION capsule).
7. Presence extension: the `["muted", "1"|"0"]` tag we already ship
   in nestsClient's MeetingRoomPresenceEvent overload, promoted from
   Amethyst-specific to NIP-defined.
8. Server + client requirements summaries.
9. Known divergences from current nostrnests/nests servers (two-
   element `["nests", <d-tag>]` namespace + `/api/v1/nests/<d-tag>`
   path) with a transition strategy via a `"nip_xx": true` flag in
   room-info responses.
10. Security considerations (bearer-token handling, NIP-98 `u` tag
    binding, audio-replay attack surface, server-impersonation VU
    meter recommendation).

Deliberately out of scope: E2E-signed audio objects (future NIP),
federation between audio servers, room recording/transcription.

Intended workflow: share with the Nests team while they're designing
the generic server, land changes against their feedback, then open a
PR on nostr-protocol/nips.

https://claude.ai/code/session_013nVLALALKaHVgHm9u5Cg8D
2026-04-22 13:27:18 +00:00
Claude 2b44e9b06b docs(quic-plan): lock in new top-level :quic module (Option A)
Updates the Architecture section to reflect the decision to house the
pure-Kotlin QUIC + HTTP/3 + WebTransport code in a new top-level
Gradle module `:quic`, sibling to `:quartz`, `:commons`, `:nestsClient`.

Key changes:

- Module placement: new KMP module `:quic` with commonMain +
  jvmAndroid + jvmMain + androidMain source sets (mirrors Quartz).
  `:quic` takes `api(project(":quartz"))` so all crypto primitives
  are in-scope without re-export.
- settings.gradle delta spelled out.
- Package layout shifts from
  `nestsClient/src/jvmAndroid/...transport/quic/` to
  `:quic/src/commonMain/com/vitorpamplona/quic/`, with UDP
  socket-specific bits in `jvmAndroid/`.
- Varint.kt migration called out: moves from
  `nestsClient/moq/Varint.kt` to `:quic` at
  `com.vitorpamplona.quic.Varint`. Mechanical, one commit.
- Rename KwikWebTransportFactory stub → QuicWebTransportFactory
  (real), living in `:quic` but implementing `:nestsClient`'s
  existing `WebTransportFactory` interface. AudioRoomConnectionViewModel
  changes one ctor call.
- Rationale section documenting why Option A beats putting it in
  `:nestsClient` (single responsibility / reusability / security
  boundary / test isolation / build graph / charter fit).
- Phase A now explicitly includes the module-creation +
  Varint-migration step; test suite must stay green across the move.

Timeline unchanged (17-19 weeks). Dependency story unchanged
(no external libs; everything piggybacks on Quartz).

https://claude.ai/code/session_013nVLALALKaHVgHm9u5Cg8D
2026-04-22 13:20:33 +00:00
Claude 1ff951dbb4 docs(quic-plan): drop BouncyCastle — Quartz already has every primitive
Audited Quartz's crypto surface and found every primitive the QUIC
plan called out for BouncyCastle is already present in commonMain:

- `utils/ciphers/AESGCM.kt` — AES-GCM with AAD (QUIC-TLS AEAD)
- `nip44Encryption/crypto/ChaCha20Poly1305.kt` — pure-Kotlin AEAD
- `nip44Encryption/crypto/Hkdf.kt` + `utils/mac/MacInstance.kt` — HKDF
- `utils/sha256/Sha256.kt` — SHA-256
- `marmot/mls/crypto/X25519.kt` — X25519 ECDH (TLS 1.3 key exchange)
- `marmot/mls/crypto/Ed25519.kt` — Ed25519 signatures
- `utils/SecureRandom.kt`

Plan update highlights:
- "What we delegate" section rewritten to point at Quartz primitives.
- Phase B renamed from "TLS via BouncyCastle" to "TLS 1.3 client state
  machine on Quartz primitives"; bumped from 2 to 3 weeks because we
  write the state machine ourselves, but eliminates the entire
  BC-adapter integration risk.
- "Dependencies to add" section zeroed out — nothing goes in
  gradle/libs.versions.toml. The only new primitive is a thin
  HKDF-Expand-Label helper on top of existing `MacInstance`, which
  we can upstream to Quartz's `Hkdf` as a general `expand(prk,
  info, length)`.
- Risk table rewritten: removed BC-specific risks, added
  Quartz-specific ones (verify `X25519.dh` against RFC 7748 vector
  on Phase B day-1).
- Cert chain signature verification uses JDK `Signature` for RSA +
  ECDSA plus Quartz `Ed25519` for Ed25519 leaves.

Total timeline moves from 16-18 weeks to 17-19 weeks — same band,
but with zero external dependencies and zero Maven-resolution risk.

https://claude.ai/code/session_013nVLALALKaHVgHm9u5Cg8D
2026-04-22 12:25:58 +00:00
Claude 40308dc917 docs: pure-Kotlin QUIC + WebTransport implementation plan
Captures the plan to unblock Phase 3b-2 (the WebTransport handshake)
by writing a Kotlin QUIC client rather than depending on a Java QUIC
library. Triggered by exhausting the off-the-shelf options:

- tech.kwik:* coords don't exist on Maven Central we can resolve.
- Netty incubator HTTP/3 needs an Android quiche-native that isn't
  published.
- Cronet doesn't expose WebTransport.
- WebView JS bridge rejected by product.

The plan delegates TLS 1.3 + crypto primitives to BouncyCastle (bcprov
+ bcpkix already cached, bctls to add) and has us writing the QUIC
packet/frame/state-machine layer + HTTP/3 + WebTransport on top.

Realistic estimate: 16-18 weeks one developer full-time, or 5-6
months at a normal cadence, plus a security review before shipping.

Hard abandonment trigger documented: if the RFC 9001 Appendix A
Initial-packet test vectors don't bit-match by end of Phase D
(~6 weeks in), abandon and wait for an Android-compatible upstream.

The plan is committed as a doc rather than executed in this session
because each phase is multi-week and would block the rest of the
audio-rooms feature in the meantime.

https://claude.ai/code/session_013nVLALALKaHVgHm9u5Cg8D
2026-04-22 08:35:09 +00:00
nrobi144 66962d360d feat(desktop): relay power tools — dashboard, config editors, subscription wiring
- Relay Dashboard as new DeckColumnType.Relays with Monitor + Configure tabs
- Monitor tab: live 1Hz session metrics, NIP-11 detail panels, reconnect
- Configure tab: collapsible editors for Connected, NIP-65 (R/W/Both toggles),
  DM (kind 10050), Search (kind 10007), Blocked (kind 10006)
- Compose Relay Picker: expandable relay selection in note compose dialog
- Nip11Fetcher: fail-closed HTTP client, 256KB limit, Mutex dedup
- RelayMetrics: separate StateFlow (1Hz) to avoid relayStatuses churn
- Bootstrap subscription: fetches user's relay config on login (kinds 10002/10050/10007/10006)
- DesktopRelayCategories aggregator: feedRelays, searchRelays, notificationRelays, dmRelays
  with fallback logic, blocked subtraction, 1s debounce
- LocalRelayCategories CompositionLocal (matches LocalTorState pattern)
- FeedScreen uses NIP-65 outbox relays, SearchScreen uses search relays
- "X relays connected" on feed is clickable → opens Relay Dashboard
- URL validation: requires domain with dot, blocks ws:// unless .onion
- Auto-add pending input on Save, empty list protection
- Thread-safe created_at dedup (AtomicLong) in DesktopAccountRelays
- DisposableEffect cleanup for bootstrap subscription

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-22 10:15:44 +03:00
nrobi144 01fc5f3ac6 fix(tor): remove broken runtime reconnect, add evictConnections
Remove the LaunchedEffect/scope.launch reconnect code that didn't
work (relay subscriptions lost after disconnect+connect cycle).
Tor toggle will use app rebuild via key() instead (next commit).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 07:25:45 +03:00
nrobi144 11d0a657ac fix(tor): close 8 network traffic leaks — fail-closed when Tor expected
SECURITY: With Tor ON, all HTTP traffic now routes through SOCKS proxy.
Previously only relay WebSocket connections used Tor; 8 other egress
paths created bare OkHttpClient() instances bypassing Tor entirely.

Fail-closed behavior:
- When Tor expected but bootstrapping → dead SOCKS proxy on port 1
  (requests fail instead of leaking IP)
- lateinit var crashes on misconfiguration (loud failure vs silent leak)

Leak sites fixed (all use DesktopHttpClient.currentClient()):
- AnimatedGifImage: GIF fetch
- SaveMediaAction: media downloads
- EncryptedMediaService: NIP-17 DM media
- ServerHealthCheck: Blossom server probes
- NoteActions: zap/lightning LNURL resolution
- DesktopBlossomClient: media uploads
- AccountManager: NIP-46 bunker relay connections
- Coil image loader: TODO (OkHttpNetworkFetcher import issue)

Also:
- Relay reconnect on Tor Active (prevents stale clearnet connections)
- isTorExpected() for fail-closed logic
- Tests updated for new torTypeProvider parameter

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 07:25:45 +03:00
Vitor Pamplona 787b9ab9db Merge pull request #1905 from nrobi144/feat/desktop-cache-v2
feat(desktop): cache-centric architecture for desktop feeds
2026-03-27 15:45:34 -04:00
Vitor Pamplona d0a3679778 Minimizes the size of the banner 2026-03-26 14:35:18 -04:00
nrobi144 61119e6916 docs: deepen cache plan — BoundedLargeCache, FeedNoteCard rewrite details
- Resolve LruCache vs LargeCache: use LargeCache (lock-free ConcurrentSkipListMap)
  with BoundedLargeCache wrapper for size enforcement on put()
- Confirm LargeCache available on desktop via quartz jvmAndroid source set
- Detail FeedNoteCard rewrite: Note model field mapping, 5 subscription removals
- Fix filter examples to use filterIntoSet (LargeCache API)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 07:12:46 +02:00
nrobi144 9c160006fa docs: desktop cache architecture brainstorm and plan
Cache-centric architecture for navigation persistence, mirroring
Android Amethyst's pattern. Three-phase incremental migration:
Phase 1 - Store events in DesktopLocalCache with LRU eviction
Phase 2 - Create FeedFilter implementations
Phase 3 - Migrate screens to FeedViewModel

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 07:12:45 +02:00
Vitor Pamplona 138bb144ee Merge branch 'main' into claude/review-cache-cleanup-Yr2P6 2026-03-25 13:20:30 -04:00
davotoula 42db03790a added progress and test plan to doc 2026-03-25 10:23:38 +01:00
davotoula 390edf311d analysis for temporary files 2026-03-25 09:29:48 +01:00
nrobi144 efa294ea72 feat(highlights): add article highlights and note-taking system
Phase 1: HighlightData model + DesktopHighlightStore (Preferences-based)
Phase 2: Text selection highlight via Cmd+H/Cmd+Shift+H, inline bold/italic
         rendering, HighlightAnnotationDialog, SelectionContainer wrapping
Phase 3: MyHighlightsScreen with grouped view, HighlightPublishAction for
         NIP-84 (kind 9802), deck/sidebar/menu wiring

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 12:16:54 +02:00
nrobi144 328fcf86d7 refactor(reads): address all review findings — security, performance, simplicity
P1 Critical:
- Add 300ms debounce on editor preview to prevent AST re-parse per keystroke
- Hoist Regex constants in ReadingTimeCalculator and TableOfContents
- Add URI scheme allowlist to editor onLinkClick (was missing vs reader)
- Add MAX_CONTENT_BYTES (100KB) validation before publish

P2 Important:
- Delete MarkdownSpikeScreen (278 LOC spike artifact)
- Delete HighlightCreator (95 LOC, zero callers — YAGNI)
- Delete DraftLongTextNoteEvent (162 LOC, no consumers — YAGNI)
- Replace ArticleMediaRenderer interface with onLinkClick lambda
- Extract inline subscription to FilterBuilders.longFormByAddress()
- Replace SimpleDateFormat with thread-safe DateTimeFormatter
- Remove dead placeholders (bookmark button, reactions row, unused param)
- Cache draft index in memory to avoid redundant disk reads
- Add TODO for publish-before-relay-ack issue

P3 Nice-to-have:
- Remove timestamp from subscription subId for stability
- Remove redundant slug ".." removal (regex handles it)
- Add metadata field length limits (title 256, summary 1024)
- Fix identical isMacOS branches in editor
- Validate image URLs (http/https only) in ArticleHeader

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 11:03:29 +02:00
Vitor Pamplona 439b392aa0 Moves EmptyNostrClient to a class to avoid auto-import issues 2026-03-22 15:14:49 -04:00
nrobi144 5b2f2ca42b feat(chats): per-message encryption badge — lock for NIP-17, lock-open for NIP-04
Show a small lock icon next to the timestamp on each DM message:
- NIP-17 (ChatMessageEvent, ChatMessageEncryptedFileHeaderEvent): filled
  lock in primary color — relay can't see sender/recipient
- NIP-04 (PrivateDmEvent): open lock in muted gray — legacy encryption,
  metadata visible to relays

Matches Android's IncognitoBadge pattern. Both NIP-04 and NIP-17 messages
in the same 1-on-1 conversation produce identical ChatroomKeys, so they
merge into one conversation — the badge is the only way to tell them apart.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 09:23:06 +02:00
nrobi144 e06287acb3 feat(chats): stacked messages layout in deck columns
In multi-deck mode, Messages column now uses stacked navigation instead
of side-by-side split pane. Full-width contact list OR full-width chat —
clicking a conversation navigates to chat, back arrow returns to list.

Single-pane mode keeps the existing split layout (280dp list + flex chat).

Changes:
- Add compactMode param to DesktopMessagesScreen (default false)
- Extract SplitMessagesContent and CompactMessagesContent composables
- Add onBack callback to ChatPane with back arrow in header
- Remove hardcoded 280dp from ConversationListPane (caller controls width)
- Pass compactMode=true from deck RootContent

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 07:49:36 +02:00
nrobi144 24d4073b9b feat(media): encrypted file sharing in desktop DMs (NIP-17 Phase 6)
Add full send + receive encrypted media support in desktop DM chat:
- Paperclip attach button and drag-and-drop in ChatPane (NIP-17 mode only)
- AES-GCM encryption before upload to Blossom server
- ChatMessageEncryptedFileHeaderEvent (kind 15) wrapped in GiftWrap
- sendNip17EncryptedFile() added to IAccount interface and implementations
- DesktopUploadOrchestrator.uploadEncrypted() with proper encrypted hash
- DesktopBlossomClient ByteArray upload overload for encrypted blobs
- LRU cache in EncryptedMediaService to avoid re-downloading
- Error handling: retry on failure, disable send during upload

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 06:53:36 +02:00
nrobi144 c90bf8f610 feat(media): add Note/Picture post type selector; fix gallery crash
- Post type toggle (Note vs Picture/kind 20) in compose dialog, only
  shown when image files are attached. Text input disabled in picture mode.
- Fix LazyVerticalGrid crash in GalleryTab: bounded height via
  fillParentMaxHeight() when nested inside LazyColumn.
- Phase 1 testing plan: all pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 14:42:44 +02:00
nrobi144 cf17dea53f feat(media): add Note/Picture post type selector in compose dialog
When images are attached, a Note/Picture toggle appears letting the user
publish as kind 20 (PictureEvent) instead of kind 1. Text input is
disabled in picture mode. Selector only shows for image file types.
Updates testing plan: Phase 1 all pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 14:37:48 +02:00
nrobi144 1d1d32da0e feat(media): add server selector to compose dialog; update testing plan
Server selector dropdown appears when files are attached, letting the
user choose which Blossom server to upload to. Updates testing plan:
Phase 2 & 3 all pass, Phase 9 audio tested with volume bug tracked.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 14:26:47 +02:00
nrobi144 836e024bd7 feat(media): use VLC :start-volume for initial audio; document volume bug
Passes :start-volume media option to VLC on play. Removes polling/delay
volume hacks. Documents 9.7 volume bug in testing plan — VLC ignores
initial volume on macOS, needs further investigation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 13:26:52 +02:00
nrobi144 2a6087af27 feat(media): global media player — persistent playback across navigation
Media playback now survives navigation. A GlobalMediaPlayer singleton owns
VLC players and exposes StateFlows. Composables are thin viewports.
NowPlayingBar has full controls (volume, mute, save, fullscreen).
GlobalFullscreenOverlay renders video fullscreen above all screens.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 12:27:13 +02:00
nrobi144 5a437ed5ac feat(search): collapsible section headers + sorting + search improvements
- Collapsible sticky section headers with animated chevron
- Full header row clickable to toggle collapse
- SearchResultSorter, SearchSortOrder, pseudo-kind filtering
- TextFieldValue cursor preservation, relay timeout improvements

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 13:23:27 +02:00
nrobi144 5475d6c2bc fix(desktop): verify user pubkey via get_public_key after nostrconnect login
The nostrconnect flow was trusting params[0] from the signer's connect
message as the user's pubkey. Some signers (e.g. nsec.app) don't put
the actual user pubkey there, causing all relay subscriptions to query
the wrong identity — contact lists, profiles, and DMs all returned empty.

Now calls remoteSigner.getPublicKey() after the handshake to get the
verified pubkey from the signer. Also stabilizes FeedScreen relay
subscriptions with distinctUntilChanged() and adds relay.primal.net
to defaults.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 10:20:18 +02:00
M 3f39f96e81 fix: route ElectrumX through Tor proxy, add onion server
- ElectrumxClient accepts injected SocketFactory (lambda) so connections
  respect the user's Tor/proxy settings instead of leaking their IP
  through raw sockets
- Add ProxiedSocketFactory for SOCKS5 proxy routing
- Add .onion ElectrumX server as primary when Tor is enabled, with
  electrumx.testls.space as clearnet fallback
- NamecoinNameResolver accepts serverListProvider lambda for dynamic
  server selection based on current Tor settings
- RoleBasedHttpClientBuilder.socketFactoryForNip05() bridges Amethyst's
  Tor settings to the socket factory
- NamecoinNameService now requires explicit init with proxy-aware client
- Remove dead code: Nip05NamecoinAdapter (never referenced),
  NamecoinVerificationDisplay (never called)
- Update design documentation
2026-03-03 06:28:01 +11:00
M f6447d2020 feat: wire Namecoin search into SearchBarViewModel
Resolve .bit, d/, and id/ identifiers from the search bar via
ElectrumX blockchain lookups. Typing any Namecoin identifier format
(m@testls.bit, testls.bit, d/testls, id/alice) now queries the
Namecoin blockchain and shows the resolved user at the top of results.

The namecoinResolvedUser flow in SearchBarViewModel detects Namecoin
identifiers, resolves them through NamecoinNameService, and prepends
the result to the standard local cache search results.

Updated docs with search integration details and manual testing guide.
2026-03-02 19:43:24 +11:00
M d82ace2f63 feat: Namecoin NIP-05 identity verification via ElectrumX
Add censorship-resistant NIP-05 verification using the Namecoin blockchain.
Users can set their nip05 field to a .bit domain (e.g. alice@example.bit)
or direct Namecoin name (d/example, id/alice) and Amethyst will resolve
the pubkey mapping via ElectrumX instead of HTTP.

Resolution uses the standard Electrum protocol (scripthash-based lookups):
- Build canonical name index script matching ElectrumX-NMC indexing
- Query blockchain.scripthash.get_history for the name's tx history
- Parse NAME_UPDATE script from the latest transaction output
- Extract Nostr pubkey from the name's JSON value

Supports both d/ (domain) and id/ (identity) Namecoin namespaces,
simple and extended NIP-05-like value formats with relay hints,
LRU caching with 1h TTL, and self-signed TLS certificates.

New files:
- quartz: ElectrumxClient, NamecoinNameResolver, NamecoinLookupCache
- amethyst: NamecoinNameService, Nip05NamecoinAdapter, NamecoinVerificationDisplay
- docs: namecoin-nip05-design.md
- tests: NamecoinNameResolverTest

Modified:
- Nip05Client: optional namecoinResolver routes .bit to blockchain
- AppModules: wire up resolver

See docs/namecoin-nip05-design.md for full architecture and protocol details.
2026-03-02 13:07:46 +11:00
nrobi144 42b33ca04c feat(chess): add platform adapters and enhance lobby state (steps 5-6)
- Add ChessLobbyState with completedGames, replaceGameState(), moveToCompleted()
- Add challengerAvatarUrl to ChessChallenge
- Add CompletedGame data class for game history

Platform Adapters:
- AndroidChessAdapter: AndroidChessPublisher, AndroidRelayFetcher, AndroidMetadataProvider
- DesktopChessAdapter: DesktopChessPublisher, DesktopRelayFetcher, DesktopMetadataProvider

Shared Infrastructure:
- ChessRelayFetchHelper for one-shot relay queries
- IUserMetadataProvider interface for platform-specific metadata
- ChessFilterBuilder with simple filter methods for fetchers
- ChessSubscriptionController interface for subscription management

Fix ChessSubscription.kt to remove broken dataSources().chess reference
(subscriptions now managed by ChessLobbyLogic)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-10 12:14:34 +02:00
nrobi144 c2f035acc0 docs: update chess implementation status
- Mark ChessViewModel, navigation, relay subscriptions as complete
- Update file structure to reflect KMP commons migration
- Update checklist with completed items
- Revise next steps to focus on FAB and badge display

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-10 12:10:39 +02:00
nrobi144 06accf5831 full chess implementation 2026-02-10 11:58:00 +02:00
nrobi144 4339247815 key storage 2026-01-06 06:49:59 +02:00
nrobi144 8c8a4ab9e8 feat: Add relay connections, login, and feed view to desktop app
- Add DesktopHttpClient and DesktopRelayConnectionManager for relay WebSocket connections
- Implement AccountManager with key generation and nsec/npub login support
- Create LoginScreen with key import and new key generation UI
- Build FeedScreen with live global feed subscription and note cards
- Add ProfileScreen showing account info and logout
- Update RelaySettingsScreen with connection status and relay management
- Configure JDK 21 toolchain for desktop builds
- Add shared UI analysis documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 14:02:44 +02:00
Vitor Pamplona 39c9b75bf4 Moves zapstore to local image and first in the list 2024-11-04 10:15:31 -05:00
Vitor Pamplona 45b568f6a7 updates amy bg 2024-09-18 17:21:44 -04:00
Vitor Pamplona 446859e8bd adds amy 2024-09-18 17:16:52 -04:00
Vitor Pamplona e1b24c22b9 adds phone mockups 2024-09-18 17:16:38 -04:00
Vitor Pamplona e0b1c4dc3f Sending jpg and webp version of the image 2024-09-18 16:28:07 -04:00