Commit Graph

1255 Commits

Author SHA1 Message Date
Vitor Pamplona 6f57652455 Merge pull request #1827 from vitorpamplona/claude/implement-nip-38-q8DOF
Enhance user status display with emoji support and metadata tags
2026-03-13 13:32:41 -04:00
Vitor Pamplona 3e0b8a5f8f Fixes gradle build on MacOS and adds a Clibsodium.def file 2026-03-13 08:40:51 -04:00
Claude 82e500eee1 feat: complete NIP-38 implementation with p tag, emoji, and expiration support
- Add optional r/p/e/a/emoji tags to StatusEvent.create() for full spec compliance
- Add GENERAL and MUSIC type constants to StatusEvent
- Filter expired statuses in UserStatusCache.addStatus() and add removeExpired()
- Add p tag (profile reference) display in DisplayStatusInner
- Add NIP-30 custom emoji rendering in status display via CreateTextWithEmoji
- Allow status type parameter in UserStatusAction.create()

https://claude.ai/code/session_0117asp4mDiR65dxbAGKi2hg
2026-03-13 03:06:22 +00:00
KotlinGeekDev 5cdf8bdd86 Merge branch 'vitorpamplona:main' into kmp-completeness 2026-03-13 01:12:49 +01:00
Vitor Pamplona fa67030b47 Adds support for BUD-10 Blossom URIs 2026-03-12 18:57:46 -04:00
Vitor Pamplona d4dd5a65e6 anySync was returning either on true or false. it was not doing what it was supposed to do which is returning after the first true. 2026-03-12 18:56:17 -04:00
KotlinGeekDev 3838b6b815 Some fixes. 2026-03-12 22:16:34 +01:00
KotlinGeekDev 42f48e11fc Make CI happy(attempt 2). 2026-03-12 21:49:08 +01:00
KotlinGeekDev a463a9802f Slightly modify defFile generation, to stop CI cries. 2026-03-12 21:36:25 +01:00
KotlinGeekDev 750bedbabd Foundations(iOS Sourceset): Reduce the header files only to those needed, plus utilities. 2026-03-12 21:06:02 +01:00
KotlinGeekDev 0b928d29a6 Make the libsodium cinterop file generation more reliable. Add in(and comment out) some test code for extracting the libsodium headers from zip file. 2026-03-12 20:28:02 +01:00
KotlinGeekDev 527130a53c Merge remote-tracking branch 'origin/kmp-completeness' into kmp-completeness 2026-03-12 20:22:55 +01:00
KotlinGeekDev d957efb1b8 Foundations(iOS Sourceset): Streamline libsodium bindings configuration. 2026-03-12 16:55:19 +01:00
Vitor Pamplona ad17924622 Making sure UrlDetector returns a schema even if the parser points to some user:password scheme. 2026-03-12 10:48:11 -04:00
KotlinGeekDev 2b61f4a3d6 Function rename for digest provider. 2026-03-12 15:33:07 +01:00
KotlinGeekDev 759b0c8b96 Foundations(iOS Sourceset): Use alternative implementation for MacInstance, due to complications with mac length under previous implementation, which makes NIP49 tests(with all other relevant tests) pass. Some spotless fixes. 2026-03-12 15:31:33 +01:00
KotlinGeekDev 8f02ea0cf6 Foundations(iOS Sourceset): Provide implementation for LibSodiumInstance.ios.kt, using the native library(shipped in project). Generate cinterop definition file with custom Gradle task. Defines bindings for use in actual code(may be streamlined later). Adds NIP44 tests and makes sure they pass. 2026-03-12 15:13:32 +01:00
Vitor Pamplona a94d5bfd07 Fixes BUD 10 tests 2026-03-11 15:29:16 -04:00
Vitor Pamplona 548ce0a69d spotless apply 2026-03-11 15:24:02 -04:00
Claude ac69a0fa74 feat(nipB7Blossom): add BUD-10 Blossom URI parser
Implements a pure-Kotlin (commonMain) parser for the BUD-10 blossom: URI
scheme, which allows sharing blob references with discovery hints.

Format: blossom:<sha256>.<ext>[?xs=<server>&as=<pubkey>&sz=<bytes>]

- BlossomUri data class holds sha256, extension, servers (xs), authors (as), size (sz)
- BlossomUri.parse() returns null for non-blossom URIs or invalid SHA-256
- Supports repeated xs/as params (multiple servers and authors)
- Percent-encodes server URLs on serialisation; decodes on parse
- BlossomUri.toUriString() round-trips back to a canonical URI
- Includes commonTest coverage for all parsing cases

https://claude.ai/code/session_01T4jyLbkNWd3f7i6MwsBcD4
2026-03-11 19:16:45 +00:00
Vitor Pamplona 0c040d8816 addresses long domain names for blossom and nostr profiles 2026-03-11 14:59:52 -04:00
Vitor Pamplona 1c044c9072 If warning is blank, revert to defaults 2026-03-11 14:12:02 -04:00
Vitor Pamplona ffe5e14b2b Display content warning reason 2026-03-11 14:10:55 -04:00
Vitor Pamplona 9bb87b38f5 Merge pull request #1808 from vitorpamplona/claude/add-content-warning-description-5BF4B
Add optional description field for sensitive content warnings
2026-03-11 13:43:47 -04:00
Claude 2b0518a675 feat: allow users to add a description to the sensitive content warning
- Add contentWarningReason() helper to TagArrayExt and EventExt for reading the reason from existing events
- Add contentWarningDescription state to ShortNotePostViewModel, wired into event building and draft load/save/reset
- Update ContentSensitivityExplainer to accept description state and render an OutlinedTextField for user input
- Pass description state from ShortNotePostScreen to ContentSensitivityExplainer
- Add "Reason (optional)" placeholder string resource

https://claude.ai/code/session_01P2nkYdNiWXiAcfMPTRTVEW
2026-03-11 16:51:37 +00:00
Vitor Pamplona 3bd2f4251b Increasing sha256 pool size 2026-03-11 12:33:11 -04:00
Vitor Pamplona 3fdde60a37 Merge branch 'main' of https://github.com/vitorpamplona/amethyst
* 'main' of https://github.com/vitorpamplona/amethyst:
  New Crowdin translations by GitHub Action
  fix: resolve conflicts with upstream PR #1789 merge
  fix(desktop): remove noisy debug logs and silence SLF4J warnings
  feat(desktop): add bunker heartbeat indicator to sidebar navigation
  fix(desktop): verify user pubkey via get_public_key after nostrconnect login
  fix(desktop): address code review findings for NIP-46 bunker login
  feat(desktop): add nostrconnect:// login flow for QR-based signer pairing
  revert: remove QR code scanning from login
  feat(desktop): webcam QR scanning via ffmpeg for bunker login
  feat(desktop): add webcam QR code scanning for bunker login
  feat(desktop): add QR code scanning for bunker login
  fix(desktop): clear stored credentials on logout
  feat(desktop): update login hints to mention bunker:// option
  fix(desktop): simplify settings logout to just a button
  feat(desktop): add logout option to menu bar and settings
  test: add NIP-46 test suite for desktop, quartz, and fix pre-existing chess test errors
  feat(desktop): add NIP-46 remote signer (bunker://) login
2026-03-11 08:42:44 -04:00
Vitor Pamplona 71574a5ce0 tracks and displays connection tentatives on relay settings 2026-03-11 08:42:32 -04:00
Vitor Pamplona ca9074e6f5 better relay parsing messaging 2026-03-11 08:17:14 -04:00
nrobi144 edf764709d fix: resolve conflicts with upstream PR #1789 merge
- Add missing commons domain files (BunkerLoginUseCase, NostrConnectLoginUseCase)
- Restore CoroutineScope in NostrSignerRemote for suspend decrypt call
- Update isolation test: upstream removed `since` filter (PR #1789)
- Add new INostrClient interface methods to TrackingNostrClient mock

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 10:35:56 +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
nrobi144 3a1e38a2f2 fix(desktop): address code review findings for NIP-46 bunker login
- Add bounds check in fromBunkerUri for missing query params (P2-1)
- Preserve bunker keys on transient force-logout (P2-3)
- Replace debug printlns with DebugConfig.log() (P2-4)
- Replace unused Unstable with Disconnected state (P2-5)
- Move validateBunkerUri to account package (P3-9)
- Fix Compose state update from IO thread (P3-11)
- Add disconnectNip46Client() to onDispose cleanup (P3-12)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 10:16:10 +02:00
nrobi144 12c91aae3d feat(desktop): add nostrconnect:// login flow for QR-based signer pairing
Adds client-initiated NIP-46 (nostrconnect://) flow so users can pair
with a remote signer (e.g. Amber) by scanning a QR code instead of
manually copying a bunker:// URI.

Changes:
- Fix RemoteSignerManager to decrypt NIP-44 content before parsing
- Add CoroutineScope to NostrSignerRemote for async event callbacks
- Add loginWithNostrConnect() to AccountManager with 120s timeout
- Add QrCodeCanvas composable using ZXing for QR generation
- Add "Connect" tab to LoginCard showing QR + copyable URI + waiting state
- Wire nostrconnect flow through LoginScreen

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 10:16:10 +02:00
nrobi144 1821b9ff71 test: add NIP-46 test suite for desktop, quartz, and fix pre-existing chess test errors
Add comprehensive test coverage for NIP-46 bunker login across quartz and desktopApp:

Quartz (4 files, 48 tests):
- ResponseParserTest: all 7 response parsers (success/error/unexpected)
- FromBunkerUriTest: URI parsing, validation, edge cases
- ConvertExceptionsTest: SignerResult→Exception mapping
- NostrConnectEventTest: canDecrypt, talkingWith, verifiedRecipientPubKey

Desktop (6 files, 45 tests):
- BunkerUriUtilsTest: validateBunkerUri + stripBunkerSecret
- AccountManagerKeyLoginTest: nsec/npub/invalid login, save, generate
- AccountManagerLogoutTest: logout, forceLogout, state transitions
- AccountManagerLoadAccountTest: internal/bunker/missing-key scenarios
- AccountManagerBunkerLoginTest: hasBunkerAccount, setConnectingRelays
- AccountManagerHeartbeatTest: start/stop, no-crash with internal signer

Production changes:
- AccountManager: constructor private→internal, add homeDir param for test injection, extract stripBunkerSecret to internal top-level, constants internal
- desktopApp/build.gradle.kts: add mockk test dependency

Fix pre-existing chess test compilation errors:
- ChessStateReconstructorTest: add missing jester subpackage imports
- ChessGameEventTest: altText()→alt() + add nip31Alts import

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 10:16:09 +02:00
Vitor Pamplona b4184d2235 Moves the upload file button closer to the image upload 2026-03-10 15:54:03 -04:00
Vitor Pamplona b2a8a422b2 - Breaks the new Import Follow interface into two screens
- Improves user suggestion search by evaluating specific nip-05s and npubs
2026-03-10 15:48:04 -04:00
Vitor Pamplona 558e8a2dd2 Adds constructor to DualCase class 2026-03-10 14:37:55 -04:00
Vitor Pamplona 1de38ad9ec Creates an interface for Nip05Client 2026-03-10 14:37:40 -04:00
Vitor Pamplona 835001bd6c Making nip05 client stable 2026-03-10 14:22:06 -04:00
Vitor Pamplona ab9ecdc939 Adds methods to follow a bunch of users at the same time 2026-03-10 11:12:23 -04:00
Vitor Pamplona ff4356ce31 Moves away from calling relay feeds "favorites" 2026-03-10 09:26:09 -04:00
Vitor Pamplona 50a578cfdc Fixes preview of relay information screen 2026-03-10 08:50:51 -04:00
Vitor Pamplona 97a3fcc9df Merge pull request #1785 from mstrofnone/feat/import-follow-list-namecoin
feat: import follow list with Namecoin resolution during signup
2026-03-10 08:14:24 -04:00
Vitor Pamplona 88e6825028 Merge pull request #1789 from nrobi144/fix/nip46-quartz-bugs
fix(quartz): fix NIP-44 key mutation and NIP-46 connect response handling
2026-03-10 08:08:08 -04:00
nrobi144 e56b0d2b83 fix(quartz): connect() returns Unit, caller calls getPublicKey separately
Per Amber maintainer: connect never returns a pubkey — response is
"ack" or the secret string. Rewrote ConnectResponse.parse() to check
result/error fields directly on base BunkerResponse (matching Jackson
deserialization). connect() is now a pure protocol handshake; callers
call getPublicKey() separately as a domain concern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 07:24:57 +02:00
Vitor Pamplona 2387a1bb91 Improves the order of search results 2026-03-09 11:25:00 -04:00
nrobi144 39393d328b fix(quartz): fix NIP-44 key mutation and NIP-46 connect response handling
Two bugs in quartz's NIP-46 remote signer:

1. FixedKey.getEncoded() returned the raw byte array reference. javax.crypto.Mac
   zeroes the key via destroy() after HMAC computation, corrupting the NIP-44
   saltPrefix ("nip44-v2") after the first computeConversationKey call. All
   subsequent NIP-44 decryptions with different key pairs fail with Invalid Mac.
   Fix: return key.copyOf() instead of key.

2. NostrSignerRemote.connect() only handled pubkey responses. Amber (and other
   signers) may respond with "ack" or "already connected" error. Added
   ConnectResponse parser that maps these to success and falls back to
   getPublicKey() to retrieve the actual pubkey.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 07:49:58 +02:00
Vitor Pamplona 991f1dfca5 spotless apply 2026-03-08 09:58:41 -04:00
M 8456b38dea feat: import follow list with Namecoin resolution during signup
Add a new signup step that lets users bootstrap their feed by importing
another profile's follow list. Supports all identifier types:

  - npub1... (NIP-19 bech32)
  - 64-char hex pubkey
  - alice@example.com (NIP-05 HTTP)
  - alice@example.bit / d/name / id/name (Namecoin blockchain)

Flow: Enter identifier → Resolve → Fetch kind 3 → Preview with
select/deselect → Apply follows → Done. Users can search multiple
profiles before continuing.

Changes to existing files:
  - NamecoinNameResolver: add resolveDetailed() + NamecoinResolveOutcome
  - NamecoinNameService: add resolveDetailed(), resolvePubkey()
  - AccountSessionManager: add isNewAccount flag, finishNewAccountSetup()
  - AccountScreen: route new accounts to ImportFollowListSection

New files:
  - FollowListImporter: identifier resolution + kind 3 fetch + parsing
  - ImportFollowListViewModel: state machine for the import flow
  - ImportFollowListScreen: UI with preview, select/deselect, search again
  - FollowListImporterTest: 14 unit tests
2026-03-08 15:38:54 +11:00
Claude 812f465608 refactor: improve URLDetector readability
- UrlDetector: simplify space handler in readDefault() — both branches
  of if/else were calling the same readEnd(InvalidUrl), making the
  conditional dead code; now we always call readEnd after attempting
  to read the domain
- UrlDetector: remove redundant inner buffer.isNotEmpty() check in
  readEnd(), already guarded by the outer condition
- UrlDetector: rename processColon() parameter from length to
  startLength to eliminate the var length = length self-shadowing
- UrlDetector: replace ArrayList<Url>() with mutableListOf<Url>()
  for idiomatic Kotlin
- DomainNameReader: replace lastSection.deleteRange(0, lastSection.length)
  with lastSection.clear() which expresses the intent directly
- DomainNameReader: move isDotPercent() and isXn() extension functions
  from inside the class body to private file-level functions — extension
  functions defined on a class instance are unusual and confusing

https://claude.ai/code/session_01Pci2AC45yQxQw6F6g7jWdd
2026-03-08 00:54:38 +00:00