Commit Graph
15330 Commits
Author SHA1 Message Date
Claude 765c1dfd7e feat: generate translator credits offline from the committed file
Makes docs/changelog/translators.json self-sufficient so a release no longer
needs to re-query Crowdin:

- sinceLastTag entries now carry each translator's languages ({user, languages}),
  recorded by the --seed run.
- Default mode (no flags) is offline: it generates the "## Translations" block
  straight from the committed file — reading sinceLastTag, grouping by the stored
  languages, and resolving npubs via the mappings registry. No token, no network.
- --seed/--raw remain the online paths (CI seeding / debugging). curl + git +
  credentials are only required there; the offline path needs just jq.

RELEASE_OPS now points at the tokenless `scripts/translators.sh` for the
changelog credits.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWQWVdWLAwBUBX2gJ55y6b
2026-06-19 16:02:47 +00:00
Claude 6b30486667 feat: track a rolling "since last tag" translator list
Reworks docs/changelog/translators.json into two lists maintained by
scripts/translators.sh:

- mappings: a forever-growing Crowdin-username/id -> npub registry. --seed
  appends new contributors with a blank npub and never deletes or overwrites
  existing entries.
- sinceLastTag: a rolling snapshot of who has translated since the last v* tag,
  fully refreshed on every --seed run.

The contribution window now defaults to the most recent v* tag instead of a
fixed two months (falling back to two months ago when no tag is reachable). The
CI seed job fetches tags (fetch-depth: 0) so it can resolve that window.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWQWVdWLAwBUBX2gJ55y6b
2026-06-19 15:52:27 +00:00
Claude 6c9ca11602 ci: seed translators.json from Crowdin on every sync
Adds a seed-translators job to the Crowdin workflow that runs
scripts/translators.sh --seed (past two months) and opens/updates a single
PR via peter-evans/create-pull-request whenever a new contributor appears, so
docs/changelog/translators.json stays current without manual upkeep. The
action is MIT and CI-only (not linked into any shipped artifact), and no-ops
when there is no diff.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWQWVdWLAwBUBX2gJ55y6b
2026-06-19 15:46:33 +00:00
Claude fc816f2afd feat: add --seed mode to pre-load translators.json from Crowdin
scripts/translators.sh --seed fetches every contributor in the window
(default: past two months) and merges their Crowdin usernames into
docs/changelog/translators.json with blank npubs, preserving existing
entries and deduping case-insensitively. Fill in the npubs afterwards.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWQWVdWLAwBUBX2gJ55y6b
2026-06-19 15:42:39 +00:00
Claude a5bf4451ed refactor: move translator-credits script to scripts/, document in RELEASE_OPS
Moves the Crowdin translator-credits generator from tools/translators/ to
scripts/translators.sh to sit with the other flat shell scripts. Drops the
standalone README (the script is self-documenting via --help) and folds the
release-time usage into RELEASE_OPS.md next to the changelog step.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWQWVdWLAwBUBX2gJ55y6b
2026-06-19 15:41:02 +00:00
Claude 41c686ebb3 feat: generate changelog translator credits from Crowdin
Adds tools/translators/translators.sh, which pulls a Crowdin "Top Members"
report for a release window (between two tags/dates) and prints the changelog
"## Translations" block grouped by language.

Crowdin contributors are joined against docs/changelog/translators.json, a
Crowdin-username/id -> npub mapping kept alongside the changelogs. Contributors
with no mapping are listed under UNMAPPED so they can be credited by hand and
backfilled.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWQWVdWLAwBUBX2gJ55y6b
2026-06-19 15:34:05 +00:00
Vitor Pamplona 7096819f3b v.1.12.3 v1.12.3 2026-06-19 11:13:00 -04:00
Vitor PamplonaandClaude Opus 4.8 ee58355e6e fix(ci): sign macOS Mach-O natives embedded in bundled jars before notarization
The v1.12.2 release was the first to actually codesign + notarize the macOS
artifacts (signing was wired after v1.12.1, which shipped unsigned). Both macOS
legs failed with "Notarization status: Invalid": Apple's notary service recurses
into the bundled jars and rejects the unsigned Mach-O natives inside them
(secp256k1, sqlite-bundled, jna, skiko, jkeychain, kdroidFilter mediaplayer) —
codesign on the .app and the CLI's loose-file loop never descend into jars.

Notary log confirmed the offending entries, e.g.
  sqlite-bundled-jvm.jar/natives/osx_arm64/libsqliteJni.dylib
    -> "not signed with a valid Developer ID certificate" / "no secure timestamp"

Add scripts/sign-macos-jar-natives.sh: a shared helper that signs every macOS
Mach-O inside the bundled jars with hardened runtime + a secure timestamp,
skipping Linux ELF via a `file` Mach-O gate and no-opping when no identity is
set (local/PR builds unchanged). Wire it into:
  - the CLI notarize step (runs before the loose-file signing loop)
  - a desktop signMacJarNatives Gradle task that signs the proguarded jars
    between proguardReleaseJars and createReleaseDistributable, so Compose
    seals already-signed code.

Validated locally on arm64: clean signed createReleaseDistributable produces an
.app that passes `codesign --verify --deep --strict`, with every nested native
carrying Developer ID + hardened runtime + secure timestamp.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 10:42:06 -04:00
Vitor PamplonaandGitHub 8ef4e42c16 Merge pull request #3278 from nrobi144/feat/desktop-relay-latency-health
feat(desktopApp): relay latency health — tracking, classifier & dashboard UI
2026-06-19 10:22:07 -04:00
Vitor Pamplona b8312f023a v.1.12.2 v1.12.2 2026-06-19 09:22:33 -04:00
David KasparandGitHub 47ac693d96 Merge pull request #3279 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-06-19 10:59:54 +01:00
Crowdin Bot 648f3f2bd4 New Crowdin translations by GitHub Action 2026-06-19 09:26:34 +00:00
David KasparandGitHub 29d6bc308e Merge pull request #3260 from nrobi144/worktree-fix-desktop-macos-keychain-proguard
fix(desktop): macOS forced re-login on cold boot — ProGuard strips java-keyring backend
2026-06-19 10:24:49 +01:00
nrobi144andClaude Opus 4.7 49929a4afa build(desktop): add osxkeychain.so regression guard task — fail release if stripped
The original "ProGuard strips the keychain backend" hypothesis turned out
to be wrong twice (PR 3260 comments document the binary PoW that refuted
both H1 strip-of-classes and H1b strip-of-native-resource). The full
117 KB osxkeychain.so resource ships intact in the proguarded
jkeychain-1.1.0-*.jar today, and Keyring.create() round-trips fine
against the proguarded classpath on macOS.

But the user-reported bug pattern (every cold boot, keychain key missing
→ forced re-login) maps so cleanly onto a hypothetical future
strip-of-native-resource that the guard is worth keeping. Cheap to run
(one unzip scan after proguardReleaseJars), wired onto every release
packaging task (DMG, MSI, DEB, RPM, current-OS distributable, runRelease)
so a regression can't slip past. Fails the build with a self-contained
explanation pointing at the next person who has to debug it.

The actual root cause of the reported bug remains unidentified after
three refuted hypotheses (see plan doc PoW table); needs the affected
user's Console.app logs + ~/.amethyst state to make further progress.
The LoginScreen "keychain-unavailable" diagnostic banner from the
earlier commit is unchanged and still earns its keep regardless of
which failure mode eventually turns out to be the cause.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-19 10:35:13 +03:00
Róbert NagyandGitHub 5e3fea94a1 Merge branch 'main' into feat/desktop-relay-latency-health 2026-06-19 10:28:07 +03:00
Vitor PamplonaandGitHub 552cd5d7e1 Merge pull request #3277 from vitorpamplona/claude/modest-planck-o0fy3v
Roadstr: visual overhaul with map hero and category pills
2026-06-18 19:45:19 -04:00
Claude 0a3ce4535e refactor: limit road event feed inclusion to geohash only
Back out the hashtag-screen wiring (its `t` tag is the event category,
not a topic, so road events only matched category-named hashtags). Keep
the geohash data source + feed filter, where road events belong by their
`g` tags.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017tYbcy4UGWxqQbcycyL7Yd
2026-06-18 23:42:28 +00:00
Claude e93dffa9b5 feat: include road events (1315/1316) in hashtag and geohash feeds
Add the Roadstr report (1315) and confirmation (1316) kinds to both the
relay subscription filters and the local feed gates for the hashtag and
geohash screens (the geohash kind list is shared with the home "around
me" feed). Reports carry geohash `g` tags and a category `t` tag, so they
now surface in nearby-geohash feeds and in the matching category hashtag
feed; confirmations carry `g` tags and surface in geohash feeds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017tYbcy4UGWxqQbcycyL7Yd
2026-06-18 23:36:09 +00:00
Claude f0ea68f440 fix: night map preserves hue instead of crushing to black
The previous night filter used a desaturating invert whose coefficients
summed to ~1.4 per channel, which pushed every (light) OSM tone to
near-black and erased forest/water/land differentiation. Replace it with
a lightness invert composed with a 180° hue rotation: the map darkens but
hue is preserved, so forests stay dark green, water dark blue, and labels
invert to readable white.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017tYbcy4UGWxqQbcycyL7Yd
2026-06-18 23:24:30 +00:00
Claude 2d563aba07 feat: make the road event map follow the app's dark theme
osmdroid's MAPNIK tiles are always light, so in dark mode the bright map
clashed with the UI and light overlays. Apply a night-mode colour-matrix
filter to the tiles overlay when MaterialTheme.colorScheme.isLight is
false (lightness-inverted + desaturated for a clean dark-grey map, not a
plain invert that turns forests magenta). Light theme keeps normal tiles.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017tYbcy4UGWxqQbcycyL7Yd
2026-06-18 23:15:38 +00:00
Claude bdc0c19257 fix: give road event comment an explicit on-surface color
The comment Text inherited LocalContentColor, which resolved to a
near-white in this card and made the report content hard to read on the
light map card. Color it onSurface so it stays readable in both themes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017tYbcy4UGWxqQbcycyL7Yd
2026-06-18 23:08:48 +00:00
Claude ca11b0a37b Revert "fix: readable pill text via WCAG contrast, not a luminance threshold"
This reverts commit 595d12f81b.
2026-06-18 23:06:47 +00:00
Claude 595d12f81b fix: readable pill text via WCAG contrast, not a luminance threshold
The category pill picked black/white text from a luminance threshold
(0.55) that left white text on mid-tone colors (fog gray, ice turquoise,
"other" gray), barely legible over a light map. Choose the text color by
the higher WCAG contrast ratio against the pill color instead, so light
pills now get black text.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017tYbcy4UGWxqQbcycyL7Yd
2026-06-18 23:00:55 +00:00
Claude 2b02a1341f feat: modernize road event cards with a map-hero + floating pill
Redesign the kind 1315/1316 cards from a text-title-over-small-map
layout into a map-hero card: the OSM preview becomes a full-bleed hero
with a floating, color-coded category pill overlaid on it (auto-contrast
text), and the comment/status sits in a clean padded block below. Shared
RoadEventCard + CategoryPill chrome backs both the report and the
confirmation, with a graceful no-location fallback.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017tYbcy4UGWxqQbcycyL7Yd
2026-06-18 22:52:35 +00:00
Claude aee2f77654 refactor: drop redundant expiry/age row from road event cards
NoteCompose's header already shows the post time and the NIP-40
expiration. The inner card's own "🕒 age · expires in …" line duplicated
that and, worse, conflicted with it: the header reads the relay-side
`expiration` tag (always created_at + 14d) while the card used the
per-type effective TTL (e.g. 30d for a speed camera), so the two showed
different countdowns for the same note. Remove the inner row; keep the
freshness-based pin dimming, which is visual-only and doesn't conflict.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017tYbcy4UGWxqQbcycyL7Yd
2026-06-18 22:47:44 +00:00
Claude 2e32660d9b feat: roadstr-accurate road event rendering (kind 1315/1316)
Align Amethyst's road event cards with the roadstr reference clients
(https://github.com/jooray/roadstr) for both interoperability and a
richer presentation.

Interop:
- Match roadstr's exact emoji set: road_closure 🚫 (was ) and
  other ℹ️ (was 📍). The t codes and per-type TTLs already matched.
- Make the kind 1316 NIP-31 alt status-dependent ("Roadstr: event
  confirmed" / "Roadstr: event denied") per the spec, instead of a
  single "Roadstr: event confirmation".

Rendering:
- Colored teardrop map pin per category, using roadstr's exact color
  palette, with the category emoji on the head (new MapPinIcon).
- Freshness: fade the report pin to 0.6 under 25% of effective TTL and
  0.4 once effectively expired, matching roadstr's opacity rule.
- Subtitle meta line: "🕒 23m · expires in 1h" / "· Expired" on reports
  and "🕒 23m" on confirmations.
- Confirmations get a green  / red  status pin.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017tYbcy4UGWxqQbcycyL7Yd
2026-06-18 22:38:07 +00:00
Vitor PamplonaandGitHub bdb16bfc2c Merge pull request #3276 from vitorpamplona/claude/wizardly-mendel-o3ar8d
Add resumable FTS reindex for NIP-50 search index rebuilds
2026-06-18 18:35:38 -04:00
Claude af1e34a34d fix(quartz): clamp non-positive FTS reindex batch size
A batchSize <= 0 made the SQLite resumable reindex select no rows yet
never report done, so a caller's loop would spin forever. Clamp the page
size to at least one in both stores and add a regression test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BZqPFds2TPPUKkMmBngwys
2026-06-18 22:32:51 +00:00
Claude b419db4fe0 feat(quartz): make FTS reindex pausable/resumable for large stores
A full FTS rebuild can run for a long time on a big store, so add a
resumable, batched overload alongside the one-shot:

    reindexFullTextSearch(resumeFrom: String?, batchSize): FtsReindexProgress

Each call processes ~batchSize events in its own write transaction and
returns an opaque cursor + done flag. The caller loops until done and may
stop at any point — the cursor is durable across crash/app-restart, and
the writer lock is released between batches, so "pause" is just "don't
make the next call". The path is additive/refresh and keeps search usable
throughout (no up-front wipe); the one-shot variant remains for a
guaranteed-clean rebuild.

- SQLite: FullTextSearchModule.reindexBatch walks event_headers ordered
  by the monotonic row_id (a free, stable cursor), restricted to
  searchable kinds, delete-then-insert per event so batches are
  idempotent and never duplicate rows.
- Filesystem: FsEventStore walks one idx/kind/<k>/ dir per step (linear,
  no re-sort); cursor is the next searchable kind. Idempotent linkFts, so
  nothing is wiped. Pauses between kinds.
- Wrappers delegate; new FtsReindexProgress value type carries cursor +
  progress + done.
- cli: `amy store reindex-fts` now loops the batched path to completion
  and reports processed/batch counts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BZqPFds2TPPUKkMmBngwys
2026-06-18 22:16:48 +00:00
Vitor PamplonaandGitHub c84333c753 Merge pull request #3275 from vitorpamplona/fix/tor-circuit-dead-warm-reset
fix(tor): warm-reset on dead-circuit self-heal instead of wiping state
2026-06-18 18:14:17 -04:00
Vitor PamplonaandClaude Opus 4.8 048aa821b6 fix(tor): warm-reset on dead-circuit self-heal instead of wiping state
When Tor is Active but every Tor-routed relay fails (the ExitTimeout /
RESOLVEFAILED barrage), onTorCircuitsDead() now does a warm reset() —
drop the in-process client to rebuild the circuit pool with a fresh exit
draw, while keeping guards and the consensus cache — instead of
resetWithCleanState().

The failure is exit-side, not entry-side: circuits build fine, but the
exits can't reach the relays. Wiping arti/state/ + cache can't improve
exit selection (exits aren't persisted) and only forces a ~60s cold
bootstrap — exactly the blackout that strands users on the
connection-failure dialog. A warm restart reconnects in ~5s.

The poisoned-guards safety net is preserved: the next start() re-runs
noUsableGuards(), so genuinely unusable guards are still wiped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 18:08:17 -04:00
Claude 31a375034a fix: make road event location map square (1:1 aspect ratio)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017tYbcy4UGWxqQbcycyL7Yd
2026-06-18 21:52:29 +00:00
Claude 0c67f63bad feat(quartz): add FTS reindex to SQLite and filesystem event stores
The set of event kinds that implement SearchableEvent — and the text
each contributes via indexableContent() — is baked into the quartz
build, so it changes across app versions. Events stored under older code
keep their old (or missing) NIP-50 full-text-search rows, so search
silently misses them after an upgrade.

Add IEventStore.reindexFullTextSearch() so the app can wipe and rebuild
the FTS index from already-stored events when it has spare cycles.

Speed: only kinds that currently map to a SearchableEvent are scanned.
Kind alone selects the event class in EventFactory, so a single probe per
distinct kind is authoritative, letting us push a `kind IN (...)` filter
(SQLite) / skip whole idx/kind dirs (filesystem) so the non-searchable
bulk — reactions, zaps, follow lists — is never deserialised.

- SQLite: FullTextSearchModule.reindexAll drops+recreates the virtual
  table (O(1) wipe) then streams only searchable-kind rows in one write
  transaction, reusing a single INSERT statement.
- Filesystem: rebuilds only idx/fts/, driving the walk from
  idx/kind/<searchable kind>/ via the new FsIndexer.linkFts.
- Wrappers (EventStore, ObservableEventStore, InterningEventStore)
  delegate; the observable layer emits nothing since no event changes.
- cli: `amy store reindex-fts`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BZqPFds2TPPUKkMmBngwys
2026-06-18 21:49:06 +00:00
Claude a9ce0df8f2 feat: render road event (kind 1315/1316) location on an OSM map
Replace the reverse-geocoded "📍 City" line on the Roadstr road event
report and confirmation cards with an osmdroid OpenStreetMap preview
pinned at the event's coordinates.

- Add osmdroid-android 6.1.20 (Apache-2.0) to the version catalog and
  the amethyst module.
- New LocationPreviewMap composable: an AndroidView-wrapped MapView with
  MAPNIK tiles, a single marker, lifecycle-aware onResume/onPause/onDetach,
  and nested-scroll-friendly touch handling so panning the map doesn't
  fight the feed scroll. Sets the OSM User-Agent to the package name
  (required or OSM returns 403).
- RoadEvent cards resolve a point from the explicit lat/lon tags, falling
  back to the center of the finest published geohash.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017tYbcy4UGWxqQbcycyL7Yd
2026-06-18 21:36:56 +00:00
Vitor PamplonaandGitHub 84976b0a3e Merge pull request #3274 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-06-18 17:10:05 -04:00
Crowdin Bot 4ef7828a1c New Crowdin translations by GitHub Action 2026-06-18 21:09:17 +00:00
Vitor PamplonaandGitHub 2d82fd7233 Merge pull request #3269 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-06-18 17:08:45 -04:00
Crowdin Bot 9fcc6bd0a9 New Crowdin translations by GitHub Action 2026-06-18 21:07:14 +00:00
Vitor PamplonaandGitHub 976b8f72b8 Merge pull request #3273 from vitorpamplona/claude/thread-note-collapse-zwnjqb
Add reply collapsing to thread view
2026-06-18 17:06:52 -04:00
Vitor PamplonaandGitHub 294be62fec Merge pull request #3272 from vitorpamplona/claude/stoic-lovelace-qv7vy8
Add Roadstr road event support (kinds 1315/1316)
2026-06-18 17:05:08 -04:00
Vitor PamplonaandGitHub e74b5ac308 Merge pull request #3271 from vitorpamplona/claude/quartz-fts-indexing-review-29o8us
Implement NIP-50 full-text search for additional event kinds
2026-06-18 17:03:15 -04:00
Claude 2d7c30facc style: always show the collapsed reply count, including "+0 replies"
Render the count on every collapsed card for visual consistency, so leaf
replies show "+0 replies" instead of just the chevron.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015hwQiQbgboo8LScPdDHDJn
2026-06-18 20:59:11 +00:00
Claude ffe3af1035 feat: index direct message content (NIP-17 ChatMessageEvent)
ChatMessageEvent (kind 14) is the decrypted NIP-17 rumor; its content is the
plaintext message. Index it so DMs are locally searchable, consistent with
messaging-client search. Opt-in confirmed by the maintainer; private zaps
(9733) remain excluded.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RFdWREvyvixRXnmNXNzmmN
2026-06-18 20:58:11 +00:00
Claude 4662cb75d0 refactor(roadstr): match NIP-88 polls architecture; register in LocalCache
Restructure the experimental roadstr events to mirror the nip88Polls
file layout, and wire the kinds into LocalCache (previously unhandled,
so they hit the "Event Not Supported" fallback and were dropped).

- Split into report/ and confirmation/ sub-packages, each with
  XEvent.kt + TagArrayBuilderExt.kt + TagArrayExt.kt + tags/, matching
  nip88Polls/{poll,response}. build() now uses eventTemplate + typed
  builder-ext functions; accessors delegate to TagArray ext functions.
- Bundle each enum into its tag class (RoadEventType in RoadEventTypeTag,
  RoadEventStatus in RoadEventStatusTag), like PollType in PollTypeTag.
- Add RoadReportTag (a GenericETag `e`-reference) mirroring PollTag, and
  have RoadEventConfirmationEvent implement EventHintProvider so the
  referenced report is linkable — parallel to PollResponseEvent.
- Shared lat/lon/geohash tag codecs live in roadstr/tags/ with generic
  builder/parse extensions.
- LocalCache: consume kinds 1315/1316 as regular events.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Cn4Lk53CcXqYFYHMut4YfY
2026-06-18 20:57:41 +00:00
Claude a7bf23a00d feat: index zap comments (LnZap request/receipt, onchain zap, nutzap)
Zaps carry an optional human-readable message; index it cheaply:

- LnZapRequestEvent (9734): content (public zap comment). Private-zap messages
  live encrypted in the `anon` tag, not content, so they stay out.
- LnZapEvent (9735): the comment is in the embedded zap request, which init{}
  already parses into `zapRequest` unconditionally — so indexing
  `zapRequest?.content` adds no extra parse cost.
- OnchainZapEvent (8333): content (optional message).
- NutzapEvent (9321): content (nutzap message).

LnZapPrivateEvent (9733) is left out: its content is a decrypted *private* zap
message (same privacy class as DMs) — deferred to an explicit opt-in.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RFdWREvyvixRXnmNXNzmmN
2026-06-18 20:54:11 +00:00
Vitor PamplonaandGitHub 2258a0ee2d Merge pull request #3270 from vitorpamplona/claude/tender-mccarthy-lr70hd
Fix NostrClientRepeatSubTest to handle timing-dependent EOSE counts
2026-06-18 16:46:31 -04:00
Claude d5835f730c style: always stack the collapsed reply count on two lines
Put an explicit newline in the plural so "+1\nreply" and "+3\nreplies" both
render the same way (count over word), instead of only the longer plural
wrapping under the width cap. Drops the now-unneeded widthIn constraint.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015hwQiQbgboo8LScPdDHDJn
2026-06-18 20:41:54 +00:00
Claude 2019c47fdb style: center the collapsed reply count label
Center-align the wrapped "+N replies" text so the count sits centered over
the word; it stays vertically centered via the row's alignment.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015hwQiQbgboo8LScPdDHDJn
2026-06-18 20:38:32 +00:00
Claude bb1d034be9 Merge remote-tracking branch 'origin/main' into claude/thread-note-collapse-zwnjqb 2026-06-18 20:32:05 +00:00
Claude e45fbccc4e style: match collapsed reply avatar spacing to NoteComposeLayout
Drop the oversized 55dp centering box that left an extra gap between the
avatar and the name. Use NoteComposeLayout's own metrics instead: 12dp
leading padding and a 10dp avatar-to-name gap, so the spacing around the
collapsed avatar matches an expanded note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015hwQiQbgboo8LScPdDHDJn
2026-06-18 20:28:27 +00:00