Commit Graph

8969 Commits

Author SHA1 Message Date
M 69e95159e9 fix: check Namecoin name expiry before resolving
Query current block height via blockchain.headers.subscribe and reject
names that have expired (>= 36000 blocks since last update). Populate
expiresIn field in NameShowResult for downstream use.

Unconfirmed transactions (height <= 0) are treated as active.
2026-03-03 06:56:59 +11: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
Vitor Pamplona cd18fdf79a Merge pull request #1728 from vitorpamplona/claude/add-relay-subscriptions-display-WHbsT
Add active subscriptions and outbox display to relay info screen
2026-03-01 12:48:25 -05:00
Vitor Pamplona 566bdb8a74 Merge pull request #1729 from vitorpamplona/claude/relay-search-suggestions-T1gpP
Add relay URL suggestions to relay input field
2026-03-01 12:47:04 -05:00
Vitor Pamplona 7212e9a879 Adds Relay Url to the Rich Text viewer 2026-03-01 12:45:47 -05:00
Vitor Pamplona ca6af92411 Merge branch 'main' of https://github.com/vitorpamplona/amethyst
* 'main' of https://github.com/vitorpamplona/amethyst:
  feat: add RelayUrlSegment for ws:// and wss:// relay URIs
  fix: treat multibyte characters as URL terminators in RichTextParser
  Simplify profile edit screen layout
  feat: show "Replying to" label in quoted notes
  fix: suppress parent thread in quoted notes
2026-03-01 11:48:46 -05:00
Vitor Pamplona 2ddcf41201 Merge pull request #1730 from vitorpamplona/claude/add-relay-uri-detection-vOdNR
Add RelayUrlSegment for WebSocket relay URL parsing
2026-03-01 11:48:09 -05:00
Claude b472be3a1a feat: add relay search suggestions to all Add a Relay fields
When the user types in any "Add a Relay" field in AllRelayListScreen,
the app now searches HintIndexer's relayDB for matching relay URLs
and displays them as clickable suggestions below the text field.

Clicking a suggestion fills the field with the relay URL, matching
the design pattern of ShowUserSuggestionList in ShortNotePostScreen.

New files:
- RelaySuggestionState: debounced Flow-based state filtering relayDB
- ShowRelaySuggestionList: Column of clickable RelayUrlLine rows

https://claude.ai/code/session_0115sYZGVQBZLX7s9oCDcKoi
2026-03-01 16:39:14 +00:00
Claude 304c348736 feat: add RelayUrlSegment for ws:// and wss:// relay URIs
Adds a new RelayUrlSegment type to RichTextParser that detects and
labels relay URIs (ws:// and wss:// schemes) as a distinct segment
type, separate from generic LinkSegments.

https://claude.ai/code/session_01U21sGdEEMLo4hY8dwxNzPr
2026-03-01 16:33:58 +00:00
Claude ce56f49369 feat: add active relay subscriptions and outbox display to RelayInformationScreen
Adds a new section before Errors and Notices that shows live relay state:
- REQ subscriptions: each subscription card shows its ID and a visual
  breakdown of all active filters using colored chips by kind category
  (notes/social/DM/economic), author counts, tag values, and time bounds
- COUNT subscriptions: same display for count queries
- Pending outbox events: chip list of event IDs awaiting delivery

Filter chips use Material3 color roles to indicate kind categories:
primaryContainer for text events (note/repost/reaction), secondaryContainer
for social/list events, tertiaryContainer for DMs/gift wraps, and
errorContainer for economic events (zap requests/receipts/NWC).

https://claude.ai/code/session_012zzv2j63ibraPNrQx8fGeu
2026-03-01 16:32:41 +00:00
Vitor Pamplona f5a7461fed Adds an emoji name to the preview to see if we can replicate the alignment when loading the username dynamically 2026-03-01 11:02:14 -05:00
Vitor Pamplona 678a97d01b Merge pull request #1727 from kojira/fix/multibyte-url-terminators
fix: treat multibyte characters as URL terminators in RichTextParser
2026-03-01 11:00:21 -05:00
kojira fd28d354e7 fix: treat multibyte characters as URL terminators in RichTextParser 2026-03-01 23:54:12 +09:00
Vitor Pamplona e7a9241833 Merge pull request #1724 from dmnyc/feat/quote-repost-reply-to-label
feat: show "Replying to" label in quoted notes
2026-02-28 20:39:37 -05:00
Vitor Pamplona e7c5727f75 Merge pull request #1725 from dmnyc/feat/profile-edit-cleanup
Simplify profile edit screen layout
2026-02-28 20:37:39 -05:00
The Daniel 2b36858c12 Simplify profile edit screen layout
Reduce visual clutter by reordering fields, improving labels, and
collapsing rarely-used social proof fields into an expandable section.

- Rename "Name" field to "Username" with @ prefix
- Reorder: Lightning Address, Nostr Address (NIP-05), Website, Pronouns
- Remove deprecated LN URL (lud06) field
- Move social proof fields (Twitter, GitHub, Mastodon) into a
  collapsible "Social proof" section (auto-expands if data exists)
- Clearer labels: "Lightning Address", "Nostr Address (NIP-05)"
2026-02-28 20:10:17 -05:00
The Daniel eb3b7077fd feat: show "Replying to" label in quoted notes
Follow-up to #1723. When a quoted note is itself a reply, display a
compact "Replying to [username]" label above the content instead of
showing nothing. Uses the event's p-tags to resolve reply targets
directly, matching the Damus-style display.
2026-02-28 18:53:32 -05:00
Vitor Pamplona 5fc7bab885 Merge pull request #1723 from dmnyc/fix/quote-repost-without-parent-display
fix: Suppress parent thread in quoted notes
2026-02-28 17:52:56 -05:00
The Daniel ace1401a27 fix: suppress parent thread in quoted notes
Adds unPackReply = false to both DisplayFullNote (nostr: bech links)
and DisplayNoteFromTag (tag references) so that quoted notes only
show the quoted post itself without its parent thread context.
2026-02-28 17:44:04 -05:00
Vitor Pamplona 3b0d7c7f09 Reverses claude new rendering scheme because we need to break into new paragraphs before coming to the rendering stage. 2026-02-28 16:34:53 -05:00
Vitor Pamplona 80921b8367 Merge branch 'main' of https://github.com/vitorpamplona/amethyst
* 'main' of https://github.com/vitorpamplona/amethyst:
  refactor: replace FlowRow-based RenderTextParagraph with single Text() composable
2026-02-28 15:41:59 -05:00
Vitor Pamplona de3f790e0d Merge pull request #1722 from vitorpamplona/claude/refactor-render-text-paragraph-yKHu8
Refactor RichTextViewer to use inline content instead of FlowRow
2026-02-28 15:38:47 -05:00
Claude 956ae21926 refactor: replace FlowRow-based RenderTextParagraph with single Text() composable
RenderTextParagraph previously assembled each word/segment as a separate
composable inside a FlowRow. It now outputs a single Text() composable
with a built AnnotatedString and an InlineTextContent map so images,
videos, and custom emojis are shown inline within the text flow:

- Images and videos (with preview): InlineTextContent with a fixed-size
  media placeholder (300×200 sp) containing ZoomableContentView
- Custom emojis: InlineTextContent with emoji-sized placeholder per
  image glyph via CustomEmoji.assembleAnnotatedList
- Hashtags: LinkAnnotation.Clickable span + optional InlineTextContent
  icon for decorated hashtags (#bitcoin, #nostr, etc.)
- Clickable URLs, emails (mailto:), phones (tel:): LinkAnnotation.Url
  spans with primary-colour styling
- Block-level widgets (URL previews, invoices, LNURL withdraw, Cashu,
  secret emojis, Nostr note/profile references): InlineTextContent with
  a 300×300 sp block placeholder
- User/event tag references without quote preview: InlineTextContent
  with a narrow text-height reference placeholder (150 sp × emojiSize)

The spaceWidth / measureSpaceWidth plumbing is removed from
RenderTextParagraph and its callers (RenderRegular callback no longer
receives Dp). measureSpaceWidth is kept because Highlight.kt still uses
it for its own FlowRow layout.

RenderWordWithPreview, RenderWordWithoutPreview, the private
ZoomableContentView string-URL wrapper, RenderCustomEmoji, and
NoProtocolUrlRenderer are all inlined into RenderTextParagraph and
removed. HashtagIcon.kt @Preview is updated to the new API.

https://claude.ai/code/session_01TtfLvFoR5Qpr2bHBWr5z3f
2026-02-28 20:29:14 +00:00
Vitor Pamplona 8f73a37a53 Fixes wrapping a non-observable value 2026-02-28 12:29:33 -05:00
Vitor Pamplona e58cbc9c8a Modifier.weight(1f) is stateless. It doesn't need to be keyed on noteEvent 2026-02-28 12:28:23 -05:00
Vitor Pamplona 21ff7c8502 avoids recreating modifiers 2026-02-28 12:21:46 -05:00
Vitor Pamplona a5edef2db8 No need to recreate the modifier on background changes 2026-02-28 12:20:47 -05:00
Vitor Pamplona 1bff239183 Fixes need for suspending function on uploading 2026-02-28 11:43:31 -05:00
Vitor Pamplona 30ffeaed34 Merge pull request #1720 from vitorpamplona/claude/add-profile-upload-button-RzGz4
feat: add profile picture upload button when user has no picture
2026-02-28 10:53:48 -05:00
Vitor Pamplona f08297c36c Merge pull request #1718 from vitorpamplona/claude/review-amethyst-issues-VFf0H
fix: render audio MIME types in imeta tags as playable media
2026-02-28 10:52:05 -05:00
Claude 11e86b5805 feat: add profile picture upload button when user has no picture
When a user visits their own profile and has no profile picture set,
show a semi-transparent upload button overlay directly on the profile
picture area. Tapping it opens the gallery picker, uploads the image
to the configured server (NIP-96 or Blossom), and immediately saves
the metadata — without requiring the user to navigate to the edit screen.

- Add uploadPictureAndSave() to NewUserMetadataViewModel: loads current
  metadata, uploads the image, then saves all metadata with the new picture
- Add ProfilePictureWithUploadOverlay composable that wraps ZoomableUserPicture
  and conditionally shows the upload overlay when isMe && no picture
- Add ProfilePictureUploadButton composable for the overlay UI with
  loading state support
- Use ProfilePictureWithUploadOverlay in ProfileHeader instead of
  ZoomableUserPicture directly

https://claude.ai/code/session_01XemJ8Hx9q4mMd1StZNY9CE
2026-02-28 02:06:43 +00:00
Claude 1efcaefe94 fix: render audio MIME types in imeta tags as playable media
Audio URLs with `audio/*` MIME types in NIP-92 imeta tags were silently
dropped (createMediaContent returned null) because only `image/` and
`video/` prefixes were checked. They now map to MediaUrlVideo, which
Media3/ExoPlayer already handles correctly for audio playback.

Also adds common audio extensions (ogg, wav, flac, aac, opus, m4a) to
the extension-based fallback so audio files without imeta tags are also
detected.

Fixes https://github.com/vitorpamplona/amethyst/issues/1701

https://claude.ai/code/session_01YSi64eXRokSy2GzYHoNFES
2026-02-28 00:34:32 +00:00
Vitor Pamplona 3762c8d6c3 Fixes the activity cast 2026-02-27 08:54:30 -05:00
Vitor Pamplona 9675f59040 Fixes lack of import and new kotlin rules 2026-02-27 08:53:49 -05:00
Vitor Pamplona 972c1ac71d Merge pull request #1717 from vitorpamplona/claude/ios-gzip-compression-iHfKC
Implement GZip compression/decompression for iOS using zlib
2026-02-27 07:55:37 -05:00
Claude b8cda402cb test(quartz/utils): add GZipTest to commonTest
Covers the full expect/actual contract across all platforms (Android,
JVM, iOS):

- round-trip for empty, single-char, simple, unicode, and JSON strings
- repetitive input compresses to a smaller size
- gzip magic number (0x1F 0x8B) present in compressed output
- compressed bytes differ from raw input bytes
- decompress of invalid data throws an exception
- special/control characters survive a round-trip

https://claude.ai/code/session_0125CGfu6aMAnSv6ZzAxFHvV
2026-02-27 01:57:10 +00:00
Claude 5cd05ab008 feat(quartz/ios): implement GZip compress/decompress for iOS
Uses platform.zlib (built-in on all Apple targets) via Kotlin/Native
cinterop to provide the actual GZip implementation:

- compress: deflateInit2 with windowBits=31 (MAX_WBITS+16) for gzip
  format; deflateBound gives a tight upper-bound so a single Z_FINISH
  call is always enough – no output loop required.
- decompress: inflateInit2 with windowBits=47 (MAX_WBITS+32) for
  automatic gzip/zlib format detection; output is collected in
  fixed-size chunks to handle arbitrary decompressed sizes.

https://claude.ai/code/session_0125CGfu6aMAnSv6ZzAxFHvV
2026-02-27 01:18:47 +00:00
Vitor Pamplona c2868d4100 Merge branch 'main' of https://github.com/vitorpamplona/amethyst
* 'main' of https://github.com/vitorpamplona/amethyst:
  feat: consolidate drawer settings into a single Settings hub screen
  New Crowdin translations by GitHub Action
2026-02-26 20:11:11 -05:00
Vitor Pamplona 027d932b63 Merge pull request #1716 from vitorpamplona/claude/consolidate-drawer-settings-CBYo3
Consolidate settings screens into unified AllSettingsScreen
2026-02-26 20:08:25 -05:00
Claude e5eb21168b feat: consolidate drawer settings into a single Settings hub screen
Replace six individual drawer items (Relays, Media Servers, Security
Filters, Privacy Options, App Preferences, User Preferences) with a
single "Settings" entry that navigates to a new AllSettingsScreen hub.
The hub lists all six options as clickable rows, each navigating to
their existing screens unchanged.

https://claude.ai/code/session_017Z9x4PNJuMtMQgfYSxTVSU
2026-02-27 01:06:02 +00:00
Vitor Pamplona fe8dd3fb51 Fixing incorrect cast 2026-02-26 20:05:30 -05:00
Vitor Pamplona 18270f8020 Adds a reqUntilEoseAsFlow extension to the Nostr Client 2026-02-26 19:56:39 -05:00
Vitor Pamplona 1b4044814f Merge pull request #1715 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-02-26 19:49:09 -05:00
Vitor Pamplona 0e659b5b07 Fixes instruction to use event database 2026-02-26 19:42:45 -05:00
Vitor Pamplona abf977b791 Removes common tags 2026-02-26 19:39:53 -05:00
Crowdin Bot 6197cc6a7a New Crowdin translations by GitHub Action 2026-02-27 00:39:49 +00:00
Vitor Pamplona 23c3edbec8 docs: add quartz-integration skill for using Quartz in external KMP projects
Adds a comprehensive Claude skill covering Gradle setup, key management,
event creation/signing, relay client, subscriptions, NIP builders, and
platform-specific notes. Also updates the legacy quartz-kmp.md to redirect
to the new skill.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 19:37:44 -05:00
Vitor Pamplona 5b156c4530 Basic (ugly) rendering of Zap events when quoted inside of posts. 2026-02-26 19:26:33 -05:00