Commit Graph
14265 Commits
Author SHA1 Message Date
nrobi144andClaude Opus 4.6 b431c1efab feat(desktop): visual personality overhaul — unified theme, sidebar, cards
Phase 1: Replace per-OS color schemes with unified Amethyst brand
- Cyan/blue accent (#0096FF light, #4DB8FF dark) replacing OS-adaptive colors
- Amethyst purple as tertiary heritage color
- Unified shapes (8/12/16/24dp) replacing per-OS variants
- Standardized typography weights (Light for display, SemiBold for headlines)
- Letter spacing unified to -0.3sp

Phase 2: Spacing system
- AmethystSpacing CompositionLocal with design tokens
- LocalIsDarkTheme for M3-compatible dark mode detection

Phase 3: Sidebar redesign
- 240dp wide sidebar with icon + text labels (was 56dp icon-only)
- Animated collapse/expand with smooth width transition
- Avatar + username at top with account switcher
- Custom feeds section from FeedDefinitionRepository
- Active item cyan pill indicator with hover effects
- Collapse state persisted in Preferences
- Debounced fitColumnsToWidth to prevent animation thrash

Phase 4: Card refinement
- OutlinedCard with 1dp border replacing 1dp shadow elevation
- 16dp internal padding (was 12dp)
- Converted NoteCard, ReadsScreen, DraftsScreen, MyHighlightsScreen, UserProfileScreen

Phase 5: Column header restyling
- 48dp height (was 40dp) with surfaceContainer background
- 12dp horizontal padding (was 8dp)

Phase 6: Polish
- HoverModifiers.kt — shared hover highlight using onPointerEvent + drawBehind
- ShimmerPlaceholder.kt — skeleton loading animation in commons/commonMain

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-29 07:02:49 +03:00
Vitor PamplonaandGitHub 16afed0f3f Merge pull request #3097 from vitorpamplona/claude/intelligent-heisenberg-MkXpX
Fix scroll position restoration in feed lists on return
2026-05-28 21:28:52 -04:00
Claude 02fd0780d5 fix(feeds): don't snap to top when returning from a post screen
StickToTopOnPrepend hardcoded `wasAtTop = true` on remember, so when the
user scrolled down, navigated to a post and came back,
rememberForeverLazyListState restored a non-zero offset but the helper
still believed the user was at the top. As soon as the head-of-feed key
emitted (first observation after recomposition), the LaunchedEffect
scrolled them back to 0.

Seed wasAtTop from the actual restored scroll position via an
initialAtTop lambda. The sampler's gesture-guarded false→true protection
against keyed-item shifts is unchanged.

Regression from #3088.
2026-05-28 23:01:49 +00:00
Vitor PamplonaandGitHub ba049da389 Merge pull request #3096 from vitorpamplona/claude/busy-sagan-QqTna
Switch Java distribution from Zulu to Temurin
2026-05-28 18:58:06 -04:00
Claude cbd8cd1b87 ci: switch setup-java distribution from zulu to temurin
Zulu's CDN (cdn.azul.com) has been returning HTTP 520 for several
hours, breaking JDK 21 setup across multiple PRs (#3075, #3095) on
every Linux runner. actions/setup-java's internal retry budget isn't
enough to ride through it.

Temurin (Adoptium) publishes its JDKs as GitHub Releases assets, so
the download path uses GitHub's own CDN — completely independent
infrastructure. Java 21 is the same upstream OpenJDK build either way,
so Gradle, Compose Multiplatform, and jpackage behave identically.

Applied to all setup-java steps in build.yml, smoke-test-desktop.yml,
and create-release.yml.
2026-05-28 22:46:29 +00:00
Vitor PamplonaandGitHub 18495449f8 Merge pull request #3094 from vitorpamplona/claude/kind-feynman-tZUzp
docs: consolidate CLAUDE.md guidance and inject skills dynamically
2026-05-28 18:26:12 -04:00
Claude 599fa2aa53 docs: restore canonical NIPs link in CLAUDE.md
Re-add the nostr-protocol/nips reference (dropped in the cleanup) as a
one-liner in the overview, tied to the /nip command so it points at the
exact spec file rather than the bare index.
2026-05-28 22:24:33 +00:00
Vitor PamplonaandGitHub 0eb2188ebd Merge pull request #3093 from vitorpamplona/claude/adoring-turing-THM7p
Add podcast support (NIP-F4) with favorites, metadata, and episodes
2026-05-28 18:24:11 -04:00
Claude ab0719fa68 fix(podcasts): wire podcast kinds into every consumer; close audit findings
Addresses 10 audit findings from the post-build review:

CRITICAL — non-functional without this:
- LocalCache.justConsume had no branches for kind 54 / 10054 / 10064 / 10154,
  so every podcast event fell through to "Event Not Supported" and was
  silently dropped. Added the four explicit branches (regular event for
  PodcastEpisode; replaceable for the other three).

HIGH — silent invisibility / broken tap-through:
- Home, profile (newthreads + mutual), hashtag, geohash, follow-pack, and
  notification feed filters didn't recognize PodcastEpisodeEvent /
  PodcastMetadataEvent. Episodes were invisible everywhere outside the
  dedicated tab; reactions/zaps on episodes were dropped from the
  notifications feed.
- ThreadFeedView's renderer dispatch had no podcast branch, so tapping a
  feed card opened a plain text-note view. Added explicit cases that call
  the new RenderPodcastEpisode / RenderPodcastMetadata composables.
- The hashtag / geohash / relay / search REQ kind lists didn't include
  podcast kinds, so discovery surfaces returned nothing for them.
- RelayInformationScreen kind→label map gained podcast entries +
  4 new string resources (Podcast Episode, Podcast Show, Authored
  Podcasts, Favorite Podcasts).
- HomeNewThreadFeedFilter.ADDRESSABLE_KINDS gained PodcastMetadataEvent so
  shows surface alongside music/wiki/long-form on the home feed.

HIGH — privacy leak in Quartz:
- FavoritePodcastsListEvent.add(isPrivate=true) was passing
  earlierVersion.tags through untouched, so toggling a previously-public
  favorite to private left the public p-tag intact. Made both branches
  symmetric: each removes the entry from the other half before adding to
  its own. Two regression tests cover the round-trip.

MEDIUM — data hygiene:
- AuthorTag.parse used to accept ANY non-empty slot-2 string as a role
  (rendering a stray relay-hint URL as "Role: wss://relay…"). Now
  validates against the spec-defined {host, cohost, editor} allowlist;
  unknown values resolve to role=null, preserving the pubkey association.

PERF:
- PodcastEpisode renderer was allocating a fresh 96-element WaveformData
  and rebuilding the cover Modifier chain per visible card. Hoisted both
  to top-level constants (FLAT_WAVEFORM, COVER_IMAGE_MODIFIER,
  PLAYER_BORDER_MODIFIER) so the whole feed shares one instance.

CODE QUALITY:
- Extracted PodcastCoverCard as a shared composable used by both renderers
  (was duplicated byte-identical across PodcastEpisode + PodcastMetadata).
- Extracted PodcastFeedLoaded so the Episodes screen and Shows screen
  share one feed body (was duplicated byte-identical).
- Dropped the misleading `group = listOf(singleAssembler)` wrapper in the
  two FilterAssembler files.
- Replaced `mapNotNull { … }.flatten()` with `flatMap { … }` in the
  Communities sub-assembly (the lambda never returns null).

DOCUMENTED:
- PODCAST_KINDS "Following" resolution still goes through kind:3 follows,
  but per NIP-F4 podcasts use their own keypairs tracked via kind:10054.
  Added an inline comment naming the deferred work — proper fix needs
  Account-level 10054 integration which is a separate scope.
2026-05-28 22:14:49 +00:00
Claude aea885bab0 docs: add Verify-Don't-Guess rule and trim CLAUDE.md
- Add a standing instruction to test hypotheses before diagnosing
  (state guesses as guesses, reproduce-first, predict-then-run).
- Remove content duplicated by the harness-injected skill list (skills
  tables, Commands section) and generic expect/actual examples.
- Condense the Feature Workflow (removed the duplicated share/keep-native
  tables and the hardcoded grep block) and the skill-handshake example.
- Fix stale facts: drop pinned tool versions (now point to
  libs.versions.toml) and correct the nestsClient tree comment to match
  the overview (production runs on moq-lite).
2026-05-28 22:12:53 +00:00
Vitor PamplonaandGitHub 1fdde747de Merge pull request #3092 from vitorpamplona/claude/adoring-galileo-ws6FG
Add NIP-78 AppDataEvent (kind 78) and refactor AppSpecificDataEvent
2026-05-28 18:08:33 -04:00
Vitor PamplonaandGitHub cb8efd070e Merge pull request #3091 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-05-28 17:45:59 -04:00
Claude 6c3ceba234 docs: add Verify, Don't Guess standing instruction to CLAUDE.md 2026-05-28 21:41:32 +00:00
Crowdin Bot 47af414e47 New Crowdin translations by GitHub Action 2026-05-28 21:38:48 +00:00
Vitor PamplonaandGitHub a0af93bbbe Merge pull request #3090 from vitorpamplona/claude/exciting-meitner-KeUBf
Add NIP-71 audio-track support with language and bitrate tags
2026-05-28 17:36:56 -04:00
Claude 40ed26ea85 refactor(quartz): NIP-78 events use the build-template pattern
Convert both kind 30078 and the new kind 78 from the legacy
`suspend create(... signer)` shape to the now-standard
`build(...) -> EventTemplate` shape used across recent quartz events
(NIP-34, NIP-66, etc):

- Use `eventTemplate<T>(KIND, content, createdAt) { ... }` and lean
  on the shared `alt()` and `dTag()` TagArrayBuilder extensions
  instead of hand-rolling the `d`/`alt` injection.
- Callers now do `signer.sign(AppSpecificDataEvent.build(...))`.

For kind 78 the `d` tag is optional (it's a grouping key, not an
addressing key), so we keep it nullable and assemble it via
`DTag.assemble` — the typed `dTag()` extension is constrained to
addressable events, which is correct.

Update the lone caller (`AppSpecificState.saveNewAppSpecificData`).
2026-05-28 21:16:03 +00:00
Claude 7efe6fdf2a feat(nip71): support audio-track imeta variants per nostr-protocol/nips#2255
Adds the audio-track imeta properties from NIP-71 PR #2255 so video
events can advertise external audio tracks (multi-language, alternate
bitrates) alongside video variants:

- New imeta properties: bitrate, duration (float seconds), waveform,
  and l <code> <standard> [ov] for language with an original-version flag
- Extends VideoMeta with bitrate, duration, waveform, language fields
  plus isAudio/isVideo helpers
- VideoEvent exposes audioTracks()/videoTracks() so players can prefer
  separate audio tracks over in-video audio while switching resolution
- Round-trip test against the PR's spec example
2026-05-28 21:15:08 +00:00
Claude 2e7583adfd feat(quartz): NIP-78 — add kind 78 normal app data event
NIP-78 was updated (nostr-protocol/nips#2292) to define a second
event kind alongside the existing addressable kind 30078:

- Kind  78: normal event, for apps that need to store and query
  multiple events of the same type. Recommended to use unique tags
  (including `d` tags) for grouping related events; the `d` tag here
  is a grouping key only, not an addressing key.

Add `AppDataEvent` (kind 78) extending `Event`, mirroring the
ergonomics of `AppSpecificDataEvent` (kind 30078): optional `d` tag
hoisted into `tags`, NIP-31 `alt` tag injected when absent, and a
`signer.sign(...)` factory. Register it in `EventFactory` so
incoming kind-78 events deserialize into the typed class.

The existing kind-30078 implementation remains compliant with the
updated spec.
2026-05-28 21:05:58 +00:00
Claude df0bb2641a chore(commons): use Headphones + Podcasts glyphs for the podcast tabs
Swaps PlayCircle / AudioFile (generic) for the canonical Material Symbols
podcast iconography — `headphones` (U+F01F) on the Episodes feed and
`podcasts` (U+F048, the mic + signal-waves glyph) on the Shows feed.
Both codepoints added to MaterialSymbols.kt and the subset font
regenerated via tools/material-symbols-subset/subset.sh.
2026-05-28 20:56:00 +00:00
Claude 09a46b7fac feat(amethyst): add Episodes & Podcasts screens for NIP-F4
Mirrors the existing Music/Playlists screen pair end-to-end so podcast
events flow through the standard feed pipeline:

- AccountSettings/Account/LocalPreferences gain the two new follow-list
  selectors (defaultPodcastEpisodesFollowList, defaultPodcastsFollowList)
  plus their derived liveX/liveXPerRelay flows.
- AccountFeedContentStates wires podcastEpisodesFeed (kind 54 from
  LocalCache.notes) and podcastsFeed (kind 10154 from addressables) into
  updateFeedsWith/deleteNotes.
- RelaySubscriptionsCoordinator + BottomBarFeedPreloaders register the
  two new filter assemblers, each with its own EOSE/since cursor.
- Routes/AppNavigation/NavBarItem add the two destinations; both go in
  DrawerFeedsItems with PlayCircle and AudioFile icons (existing subset
  glyphs, no font regeneration required).
- New NoteCompose dispatch cases call RenderPodcastEpisode (cover +
  audio player via the shared GetMediaItem/GetVideoController/
  RenderVoicePlayer chain + description + markdown content) and
  RenderPodcastMetadata (cover + title + description + website chips).

Skipped (separate PRs): authoring flows (NewPodcast/NewEpisode) and the
kind:10054 favorites toggle sheet — podcast publishers typically don't
hold their podcast keypair in Amethyst, and favorites need a
PrivateTagArrayEventCache hookup in Account that's larger than the read
path alone.
2026-05-28 20:36:42 +00:00
Claude b47cdf5b96 feat(quartz): add NIP-F4 podcast event support
Implements the four event kinds defined by NIP-F4 so Quartz can parse and
build native Nostr podcasts: kind:10154 show metadata, kind:10064 author
counter-claim, kind:54 episode, and kind:10054 favorite-podcasts list. All
four are registered in EventFactory so the existing JSON deserialization
pipeline returns typed instances. Tag classes mirror the per-event package
layout used by the experimental music module.
2026-05-28 20:10:39 +00:00
David KasparandGitHub d2e5364074 Merge pull request #3089 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-05-28 18:23:40 +02:00
Crowdin Bot 0ff512c09e New Crowdin translations by GitHub Action 2026-05-28 15:57:45 +00:00
Vitor PamplonaandGitHub e9a1215063 Merge pull request #3088 from vitorpamplona/claude/intelligent-fermat-8y2or
Auto-stick feeds to top on prepend with StickToTopOnPrepend
2026-05-28 11:55:51 -04:00
Vitor PamplonaandGitHub 938e9401b2 Merge pull request #3087 from vitorpamplona/claude/sweet-gates-pLvsz
Fix StrictMode violation in ML Kit translation initialization
2026-05-28 11:54:15 -04:00
Claude b1da3c2161 fix: move ML Kit translation off the UI dispatcher
LaunchedEffect runs on Dispatchers.Main by default. The first call to
LanguageTranslatorService triggers its class init, which loads a Properties
file from inside the play-services AAR via ZipFile/RandomAccessFile and
trips StrictMode's DiskReadViolation on the UI thread.

Wrap the translateAndCache call in withContext(Dispatchers.IO) so MLKit's
first-touch init happens off the UI dispatcher.
2026-05-28 15:52:21 +00:00
David KasparandGitHub b9bc21d78e Merge pull request #3084 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-05-28 14:29:20 +02:00
Crowdin Bot 6e9a905e64 New Crowdin translations by GitHub Action 2026-05-28 12:28:31 +00:00
davotoulaandClaude Opus 4.7 d27d215d97 i18n: add cs/de/sv plurals for music track counts; teach skill to diff <plurals>
The find-missing-translations skill only diffed <string name=, so missing
<plurals> resources slipped through. Updated Steps 2, 2.5, 3 to diff
<plurals> independently and added 3 missing music playlist plurals
across cs/de/sv with correct CLDR category coverage (Czech: one/few/many/other).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 14:26:55 +02:00
David KasparandGitHub a70e0e6cf9 Merge pull request #3083 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-05-28 14:18:12 +02:00
Crowdin Bot a8d8d704c4 New Crowdin translations by GitHub Action 2026-05-28 12:16:37 +00:00
davotoulaandClaude Opus 4.7 b98c18351a i18n: add cs/de/sv translations for music tracks/playlists, video error fallback, wallet reorder
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 14:14:46 +02:00
David KasparandGitHub 03fef56d08 Merge pull request #3082 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-05-28 14:09:54 +02:00
Crowdin Bot e1b5c7e24b New Crowdin translations by GitHub Action 2026-05-28 12:08:43 +00:00
David KasparandGitHub e376f71d0b Merge pull request #3081 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-05-28 14:06:28 +02:00
Crowdin Bot a5aefc3233 New Crowdin translations by GitHub Action 2026-05-28 12:05:11 +00:00
davotoulaandClaude Opus 4.7 4596102a66 i18n: add Czech, German, Swedish translations for NIP-82 sections, music upload banner, send
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 14:01:26 +02:00
David KasparandGitHub 196175691e Merge pull request #3080 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-05-28 13:57:42 +02:00
Crowdin Bot 648f517a3f New Crowdin translations by GitHub Action 2026-05-28 11:38:10 +00:00
David KasparandGitHub 38fe2861b0 Merge pull request #3079 from davotoula/fix/namecoin-password-toggle-icon
Use distinct icons for password visibility toggle
2026-05-28 13:36:13 +02:00
davotoula ace6e979d9 fix(namecoin): use distinct icons for password visibility toggle
The trailing icon used MaterialSymbols.Lock in both branches of the
visibility conditional, making it a no-op. Switch to Visibility /
VisibilityOff to match the AccountBackupScreen convention.
2026-05-28 12:01:45 +02:00
Claude ae05bb9abd refactor(feeds): hoist auto-stick into Saveable* wrappers
Pulls StickToTopOnPrepend out of every per-feed callsite and into
SaveableFeedContentState, SaveableGridFeedContentState, SaveableFeedState,
and SaveableGridFeedState — the same wrappers that already own
WatchScrollToTop. A new FeedContentState-keyed overload derives the head
key from feedContent → Loaded.feed → list.firstOrNull()?.idHex, so the
wrappers can wire auto-stick without any per-feed plumbing.

Removes the explicit StickToTopOnPrepend calls from FeedLoaded,
PictureFeedLoaded, ArticlesFeedLoaded, NestsFeedLoaded,
WebBookmarksFeedLoaded, GalleryFeedLoaded, DiscoverFeedLoaded,
DiscoverFeedColumnsLoaded, and ChatroomListFeedView — they all consume
listStates created by one of the four wrappers above.

Kept as explicit calls:
- UserFeedView (custom listState, no wrapper)
- CardFeedView (CardFeedContentState — different type)
- TabNotesNewThreads (custom listState, no wrapper)
- BrowseEmojiSetsScreen (doesn't use SaveableGridFeedContentState)

Also extracts the list/grid bodies to a private stickToTopOnPrepend
core that takes the state object as the LaunchedEffect key plus
lambdas for sampling / scroll, and switches the cached flag from
mutableStateOf to a plain BooleanArray holder (read only from effects,
never composition — no snapshot tracking needed). Adds the missing
"why isScrollInProgress gating is safe" line to the KDoc.
2026-05-28 02:09:40 +00:00
Claude ac3f351458 feat(feeds): stick to top when items prepend and user is at top
Adds StickToTopOnPrepend, a Compose helper that auto-scrolls back to
index 0 whenever new items land at the head of a feed — but only if the
user was already at the very top right before the update. Wired into
every FeedLoaded variant: Home/Hashtag (FeedLoaded), Notifications
(CardFeedView), Pictures, Articles, Discover (list + grid),
WebBookmarks, ProfileGallery, BrowseEmojiSets, Chatroom list,
UserFeed, NestsFeed, and TabNotesNewThreads.

Why this was broken: every feed uses stable key = item.idHex, so when N
items prepend Compose preserves the user's visual anchor by shifting
firstVisibleItemIndex from 0 to N. The existing
WatchScrollToTop only fires on explicit tab-bar taps, and the
LaunchedEffect(items.firstOrNull()) { if (firstVisibleItemIndex <= 1) }
pattern (used in ChatFeedView and PublicChatsFeedLoaded) breaks the
moment more than one item arrives in the same batch.

How the helper avoids the race: it tracks "was at top" continuously via
snapshotFlow but only flips it true → false when isScrollInProgress is
true. Data-driven index shifts happen with isScrollInProgress == false,
so they never poison the cached value. When firstItemKey changes and
the cached value is still true, we snap back to 0 with an instant
(non-animated) scroll so the prepend appears as in-place growth instead
of a visible jump-then-scroll.

ChatFeedView is left alone — it already works because reverseLayout
masks the prepend shift.
2026-05-27 23:35:56 +00:00
Vitor PamplonaandGitHub 522a83c4de Merge pull request #3078 from vitorpamplona/claude/pensive-turing-6UC1W
Add dedicated NIP-82 software app detail screen
2026-05-27 18:38:03 -04:00
Claude a2b4e5fa70 feat(nip82): compact apps feed card + dedicated detail screen
Rework the NIP-82 Software Applications feed item so it scans cleanly at
list density and split the detail content into its own route.

Feed card (RenderSoftwareApplication): icon + name + summary, full
description (3 lines), platforms / license chips, and a latest-version
chip resolved from LocalCache. Drops the screenshots strip, website /
repo link rows, and #topic chips at feed scale. The card is tappable
and the standard ReactionsRow now hosts replies, boosts, likes, zaps,
and share underneath each card.

New SoftwareAppDetailScreen (Route.SoftwareAppDetail) reached via the
card tap, the routeFor() dispatch, and naddr deep links. Layout: 72dp
header, screenshots carousel, About, Platforms, Topics (#tag chips
clickable through to Route.Hashtag), Links, ReactionsRow, latest
release with bundled assets, a collapsible "show older releases"
section, and the NIP-22 comment thread inline (driven off the app's
address tag through ThreadFeedViewModel + ThreadFilterAssembler).
2026-05-27 22:23:59 +00:00
Vitor PamplonaandGitHub 097f9a9a5b Merge pull request #3077 from mstrofnone/feat/desktop-namecoin-core-rpc-backend
feat(desktop): Namecoin Core RPC backend + composite fallback
2026-05-27 16:07:01 -04:00
m d9d7b44e91 feat(desktop): Namecoin Core RPC backend + composite fallback
Brings Amethyst Desktop to feature parity with Android for the Namecoin
resolution backend stack landed in #3056 / #3068. Three pieces:

- DesktopNamecoinPreferences now persists backend, namecoinCoreRpc,
  fallbackToCustomElectrumx and fallbackToDefaultElectrumx (KEY_BACKEND
  / KEY_CORE_RPC / KEY_FALLBACK_*), mirroring NamecoinSharedPreferences.
  Mutators are non-suspend because java.util.prefs is synchronous,
  unlike Android's coroutine-backed DataStore. The Jackson mapper now
  rejects unknown properties on read so kotlinx `@Serializable`
  computed getters (e.g. NamecoinCoreRpcConfig.isUsable) round-trip
  cleanly through java.util.prefs.

- DesktopNamecoinNameService takes an optional OkHttpClient provider,
  lazily constructs a NamecoinCoreRpcClient when supplied, and builds
  a fresh CompositeNamecoinBackend per lookup based on current
  NamecoinSettings. Same shape as AppModules#buildNamecoinBackend.
  Exposes the underlying RPC client (rpcClient) and a probeCoreRpc(cfg)
  helper for the Settings Test RPC button.

- NamecoinSettingsSection gains a backend radio selector, a Core RPC
  subform (URL / username / password / Save / Test RPC) with a TOFU
  cert-pin AlertDialog mirroring Android's NamecoinCoreRpcSection, and
  a fallback toggles section. The same KEY_PINNED_CERTS list is shared
  with both ElectrumXClient and NamecoinCoreRpcClient via
  setDynamicCerts(...), matching Android's behaviour where both
  backends consume one trust store.

- Main.kt wires DesktopHttpClient.currentClient() in as the Core RPC
  HTTP provider so .onion RPC URLs flow through the existing Tor
  routing without extra plumbing, and propagates the new mutators to
  the Settings UI.

- Extends DesktopNamecoinPreferencesTest with 8 new cases covering
  default state, backend round-trip, Core RPC URL/user/pass/pin-flag
  round-trip, fallback toggles, reset clearing, and a full
  multi-field round-trip across a fresh preferences instance.

Verification on the canonical workspace clone:
- ./gradlew :commons:jvmTest --tests *Namecoin* — BUILD SUCCESSFUL
- ./gradlew :amethyst:compilePlayDebugKotlin — BUILD SUCCESSFUL
- ./gradlew :desktopApp:compileKotlin :desktopApp:test — BUILD SUCCESSFUL
- ./gradlew :amethyst:testPlayDebugUnitTest --tests *Namecoin* — BUILD SUCCESSFUL
- ./gradlew :amethyst:spotlessCheck :commons:spotlessCheck
  :desktopApp:spotlessCheck — BUILD SUCCESSFUL
2026-05-28 06:01:54 +10:00
Vitor PamplonaandGitHub f898e4be57 Merge pull request #3067 from vitorpamplona/claude/confident-allen-AOGU6
Add music tracks and playlists support with NIP-51 events
2026-05-27 15:59:41 -04:00
Claude bf02a235e0 Merge remote-tracking branch 'origin/main' into claude/confident-allen-AOGU6
# Conflicts:
#	amethyst/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt
#	amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt
#	amethyst/src/main/java/com/vitorpamplona/amethyst/model/AccountSettings.kt
#	amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt
2026-05-27 19:55:07 +00:00
Vitor PamplonaandGitHub 08520f553f Merge pull request #3076 from mstrofnone/feat/desktop-namecoin-pinned-certs
feat(desktop): persist TOFU-pinned Namecoin ElectrumX certs
2026-05-27 15:45:19 -04:00