Commit Graph

9855 Commits

Author SHA1 Message Date
Vitor Pamplona badc681511 Merge pull request #1851 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-03-15 16:01:44 -04:00
Claude d10687d6fe feat: Implement iOS OptimizedJsonMapper using KotlinSerializationMapper
Replace all TODO stubs in the iOS actual implementation with delegation
to KotlinSerializationMapper. Wraps SerializationException into
IllegalArgumentException to match the jvmAndroid error handling pattern.

https://claude.ai/code/session_01QBc4Pb7a6m4TfLZSJKVdjw
2026-03-15 19:58:40 +00:00
Claude 3bea2f795c refactor: Move KSerializers to their respective NIP packages
- Bunker serializers → nip46RemoteSigner/kotlinSerialization/
- NIP-47 serializers → nip47WalletConnect/kotlinSerialization/
- Rumor serializer → nip59Giftwrap/rumors/kotlinSerialization/

Mirrors the existing Jackson serializer directory structure which uses
a jackson/ subpackage within each NIP package.

https://claude.ai/code/session_01QBc4Pb7a6m4TfLZSJKVdjw
2026-03-15 19:55:19 +00:00
Claude ffac682238 feat: Add kotlinx.serialization KSerializers mirroring all Jackson custom serializers
Add 15 KSerializer implementations in commonMain that replicate the exact
behavior of all 21 Jackson serializer/deserializer registrations:

- EventKSerializer, TagArrayKSerializer, FilterKSerializer
- EventTemplateKSerializer, RumorKSerializer, CountResultKSerializer
- MessageKSerializer (8 message types), CommandKSerializer (5 command types)
- BunkerRequest/Response/MessageKSerializer (NIP-46)
- Nip47Request/Response/NotificationKSerializer (NIP-47)
- KotlinSerializationMapper as the main entry point

Uses JsonElement-based approach for performance. All serializers produce
identical JSON output to Jackson. Includes comprehensive test suite (35+
tests) verifying exact output parity and cross-deserialization between
Jackson and kotlinx.serialization.

https://claude.ai/code/session_01QBc4Pb7a6m4TfLZSJKVdjw
2026-03-15 16:37:22 +00:00
Claude 22945b7faa feat: add queryCountSuspend utility to Quartz and simplify ViewModels
Add INostrClient.queryCountSuspend() extension functions in Quartz that
wrap NIP-45 COUNT queries as suspend functions, managing subscription
lifecycle internally. Two overloads: single-relay and multi-relay.

Simplify BasicRelaySetupInfoModel and Nip65RelayListViewModel to use the
new utility — removes IRelayClientListener implementation, subId tracking
maps, onIncomingMessage handlers, and cleanup logic from both ViewModels.

https://claude.ai/code/session_016158D5mq5BygS1uBbLNbsA
2026-03-15 16:14:24 +00:00
Crowdin Bot d8de0a9b84 New Crowdin translations by GitHub Action 2026-03-15 15:47:20 +00:00
Claude 17c3611f50 feat: redesign RelayEventCountRow with pill chip style
Replace the plain icon+text count display with rounded pill chips that
have a subtle green border and tinted background. Each count entry gets
its own pill with an icon and bold text, making the event counts more
visually distinct and scannable.

https://claude.ai/code/session_016158D5mq5BygS1uBbLNbsA
2026-03-15 15:46:56 +00:00
Vitor Pamplona 3bd6ef5f6c changes from damus to nos.lol for more stable relay behavior in tests 2026-03-15 11:44:20 -04:00
Vitor Pamplona 2b157cc383 Fixes throw vs null test cases and nsec hallucinations 2026-03-15 11:18:39 -04:00
Vitor Pamplona a793ff149b Merge branch 'main' of https://github.com/vitorpamplona/amethyst
* 'main' of https://github.com/vitorpamplona/amethyst:
  New Crowdin translations by GitHub Action
2026-03-15 11:18:10 -04:00
Vitor Pamplona c0a81ef9a2 Merge pull request #1850 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-03-15 11:07:30 -04:00
Crowdin Bot 68f58c3b8d New Crowdin translations by GitHub Action 2026-03-15 15:06:39 +00:00
Vitor Pamplona 0380927f7e fromJsonTo calls throw, they should always be wrapped if we want null results. 2026-03-15 11:05:40 -04:00
Vitor Pamplona 2c91fdea15 Avoids using format to write hex-encoded strings. 2026-03-15 11:03:50 -04:00
Claude 764c2241ca refactor: integrate relay event counts into each ViewModel
Move count query logic from separate RelayEventCountViewModel into each
relay list's own ViewModel. BasicRelaySetupInfoModel now manages counts
via countFilters() override. Nip65RelayListViewModel gets its own count
infrastructure for home (outbox) and notification (inbox) relay lists.
Simplify AllRelayListScreen by removing 7 extra count ViewModels and
their LaunchedEffects.

https://claude.ai/code/session_016158D5mq5BygS1uBbLNbsA
2026-03-15 15:02:09 +00:00
Claude b1723a5dfb feat: add relay event count stats to AllRelay settings screen
Use NostrClient's NIP-45 COUNT queries to show how many events each
relay stores, with filters specific to each relay role:
- Outbox: events authored by the user
- Inbox: events where the user is p-tagged
- DM Inbox: DM events (kind 4, 1059) tagging the user
- Private Home: events authored by the user
- Proxy: total event count
- Search: total event count
- Indexer: kind 0 and kind 10002 counts separately
- Broadcast: no count (as specified)

https://claude.ai/code/session_016158D5mq5BygS1uBbLNbsA
2026-03-15 14:41:19 +00:00
Claude 997a59dc23 feat: add file encryption toggle for encrypted DMs with retry on failure
Add an "Encrypt files" toggle (default: on) to the file upload dialog in
NIP-17 encrypted DMs. When encrypted upload fails, show an informative
dialog explaining that many servers don't accept encrypted files on free
accounts, with an option to retry without encryption. The retry dialog
warns that without encryption anyone with the link can see the content.

https://claude.ai/code/session_012xvKzHrZPq3ZTAzBN2LvrR
2026-03-15 14:30:26 +00:00
Claude aecbcb68a5 feat: per-relay recv/new counts and OK-true acceptance tracking
ViewModel:
- MAX_ACTIVITY_LOG raised to 5000
- Remove activeRelays from LiveSyncActivity (active relay chips removed)
- Add eventsAccepted: Int to CompletedRelayInfo
- Add totalEventsAccepted: Int to SyncState.Done
- Register IRelayClientListener on account.client for the duration of
  the sync to intercept OkMessage(success=true) from destination relays
- sourceRelayOfEvent map attributes each forwarded event to the relay
  it was first seen on; ConcurrentHashMap.remove() ensures the first
  OK true is counted exactly once per event (dedup across dest relays)
- acceptedCountPerRelay accumulates per-source-relay accepted counts,
  read at onRelayComplete time
- downloadFromPool.onEvent changed to (Event, NormalizedRelayUrl) to
  carry the source relay into runSync routing logic

Screen:
- Remove ActiveRelaysCard and ActiveRelayChip composables + preview
- Remove animation imports (no longer needed)
- ActivityLogRow now shows two right-hand columns per relay:
    recv N  — events received from that source relay
    new N   — events accepted as new by destination relays (highlighted
               in primary color when > 0)
- DoneCard now shows three lines:
    Forwarded N events to destination relays.
    M events accepted as new by destination relays.  ← key headline
    Completed in N seconds.

Strings: event_sync_done_body replaced by done_sent / done_accepted /
done_duration; event_sync_reading_from and events_found_log removed;
log_recv and log_new added.

https://claude.ai/code/session_01U8qF9mK4UBvXsXP1zNMXfX
2026-03-15 14:19:08 +00:00
David Kaspar a21e38f428 Merge pull request #1847 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-03-15 11:53:03 +00:00
Crowdin Bot 7999010390 New Crowdin translations by GitHub Action 2026-03-15 11:51:55 +00:00
David Kaspar 00fb924dbb Update README with build instructions and requirements
Added instructions for full build and requirements.
2026-03-15 11:50:24 +00:00
davotoula f28fdd8404 Convert between flag types
spotlessApply
2026-03-14 21:39:27 +01:00
David Kaspar f3aafd3884 Merge pull request #1845 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-03-14 20:26:58 +00:00
Crowdin Bot 2df98c456a New Crowdin translations by GitHub Action 2026-03-14 20:04:41 +00:00
David Kaspar 21bf8a343a Merge pull request #1844 from davotoula/update-translations
update cz, pt, de, sv
2026-03-14 20:03:08 +00:00
David Kaspar caee58da55 Add migrations.xml to .gitignore 2026-03-14 20:02:48 +00:00
davotoula 64bf1d5090 update cz, pt, de, sv 2026-03-14 21:00:31 +01:00
Vitor Pamplona ee449f78f4 Merge pull request #1843 from davotoula/bugfix-multiple-spinners-on-upload
Bugfix: multiple spinners on upload
2026-03-14 14:10:22 -04:00
David Kaspar 9d14a2d840 Merge pull request #1842 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-03-14 17:30:32 +00:00
davotoula 795da8cf1b Block Add to message button while uploading 2026-03-14 18:00:36 +01:00
davotoula 1fc0ba8628 refactor:
extract MediaUploadTracker with common methods

bugfixes:
 ChatFileUploadState.canPost() was missing isUploadingFile check
 ChatNewMessageViewModel.cancel() was never resetting upload flags
 Double-reset in ChatFileUploader and ChannelNewMessageViewModel
2026-03-14 18:00:36 +01:00
davotoula 42542159d4 bugfix: remove dead code
bugfix: ChannelNewMessageViewModel canPost checks wrong state
2026-03-14 18:00:36 +01:00
davotoula c290a1c779 - SelectFromGallery and SelectFromFiles now accept an enabled param separate from isUploading
- All ViewModels track isUploadingFile alongside isUploadingImage, set via hasNonMedia()
  - All screen call sites pass source-specific flags so only the initiating button spins
  - canPost() methods block posting during file uploads too
  - ChatNewMessageViewModel delegates to ChatFileUploadState (fixes pre-existing dead state)
  - cancel() methods reset both flags in all ViewModels
2026-03-14 17:59:35 +01:00
Claude a49a0ac9ae feat: add @Preview composables to EventSyncScreen
One ThemeComparisonColumn preview per card — renders both dark and light
themes stacked — covering all independently previewable composables:

  SyncProgressCardPreview  — mid-sync progress (312/1024 relays, 4821 sent)
  PausedCardPreview        — paused state with relay/event counts
  DoneCardPreview          — completed run (18K events, 187s)
  ErrorCardPreview         — configuration error message
  ActiveRelaysCardPreview  — 5-relay FlowRow with pulsing chips
  DestinationRelaysCardPreview — all three sections (outbox/inbox/DM)
  ActivityLogCardPreview   — mixed log: found events + empty/unreachable

https://claude.ai/code/session_01U8qF9mK4UBvXsXP1zNMXfX
2026-03-14 16:16:36 +00:00
Claude 6aacaa7d41 fix: remove event sync section item from AllRelayListScreen
https://claude.ai/code/session_01U8qF9mK4UBvXsXP1zNMXfX
2026-03-14 15:51:41 +00:00
Crowdin Bot 0dce9542fb New Crowdin translations by GitHub Action 2026-03-14 15:41:38 +00:00
Vitor Pamplona 42574f302c updates change log 2026-03-14 11:39:02 -04:00
Vitor Pamplona d4ae3411c7 spotless 2026-03-14 11:36:58 -04:00
Vitor Pamplona 6739e66bd3 Merge pull request #1828 from vitorpamplona/claude/implement-nip47-wallet-Fjcds
Implement NIP-47 Wallet Connect protocol with full method support
2026-03-14 11:32:51 -04:00
Claude 78c66b00eb fix: align arrow icons to 40dp to match user picture size
https://claude.ai/code/session_01JFogiwyR4CPVP8cRznqahJ
2026-03-14 15:29:28 +00:00
Claude b7dd460734 feat: live relay activity UI for event sync screen
ViewModel now emits a LiveSyncActivity StateFlow alongside the existing
SyncState, carrying:
  - activeRelays: which relays are currently being queried
  - recentCompletions: last 100 completed relays with event counts
  - outboxTargets / inboxTargets / dmTargets: destination relay sets

downloadFromPool gains onRelayStart/onRelayComplete(relay, eventsFound)
callbacks; downloadFromRelay returns Int (total events across all pages).
Tracking uses ConcurrentHashMap.newKeySet + synchronized ArrayDeque for
thread safety across 50 concurrent workers.

Screen adds three new live cards:
  ActiveRelaysCard  — FlowRow of chips with a shared pulsing dot
                      animation (one InfiniteTransition for all chips)
  DestinationRelaysCard — Outbox / Inbox / DMs sections, color-coded
                          using primary / secondary / tertiary
  ActivityLogCard   — fixed-height (260dp) inner-scrollable list;
                      filled dot + count for active relays, muted for
                      empty/unreachable ones; K/M formatting for counts

String resources updated: event_sync_batch_of → event_sync_relays_progress,
paused_body copy updated to relay language; 7 new strings added.

https://claude.ai/code/session_01U8qF9mK4UBvXsXP1zNMXfX
2026-03-14 15:26:12 +00:00
Vitor Pamplona 03e1c32757 Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-03-14 11:20:33 -04:00
Claude 84035f887a feat: parse NIP-47 transaction metadata for sender/recipient display
Add NwcTransactionMetadata parser that extracts comment, payer_data,
recipient_data, and nostr zap data from the untyped metadata field.
The transaction list UI now shows the Nostr user profile picture and
name for zap senders/recipients, falls back to payer name/email or
lightning address, and displays comment when it differs from description.

https://claude.ai/code/session_01JFogiwyR4CPVP8cRznqahJ
2026-03-14 15:18:53 +00:00
Claude 666c795c93 fix: use correct cancellation checks in suspend functions
isActive is a CoroutineScope extension and has no CoroutineScope
receiver in plain suspend fun bodies (runSync, downloadFromRelay).

- runSync catch block: split into CancellationException (rethrow) +
  Exception, removing the invalid isActive guard entirely
- downloadFromRelay while loop: while(isActive) -> while(true) with
  coroutineContext.ensureActive() as the first statement, which works
  in any suspend fun and throws CancellationException when cancelled

The isActive import is kept for the supervisorScope lambda in
downloadFromPool, where a CoroutineScope receiver is in scope.

https://claude.ai/code/session_01U8qF9mK4UBvXsXP1zNMXfX
2026-03-14 15:03:45 +00:00
Claude 2fd623a97d fix: wallet screen showing "No wallet connected" on first open
The WalletViewModel.init() was called inside LaunchedEffect (async),
but hasWalletSetup() was checked synchronously during the first
composition frame—before init had run. Moved init to run synchronously
during composition and made hasWalletSetup a reactive StateFlow so the
UI updates when wallet state changes.

https://claude.ai/code/session_01JFogiwyR4CPVP8cRznqahJ
2026-03-14 14:30:54 +00:00
Vitor Pamplona 120981f8c4 spotless apply 2026-03-14 10:18:16 -04:00
Vitor Pamplona 493fe05ac4 Fixes missing parameter 2026-03-14 10:18:08 -04:00
Claude 5905926d4a feat: sliding window relay pool replaces fixed batch chunks
Instead of waiting for all 50 relays in a batch to finish before
starting the next 50, a Semaphore(MAX_CONCURRENT_RELAYS) keeps the
concurrency window full at all times: the moment one relay is fully
exhausted it releases the semaphore and the next relay starts.

Each relay is handled by downloadFromRelay(), which paginates
independently (until cursor) until the relay returns no events.
supervisorScope ensures a single relay failure does not cancel
the rest of the pool.

Dedup sets and event counter are now thread-safe (ConcurrentHashMap
key sets, AtomicLong) since workers fire concurrently.

SyncState.Running/Paused fields renamed:
  chunkIndex/totalChunks -> relaysCompleted/totalRelays
  nextChunkIndex         -> nextRelayIndex

https://claude.ai/code/session_01U8qF9mK4UBvXsXP1zNMXfX
2026-03-14 13:44:48 +00:00
Claude 1841e47c5c feat: add high-level Nip47Client and Nip47Server APIs for NIP-47
Simplifies the NWC developer experience by providing Nip47Client (for
wallet client apps) and Nip47Server (for wallet service backends) that
handle URI parsing, signer creation, event building, filter construction,
and response decryption. Updates README with quick-start examples.

https://claude.ai/code/session_01JFogiwyR4CPVP8cRznqahJ
2026-03-14 11:39:17 +00:00
David Kaspar 43914c0f09 Merge pull request #1841 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-03-14 11:19:39 +00:00