Commit Graph
16004 Commits
Author SHA1 Message Date
Claude 056d54434e fix(podcasts): bookmark button now reflects state + confirms with a toast
PodcastBookmarkButton read `note in bookmarks.public` — an identity-based
List<Note> containment that is unreliable for addressable shows/episodes
(the rendered note instance may differ from the one rebuilt from the
a-tag), so the icon never flipped and there was no way to tell a podcast
was already bookmarked.

Switch to the public bookmark id/address sets (the same reactive pattern
the working git-repository bookmark button uses): match note.address for
addressable notes and note.idHex otherwise. The icon now reliably shows
bookmarked vs not (filled/primary vs outline/onSurfaceVariant), and each
tap fires a confirming toast so the action is never silent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JGa1EM5KWyDo1o5Yr6sS18
2026-07-01 13:22:31 +00:00
Claude 496cda2f22 feat(podcasts): dedicated Podcast Bookmarks screen + detail-screen toggle
Adds a Podcasts row to the Bookmark lists screen (mirroring Git
Repositories), opening a feed of just the bookmarked podcasts:

- quartz: isPodcastEvent() — a reusable predicate matching shows,
  episodes (NIP-F4 + Podcasting-2.0) and trailers, used to pull the
  podcast subset out of the mixed NIP-51 kind:10003 bookmark list.
- BookmarkPodcastsFeedFilter / ...FeedViewModel / BookmarkedPodcastsScreen
  filter the bookmark list (public + private) down to podcast notes,
  newest first, and render them with the standard podcast cards.
- Route.BookmarkedPodcasts + AppNavigation wiring; a "Podcasts" row with a
  live count in ListOfBookmarkGroupsFeedView.
- The single-podcast detail screen (PodcastScreen) gains a bookmark action
  in its top bar that reflects and toggles bookmarked state (reusing the
  stateful PodcastBookmarkButton). TopBarExtensibleWithBackButton now
  accepts an actions slot to host it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JGa1EM5KWyDo1o5Yr6sS18
2026-06-30 23:05:29 +00:00
Claude ec3b41aa34 feat(podcasts): pay V4V splits through the zap button as real zaps
The standard zap button now detects a Podcasting-2.0 value-for-value block
on a podcast note (episode or show) and pays that split instead of a plain
author zap — so V4V becomes a first-class zap rather than a separate, no-
receipt payment:

- AccountViewModel.zap() intercepts a note carrying a value block and routes
  the chosen amount to the V4V split. Intercepting at zap() covers every
  entry point (one-tap, amount popup, custom dialog, polls) with no UI churn.
- V4VPaymentHandler gains asZap/zapType: lnaddress shares now attach a NIP-57
  zap request, so a Nostr-aware provider mints a zappable invoice and
  publishes a receipt (driving the zap button's icon/counter). Node shares
  stay keysend — no LNURL, so a receipt is impossible there by protocol.
- Per-minute streaming pays with asZap=false so it doesn't publish a receipt
  every minute.
- The dedicated "Send value" button is now redundant and removed;
  PodcastValueSplits becomes a pure recipient/percentage breakdown display
  next to the zap button.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JGa1EM5KWyDo1o5Yr6sS18
2026-06-30 22:45:48 +00:00
Claude a65e37b8f5 feat(podcasts): render Podcasting-2.0 shows in detail + thread views
Make the single-podcast detail screen spec-neutral so a Podcasting-2.0
show (kind 30078, d=podcast-metadata, e.g. "Soapbox Sessions") renders
its real cover art and title instead of the default Amethyst banner and
"Podcasts" fallback:

- PodcastHeader/PodcastScreen now take a resolved PodcastShow? instead of
  a NIP-F4-only PodcastMetadataEvent?, resolving from either the kind
  10154 (F4) or kind 30078 (P2.0) metadata event.
- FilterOnePodcast adds a #d=podcast-metadata filter on kind 30078 so the
  P2.0 show metadata is actually fetched on deep-links/fresh loads.
- NoteMaster (thread/full view) now dispatches Podcasting20EpisodeEvent,
  Podcasting20TrailerEvent, and the kind 30078 podcast-metadata variant
  to the shared podcast renderers, matching NoteCompose.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JGa1EM5KWyDo1o5Yr6sS18
2026-06-30 22:05:37 +00:00
Claude 821e9bafdd fix: drop the "Mock Podcast" kind:10154 spam flood before consuming
Someone is flooding thousands of identical mock NIP-F4 show-metadata events.
They share an exact fingerprint — title "Mock Podcast", description and content
both "Headless test feed" — so match that and refuse to cache them.

- PodcastMetadataEvent.isMockSpam() encodes the fingerprint (all three fields
  must match, so a real show sharing one field is never flagged); unit-tested.
- LocalCache's PodcastMetadataEvent consume branch returns without storing when
  it matches, so the spam never reaches the cache, feeds, search, or the merged
  podcast list.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JGa1EM5KWyDo1o5Yr6sS18
2026-06-30 20:50:33 +00:00
Claude 1eeda56b51 feat: add "Mine" to the Podcasts and Podcast Episodes feed filters
The two podcast feeds used kind3GlobalPeopleRoutes, which omits the "Mine"
option — so a creator had no way to filter the feed down to their own published
shows/episodes (and the default follow-list view is usually empty for podcasts,
since NIP-F4 shows are their own keypairs you rarely kind:3-follow).

Add a podcastRoutes catalog in TopNavFilterState that mirrors musicRoutes
(content catalog + Mine + interests + mute list) and point both podcast top bars
at it. "Mine" resolves to an AuthorsTopNavPerRelayFilterSet of the user's own
pubkey, which the podcast SubAssemblyHelper already dispatches through
filterPodcastEventsByAuthors — so selecting it actually fetches the creator's
own catalog, not a dead option.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JGa1EM5KWyDo1o5Yr6sS18
2026-06-30 20:07:54 +00:00
Claude d0f6f03d2c Merge remote-tracking branch 'origin/main' into claude/podcast-event-kinds-merge-vv24gd 2026-06-30 19:32:50 +00:00
Claude 13d654f6be Merge remote-tracking branch 'origin/main' into claude/podcast-event-kinds-merge-vv24gd 2026-06-30 19:23:05 +00:00
Vitor Pamplona e32b3160ae Updating libraries. 2026-06-30 15:21:43 -04:00
Vitor PamplonaandGitHub d1bd8dd3b4 Merge pull request #3427 from vitorpamplona/claude/plans-in-folders-hajl33
docs: add per-module plans indexes and master roll-up
2026-06-30 12:03:06 -04:00
Claude ff50652484 docs: add root PLANS.md master index across all module plan folders
Adds a repo-root cross-module roll-up that stitches the 10 per-folder
plans/ indexes into one view: totals, a per-module status table, and a
"live work" section listing every in-progress / queued / abandoned plan
with links. Shipped plans stay in each folder's archive/ and are linked
via the per-module README.

142 plans: 122 shipped, 9 in-progress, 8 queued, 3 abandoned.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016hpUivtmq4pgzqRbY6MYrA
2026-06-30 15:52:49 +00:00
Claude 6579b5f656 docs: audit, status-stamp, and index all module plans
Audited all 143 plan files across the 10 plans/ folders. Each plan now
carries a Status header (shipped | in-progress | queued | abandoned)
backed by codebase evidence, and every folder has a README.md index
grouping plans by status.

Shipped plans were moved into a per-folder plans/archive/ (via git mv,
history preserved) so each plans/ folder surfaces only live work:

  shipped (archived): 122   in-progress: 8   queued: 7   abandoned: 4

docs/plans/ is the frozen legacy folder; its plans were stamped and
indexed in place (48 of 52 archived) but it remains closed to new plans.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016hpUivtmq4pgzqRbY6MYrA
2026-06-30 15:35:38 +00:00
Vitor PamplonaandGitHub dc47296a5f Merge pull request #3425 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-06-30 09:13:26 -04:00
vitorpamplonaandgithub-actions[bot] a054215c4f chore: sync Crowdin translations and seed translator npub placeholders 2026-06-30 12:51:31 +00:00
Vitor PamplonaandGitHub 26ac7b7ff0 Merge pull request #3426 from vitorpamplona/claude/connected-apps-permissions-bqion9
Add "Manage permissions" UI for Connected Apps detail screen
2026-06-30 08:49:04 -04:00
Vitor PamplonaandGitHub 609aa1d0fc Merge pull request #3424 from nrobi144/feat/desktop-follow-packs
feat(desktop): Follow Packs (NIP-51 kind 39089) — Discover + follow flow
2026-06-30 08:44:40 -04:00
nrobi144 de2c970e3e feat(desktop): Follow Packs (NIP-51 kind 39089) discovery and follow flow
Adds a Follow Packs experience to Amethyst Desktop:

- New "Discover" sidebar destination with featured-pack hero, hashtag chips
  driven by NIP-12 `t` tags, a 3-up "From the pack" notes feed, and a
  right-rail of mini pack thumbnails.
- New "Follow Packs" launchable column (App Drawer + Discover "Browse all")
  with multi-field search across title, description, creator name/npub,
  and `t` tags.
- Pack detail overlay (read-only) with per-member Follow/Unfollow buttons
  that reflect the live kind-3 state, plus pack-level Follow all /
  Unfollow all with a dedupe-aware confirm dialog ("Follow N new (M
  already followed)").
- Bulk follow / unfollow batched into a single kind-3 publish via new
  `FollowActions.buildUnfollowBatch` and `Kind3FollowListState.follow/
  unfollow(users: List<User>)`. The mutating call sites are Mutex-
  protected against concurrent races.
- naddr → 39089 references in notes render as a rich inline card with
  avatar stack + Follow all CTA. Cache miss triggers a one-shot
  subscription; empty / deleted packs render minimal states.
- Shuffle button rotates both the featured pack and the gallery,
  excluding the last 5 shown.
- Pack image fields render via Coil `AsyncImage` with a deterministic
  gradient fallback.

Protocol additions:
- Quartz: `FollowListEvent.hashtags()` convenience accessor.

Bug fixes wrapped into the feature:
- `DesktopLocalCache.consumeContactList` now also loads the event into
  `addressableNotes` so `Kind3FollowListState.getFollowListEvent()`
  returns the user's actual kind-3. Without this, every bulk follow
  silently replaced (rather than appended to) the contact list.
- Added Material Symbols `Shuffle` codepoint and regenerated the
  bundled subset font (still 432 KB).
2026-06-30 12:05:16 +03:00
Vitor PamplonaandGitHub 07e0cc2989 Merge pull request #3419 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-06-29 22:28:20 -04:00
Vitor PamplonaandGitHub a0586a8613 Merge pull request #3422 from vitorpamplona/claude/event-tag-parsing-w7x43s
feat(nip89): parse and display app-handler t/i/a/client tags
2026-06-29 22:28:02 -04:00
Claude 58b3e84184 feat(napplet): add "Manage permissions" to app pull-down sheets
Add a direct link to each running app's editable Connected Apps
permission-detail screen from its top pull-down sheet, so users can
change the trust level and per-capability grants as they navigate.

Covers every top pull-down rendering:
- Embedded napplet/nsite and web-app tabs (Compose TopControlSheet),
  keyed by the napplet `pubkey:dtag` coordinate or the web client's
  `browser:<origin>`.
- Full-screen sandbox host and direct-browser activities (native
  NappletControlSheet), via a new MSG_OPEN_PERMISSIONS IPC: the host
  (which can't state its own coordinate) sends its launch token or
  visited origin, and the main-process broker resolves the trusted
  coordinate and opens MainActivity through a `connectedapp?coordinate=`
  deep link added to uriToRoute.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019dXhUL8To3qVXJVBZGCmhU
2026-06-30 01:59:00 +00:00
Claude 3b3d7b8c11 feat(nip89): richer related refs, handles/NIPs bottom sheets
Refine the app-handler card rendering:

- NIP "Implements" bottom sheet now shows a wrapping row of clickable NIP
  chips that open each spec in the browser, instead of a list of raw URLs.
- "Handles" gets the same "+N" overflow -> bottom sheet treatment as
  "Implements", listing every handled kind.
- Related (`a`-tag) references now render as the referenced event's author
  avatar + its real name with a short kind label, since these are vouched
  for by the handler's author. Software Application shows the app name
  (not the package-id d-tag) and is labelled "App"; Git repositories and
  NIP-text events use their name/title, falling back to the d-tag until the
  event loads.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FLfM7JUTr2vNiNUi4Ukmqn
2026-06-30 01:41:42 +00:00
vitorpamplonaandgithub-actions[bot] d564dac0eb chore: sync Crowdin translations and seed translator npub placeholders 2026-06-30 01:25:28 +00:00
Vitor PamplonaandGitHub 1183ac7a00 Merge pull request #3421 from vitorpamplona/claude/nip07-permission-screen-bug-f501wz
Fix first-connect dialog suppression to allow retry after cooldown
2026-06-29 21:23:02 -04:00
Vitor PamplonaandGitHub 43a6dbaf44 Merge pull request #3420 from vitorpamplona/claude/browser-console-log-design-rq4x48
Console panel: add visibility toggle, elevation, and state sync
2026-06-29 20:31:07 -04:00
Claude 8b4f5e28f4 fix(napplet): let users re-trigger NIP-07 connect after cancelling
Pressing Back on the "Connect to Nostr" first-connect dialog resolves to
AppConnectResult.Cancelled, which added the app's coordinate to an in-memory
`sessionCancelled` set. That set suppressed every future connect prompt for the
entire broker lifetime, so a later request — e.g. the user re-clicking "login"
in the in-app browser — was silently denied and the dialog never reappeared.
Because a Cancel persists nothing, the app also never showed up in Connected
Apps, leaving the user with nothing to clear to recover.

Replace the permanent suppression with a short, self-clearing cooldown
(`cancelledUntil` map): a Cancel suppresses re-prompts only briefly so the
burst of requests a page/napplet fires on load doesn't relaunch the dialog per
request, while a deliberate retry seconds later prompts again. The clock is
injectable for deterministic tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HDcts4HzwSff4fy6oSVA6D
2026-06-30 00:16:31 +00:00
Claude 7d7789c8c9 fix(browser): console toggle + on-top pull tab in full-screen browser
The full-screen direct-WebView browser (NappletBrowserActivity, launched when
you type an address) and the sandbox host (NappletHostActivity) used an older
console design that diverged from the embedded tabs' Compose chrome:

- The Console row in NappletControlSheet was a plain action row and the bottom
  pull-up grabber was always visible. Make Console a Switch toggle (like the Tor
  row / the Compose TopControlSheet), and hide the whole NappletConsolePanel
  until the toggle is on — turning it on reveals the sheet already pulled up,
  mirroring BottomConsoleSheet.
- The console grabber/panel sat at elevation 0 while the top sheet's panel is at
  6dp, so an open top sheet drew over the console when they overlapped (e.g. in
  landscape). Elevate the console sheet above the top sheet so its pull tab and
  log render on top, matching the Compose layer where BottomConsoleSheet is
  composed after TopControlSheet.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A9kfpNrBRB8WJNi67NHGGX
2026-06-30 00:14:19 +00:00
Claude 250f918ebe feat(nip89): parse and display app-handler t/i/a/client tags
NIP-89 handler cards (kind 31990) previously only surfaced the supported
kinds and platform links, and even the platform links were silently dropped
when the link tag had no entity type. This widens both parsing and display:

- Fix PlatformLinkTag.match to accept 2-element link tags (entity type is
  optional per NIP-89), so e.g. NostrHub's `["android", "intent:..."]` links
  are no longer discarded.
- Parse the `i` supported-NIP tags (NostrHub points them at the NIP spec
  markdown files) into a new SupportedNipTag, plus accessors for `t`
  categories, `a` related addresses, and the `client` tag.
- Extend AppDefinitionEvent.build() with categories/supportedNips/
  relatedAddresses/client so creation stays symmetric with parsing.
- Render the new data in RenderAppDefinition: category chips, compact
  tappable rows for related addressable events (source repo, store listing,
  ...), a "via <client>" line, and NIP chips with a "+N" overflow that opens
  a bottom sheet listing every supported NIP linking to its spec.

The deprecated `alt` tag is intentionally not surfaced on the handler card.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FLfM7JUTr2vNiNUi4Ukmqn
2026-06-29 23:57:40 +00:00
Claude 6355784c98 Merge remote-tracking branch 'origin/main' into claude/podcast-event-kinds-merge-vv24gd 2026-06-29 23:51:54 +00:00
Vitor PamplonaandGitHub 4326d84887 Merge pull request #3415 from vitorpamplona/claude/git-repo-readme-code-tabs-e4uf6c
Add git smart-HTTP browser for NIP-34 repositories
2026-06-29 19:50:24 -04:00
Claude fdcfc05ba2 refactor(git): collapse status/PR-update indexes to map().stateIn
Now that observeEvents re-emits the whole matching list each time,
GitStatusIndex and GitPullRequestUpdateIndex no longer need the imperative
launch/collect-into-MutableStateFlow wrapper carried over from the old
newEventBundles version. Each is now a single observeEvents().map { reduce }
.stateIn(scope, Eagerly, null) — dropping startIfNeeded(), the AtomicBoolean
double-start guard, and the MutableStateFlow/asStateFlow pair.

Eagerly (not WhileSubscribed) is required: callers read .value synchronously
(isClosedOrResolved, the feed filters, the home open-count derivations) and
must not see a stale map when nobody is collecting. All startIfNeeded() call
sites removed; stateIn shares one upstream subscription across collectors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpNmN8CvP6HnEsdTGAjVUr
2026-06-29 23:43:25 +00:00
Claude 9a6c535cbd feat(git): bookmarked repositories as a standalone screen
Replace the third "Repositories" tab on the default bookmark screen with a
dedicated entry on the bookmark-lists screen, mirroring how Pinned Notes
works: a row in ListOfBookmarkGroupsFeedView that opens its own
BookmarkedRepositoriesScreen via the new Route.BookmarkedRepositories.

The row shows the bookmarked-repo count from
gitRepositoryListState.publicRepositoryAddressSet; the screen renders the
BookmarkRepositoriesFeedViewModel feed (moved to a repositories/ package),
invalidates on bookmark changes, and preloads any uncached repo
announcements via the EventFinder. Reverts the tab added to
BookmarkListScreen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpNmN8CvP6HnEsdTGAjVUr
2026-06-29 23:30:40 +00:00
Claude a2f918c1eb feat(git): bookmarked repos tab + observeEvents for GitStatusIndex
- GitStatusIndex now subscribes to a kind-1630..1633-filtered
  LocalCache.observeEvents instead of LocalCache.live.newEventBundles,
  matching the GitPullRequestUpdateIndex change: the indexed observable
  seeds from the cache index and re-emits the full list on each new status
  event, so the manual onStart full-cache scan and per-bundle type
  filtering are gone and the collector just reduces to latest-per-target.
- Bookmark screen gains a third "Repositories" tab listing the user's
  bookmarked (NIP-51 kind 10018) git repositories. New
  BookmarkRepositoriesFeedFilter resolves the public repository address set
  to addressable notes (newest first); the screen invalidates it on
  publicRepositoryAddressSet changes and preloads any uncached repo
  announcements via the EventFinder.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpNmN8CvP6HnEsdTGAjVUr
2026-06-29 23:20:19 +00:00
Claude 0d8936e8d3 refactor(git): index PR updates via LocalCache.observeEvents
GitPullRequestUpdateIndex now subscribes to a kind-1619-filtered
LocalCache.observeEvents instead of LocalCache.live.newEventBundles. The
indexed observable seeds its matching set from the cache index (via init())
and re-emits the full list on each new PR update, so the manual onStart
full-cache scan and the per-bundle type filtering over every event of every
kind are both gone. The collector just reduces the list to the
latest-per-parent map. PR updates are rare, so recomputing the whole map per
emission is cheaper than scanning every bundle.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpNmN8CvP6HnEsdTGAjVUr
2026-06-29 23:06:11 +00:00
Claude 2316e72573 fix(git): bookmark feedback, social divider, and disappearing-bar reset
- Top-bar repo bookmark toggle now switches between BookmarkAdd (with +)
  and Bookmark glyphs instead of two identical  glyphs, so the icon
  visibly changes shape (not just tint) when starred/unstarred.
- Add a thin HorizontalDivider after the ReactionsRow on the repo home.
- Code browser: opening/closing a file or changing folders swaps the
  scrollable in place, landing the new view at the top with no scroll
  delta, which left the disappearing top bar stranded at its hidden
  offset over a blank band. Expose the scaffold bar state via
  LocalDisappearingBarState and reset it to visible on each in-place view
  change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpNmN8CvP6HnEsdTGAjVUr
2026-06-29 23:01:16 +00:00
Claude f14ddd9e45 fix(git): import KMP Dispatchers.IO in GitRepositoryListState
The commonMain GitRepositoryListState used Dispatchers.IO without importing
the multiplatform kotlinx.coroutines.IO extension, so it resolved to the
JVM-only member and broke the iOS native compile
(:commons:compileKotlinIosSimulatorArm64). Matches BookmarkListState.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpNmN8CvP6HnEsdTGAjVUr
2026-06-29 22:44:14 +00:00
Claude 2f9162a96f feat(git): New Issue is a full screen; fix square FAB shape
- Converts the New Issue composer from an AlertDialog to a dedicated screen
  (new Route.GitRepositoryNewIssue + GitNewIssueScreen with its own top bar
  and a Create action). The Issues FAB now navigates to it.
- The extended FAB rendered square because the app theme sets shapes.large
  (the extended-FAB default shape) to 0.dp; pin an explicit RoundedCornerShape.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpNmN8CvP6HnEsdTGAjVUr
2026-06-29 22:06:02 +00:00
Claude 3e0c688b8c feat(git): htree open-in-browser fallback; remove maintainers; tighten gaps
- Repos that can't be cloned over http(s) (e.g. Iris's htree://) now show a
  "Hosted externally" notice with an open-in-browser link instead of an empty
  dashboard — on the home, the Code screen, and the feed repo card.
- Removed the "Maintained by" row from the project home.
- Tighter home section spacing (12 → 8dp) and a smaller bottom padding on the
  feed repo card so the last-commit line sits closer to the reaction row.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpNmN8CvP6HnEsdTGAjVUr
2026-06-29 21:06:24 +00:00
Claude a4bd541522 feat(git): snapshot cache, FAB, disappearing-bar fix, title subtitle, spacing
- Snapshot cache: a process-wide GitRepoSnapshotCache keyed by repo address.
  The browser ViewModel serves an already-fetched default-branch snapshot
  synchronously, so the stats render in share-to-image and don't re-fetch when
  switching screens.
- Issues/PR screens: filter chips now live inside the disappearing top bar
  (via the scaffold's belowBar slot) so they hide with it instead of leaving a
  static black band; the feed uses normal content padding.
- New issue is now an extended FAB on the Issues screen.
- Top bar shows the repo description as a single-line subtitle under the name;
  removed the duplicate description from the home body.
- Tighter spacing: home sections, code header rows (branch row / search /
  breadcrumb).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpNmN8CvP6HnEsdTGAjVUr
2026-06-29 20:50:07 +00:00
Claude 76ed4bc685 Merge remote-tracking branch 'origin/main' into claude/podcast-event-kinds-merge-vv24gd 2026-06-29 20:09:32 +00:00
Claude 2378d70326 Merge remote-tracking branch 'origin/main' into claude/git-repo-readme-code-tabs-e4uf6c 2026-06-29 20:09:01 +00:00
Vitor PamplonaandGitHub 2152d5d5d6 Merge pull request #3416 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-06-29 15:47:30 -04:00
vitorpamplonaandgithub-actions[bot] 4060bfac39 chore: sync Crowdin translations and seed translator npub placeholders 2026-06-29 19:43:35 +00:00
Vitor PamplonaandGitHub f5879ab107 Merge pull request #3418 from vitorpamplona/claude/cashu-wallet-wizard-0zr280
Add Cashu wallet find-or-create wizard with cross-relay discovery
2026-06-29 15:40:59 -04:00
Claude a687e03461 Merge remote-tracking branch 'origin/main' into claude/cashu-wallet-wizard-0zr280
# Conflicts:
#	amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt
2026-06-29 19:26:56 +00:00
Claude 124dcafdf9 fix(cashu): re-sign on adopt so a deleted wallet can't be re-deleted
The find-or-create wizard can surface a wallet the user previously
DELETED — a relay that missed the kind:5 still serves the kind:17375 to
the crawl. adoptDiscoveredWallet rebroadcast that event verbatim (same id,
same created_at), which loses to the prior NIP-09 deletion two ways:
DeletionEvent.build emits both an `e` tag (old id) and an `a` tag (the
replaceable 17375:pubkey: address), so relays reject the duplicate id and
re-delete every version with created_at <= the deletion's the moment the
kind:5 propagates back — on relays and in our own LocalCache. The
"reactivated" wallet would then silently vanish.

Adopt now re-signs a FRESH kind:17375 + kind:10019 (via publishWalletEvents)
with the discovered wallet's own mints and P2PK key. A new id escapes the
`e`-tag delete and created_at=now escapes the `a`-tag delete, while the
same key + mints preserve the nutzap address and all recoverable funds
(the NUT-13 seed derives from the key, not the event id). Falls back to a
verbatim rebroadcast only if the wallet can't be decrypted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EqmMR2QiULS5QGosSgSQAe
2026-06-29 18:18:38 +00:00
Claude 0bfe9d370e fix(cashu): return to the Wallet hub after deleting the wallet
Deleting the Cashu wallet popped back to CashuWalletScreen, which on an
empty wallet auto-launches the find-or-create wizard — so the user was
funneled straight back into creating the wallet they just deleted.

Navigate to the top-level Wallet hub (Route.Wallet) via newStack instead,
which pops the Cashu screens off the back stack so the wizard never
composes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EqmMR2QiULS5QGosSgSQAe
2026-06-29 18:13:18 +00:00
Claude d2dfd044cf feat(cashu): add "Wallet Created" celebration before the mint picker
In the find-or-create wizard, choosing "Create a new wallet" jumped
straight to the mint manager. Add a short celebratory interstitial first:
an animated check badge springs in (bouncy overshoot) behind an expanding
pulse ring, "Wallet Created" + "Now pick a few mints to host your sats"
fade up, a haptic fires, and a "Pick mints" button continues to the mint
selection.

The screen is purely presentational — the kind:17375 still isn't
published until the user adds a mint on the next screen — so "Pick mints"
uses popUpTo to replace the interstitial in the back stack, avoiding an
awkward return to the celebration.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EqmMR2QiULS5QGosSgSQAe
2026-06-29 18:02:31 +00:00
Claude 29303b18c2 feat(git): make recent-activity rows and the last-commit line clickable
- Recent-activity rows navigate to the issue/PR they represent (routeFor).
- The last-commit strip is now tappable: on the home it opens the Code
  screen; on the feed repo card it opens the repository.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpNmN8CvP6HnEsdTGAjVUr
2026-06-29 17:50:03 +00:00
Claude 09633abae5 feat(git): home polish + repo-card dashboard in the feed
Home screen:
- Nav cards: tighter vertical spacing; badges now count only OPEN issues/PRs,
  derived from the live GitStatusIndex (started on the home so the split is
  correct without visiting the Issues screen first).
- Moved the reaction row to after the recent-activity pulse.
- Added the standard 3-dot note menu (MoreOptionsButton) to the top bar.

Feed card (RenderGitRepositoryEvent):
- Replaced the web/clone links with the same stat tiles + language bar +
  last-commit strip used on the home, loaded from a lazily-fetched shallow
  snapshot. (Factory made internal so the card can build the browser VM.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpNmN8CvP6HnEsdTGAjVUr
2026-06-29 17:45:18 +00:00
Claude 45f36a8159 refactor(git): use the standard ReactionsRow; tighten file rows
- Social bar now renders the app's canonical ReactionsRow (reply, boost,
  like, zap, zapraiser, reaction gallery) instead of a bespoke subset, so
  the repository announcement behaves exactly like any other note.
- Code browser file rows: replace the heavy 32dp boxed icon with a plain
  20dp icon and tighten spacing/padding, reducing the oversized horizontal
  gap before the file name.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpNmN8CvP6HnEsdTGAjVUr
2026-06-29 16:56:24 +00:00