Commit Graph
15076 Commits
Author SHA1 Message Date
Claude 5263e3b1d9 fix: exclude p, e, a, and alt tags from note text search matching
Their values are ids or descriptions of other events, not content of
the event itself, so they shouldn't make an event match a text search.

https://claude.ai/code/session_01YMs6aXuvs5NaYjzyPH6Zqj
2026-06-12 15:37:16 +00:00
Claude 41055c7769 fix: align app detail screen with thread UI conventions
- Add 12dp horizontal padding to all app detail sections (header,
  screenshots, about, platforms, topics, links, releases) so content
  no longer touches the screen edges like other screens
- Render comments with the reply-level indentation bars used by the
  regular thread feed (drawReplyLevel + levelFlowForItem)
- Move the reactions row below the releases, matching the master-note
  layout of thread screens, and follow it with a divider
- Drop the Comments section label since the reactions row + threaded
  replies already follow the standard screen pattern

https://claude.ai/code/session_01RJSke6d4dpSZgdtXAmGMmp
2026-06-12 15:36:35 +00:00
Vitor PamplonaandGitHub ee95312700 Merge pull request #3193 from vitorpamplona/claude/nifty-brown-egcooi
Add --payer-data flag to offer request command
2026-06-12 11:30:20 -04:00
Claude cbe4b030e1 refactor: expose my 31989s as a LocalCache-observed StateFlow on Account
Account.myAppRecommendations is now LocalCache.observeEvents (indexed
kind+author filter) stated in the account scope, seeded with a
synchronous scan so the editor's first frame still sorts correctly.
The editor and the Recommend button collect it instead of rescanning
the cache on every newEventBundles emission; isAppRecommended is gone.
The synchronous scan stays only as the seed and for the mutex-guarded
read-modify-write publishers, which must read current cache truth.

https://claude.ai/code/session_015dX5vWqvXUYD8rzPYX8vTB
2026-06-12 15:29:30 +00:00
Claude 18c21ad51b feat(cli): add --payer-data to amy offer request
Offers can be configured (via nmanage / ShockWallet) to require payer
fields; Lightning.Pub rejects requests missing them with the misleading
"Invalid Offer" (code 1) reply. A flag to attach payer_data makes such
offers testable from the CLI.

https://claude.ai/code/session_01Fh7MRv8477pJiAJZ7yF87r
2026-06-12 15:18:45 +00:00
Claude 3fc19ce023 refactor: model the curated notification mode as TopFilter.Selected
Replaces TopFilter.GlobalRaw: TopFilter.Global itself now shows every
event that p-tags the user in Notifications (still minus hidden/reported
authors, muted threads, hidden DM content, and self), and the curated
per-kind relevance heuristics move to a new notifications-only
TopFilter.Selected mode.

Selected is offered only in the notifications top nav filter and is the
default for new users and new installs. Existing users who had Global
selected keep Global and therefore now see everything, intentionally.

https://claude.ai/code/session_013VDWpD8Dr6sBF7tBEUZGpg
2026-06-12 15:15:16 +00:00
Claude eed490f579 fix: open app definitions by address instead of version event id
Clicking an app in the recommendations editor (or any 31990 link)
navigated to Route.Note(event.id) — the per-id version note, which the
soft cache evicts and relays can't serve for replaceables — leaving the
thread stuck on 'Event is loading or can't be found'. Route by
addressTag() like the generic AddressableEvent branch already does.

https://claude.ai/code/session_015dX5vWqvXUYD8rzPYX8vTB
2026-06-12 15:08:42 +00:00
Claude 7f39a18a02 fix: exclude client tag from note text search matching
Searching for an app name (e.g. "Amethyst") was returning every event
published through that client, because the local-cache note search
matched the search term against all tag values including the NIP-89
["client", ...] tag. Skip the client tag when matching tag values in
findNotesStartingWith.

https://claude.ai/code/session_01YMs6aXuvs5NaYjzyPH6Zqj
2026-06-12 15:07:13 +00:00
Claude 36d1b9b506 feat: split notifications Global into Selected (curated) and a raw Global
The notifications mode previously labeled Global applied per-kind relevance
heuristics (tagsAnEventByUser) that drop reactions/reposts targeting other
people's notes, unrelated thread replies, etc. That mode is now shown as
"Selected" in the notifications spinner, and a new real Global mode
(TopFilter.GlobalRaw) shows every event that p-tags the user, filtered only
by the notification kind whitelist, hidden/reported authors, muted threads,
muted DM content, and self-authored events.

The split-notifications Everyone tab now pins to the raw Global mode.
Other feeds' Global filter is unchanged.

https://claude.ai/code/session_013VDWpD8Dr6sBF7tBEUZGpg
2026-06-12 15:00:53 +00:00
Vitor PamplonaandGitHub 1927ce1ef0 Merge pull request #3191 from vitorpamplona/claude/elegant-allen-9mt4he
Unify payment card UI with PaymentCard component
2026-06-12 10:59:49 -04:00
David KasparandGitHub f161cfce77 Merge pull request #3190 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-06-12 16:56:31 +02:00
Claude 4b47da9c5d feat: 'by author' chip on app items + stable scroll on return to the editor
- New ByAuthorChip ('by <picture> <name>' pill, tappable to the profile,
  with the following-checkmark overlay on the picture) shown under the
  app name in the recommendations editor rows and on the app definition
  card, so apps from known authors are distinguishable from impersonators.
- The editor's ordering pins now initialize from cached data instead of
  empty sets, so the first frame after returning from an item sorts the
  same as before leaving; previously the restored scroll anchor jumped
  down the list when the recommended/follows tiers kicked in.

https://claude.ai/code/session_015dX5vWqvXUYD8rzPYX8vTB
2026-06-12 14:44:05 +00:00
Crowdin Bot 061da30553 New Crowdin translations by GitHub Action 2026-06-12 13:33:32 +00:00
Vitor PamplonaandGitHub b37e62cd62 Merge pull request #3186 from nrobi144/feat/unhealthy-relay-review
feat(desktop): unhealthy-relay review banner + popup
2026-06-12 09:31:34 -04:00
Claude 7605a5659a revert: drop the kind 31989 search result collapsing
Restores SearchBarViewModel to return search results unmodified.

https://claude.ai/code/session_015dX5vWqvXUYD8rzPYX8vTB
2026-06-12 13:28:38 +00:00
Vitor PamplonaandGitHub da8dca29d7 Merge pull request #3188 from davotoula/feat/onchain-failure-translations
Localize onchain zap send UI and failure messages
2026-06-12 09:20:18 -04:00
davotoula a593ec35f4 Code review:
- Account.kt: collapse three identical backend-not-configured Failure
  constructions into one helper
- OnchainZapSendError: declare causeIsUserFacing on the enum so the
  sender owns which failures carry a human-readable cause, instead of
  the UI mapper hardcoding the list
- SendPaymentScreen: fee chip label is now a single format resource
  instead of manual string concatenation
2026-06-12 14:05:12 +02:00
davotoula 97f9cca43e feat(l10n): localize onchain zap send dialog and failure messages 2026-06-12 14:04:55 +02:00
davotoula 7265a9da36 refactor: extract duplicated string literals into constants (sonar) 2026-06-12 14:04:47 +02:00
David KasparandGitHub 078ceac846 Merge pull request #3187 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-06-12 10:22:48 +02:00
Crowdin Bot bbd039cd74 New Crowdin translations by GitHub Action 2026-06-12 08:21:53 +00:00
davotoulaandClaude Fable 5 5bfe20b673 feat: add cs, de, sv, pt-BR translations for CLINK, Send Payment, workouts, and pin strings
Source-identical values (Cashu, Lightning, On-chain, and per-locale
loanwords like Meditation/Yoga/Workouts in de) are intentionally left
to the English fallback since Crowdin strips them on export anyway.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 10:16:11 +02:00
nrobi144 a46a72a89f feat(desktop): unhealthy-relay review banner + popup
Surfaces relays unresponsive for 7+ days across the user's NIP-65 (10002),
DM (10050), and Search (10007) relay lists. A non-modal banner appears
above feed columns (and above the single-pane content) whenever the
classifier finds anything; tapping it opens an anchored Popup with one
row per unhealthy relay and per-row Remove / Open Dashboard / Snooze 7d
actions plus a banner-level "Snooze all 7d".

Quartz
- RelayStat gains best-effort lastConnectAt + lastIncomingAt timestamps
  (epoch seconds, 0 = never observed). RelayStats listener pushes them
  on onConnected / onIncomingMessage. Durable per-relay history lives
  outside quartz in the commons RelayHealthStore.

Commons (new commons/relays/health/ package)
- classifyRelayHealth() pure function with the v1 gates:
  * first-run grace (don't flag for 7d after firstScanAt)
  * offline grace (don't flag if no relay anywhere has responded)
  * Tor-mode skip (relay timing is intentionally lossy through Tor)
  * per-relay snooze (snoozedUntil > now)
  * 10006 (blocked) excluded from detection but still part of the
    multi-list Remove action
- RelayHealthStore (account-scoped, supervised scope, 5s debounced
  persist, 60s ticker for snooze expiry).
- RelayHealthListener wires the quartz lifecycle into the store.
- RelayHealthPersistence interface (no expect/actual — single impl per
  platform via injection).
- RelayListMutator interface + RelayRemovalResult sealed type.
- Shared UnhealthyRelayBanner (errorContainer @ 50% alpha) and
  UnhealthyRelayRow (static outlined tag chips, no ripple) composables.
- 8 classifier unit tests covering each gate + multi-list membership.

Desktop wiring
- PreferencesRelayHealthPersistence (java.util.prefs.Preferences, per
  account via 8-char pubkey prefix).
- DesktopRelayListMutator runs the 4 sign-and-broadcast jobs in
  parallel via async/awaitAll so a slow NIP-46 bunker doesn't multiply
  latency by 4.
- Banner placed in DeckColumnContainer + SinglePaneLayout, store +
  listener + per-account scan trigger wired in Main.kt's MainContent.

Scope: Desktop only for v1. Android wiring is intentionally not in
this PR — the commons module is platform-neutral and ready for Android
to follow whenever someone wants to pick it up.
2026-06-12 06:40:46 +03:00
Claude ae993068aa fix: NIP-89 UI polish — chip alignment, compact button, list quality, 31989 rendering and search dedup
- App card: '+n' kinds overflow is now a chip with the same metrics as
  KindChip so it centers with the others; Recommend button is compact
  (32dp), sits flush with the banner's right edge, and gains breathing
  room below the cover.
- Recommendations editor: hides unnamed kind 31990 events (kept only if
  already recommended) and only opens an EventFinder subscription for
  rows whose definition isn't in cache yet, so the list stops filling
  with 'Unnamed app' rows that never resolve.
- Editor ordering: the follow list is now collected as it loads (it was
  snapshotted once at screen entry, so the follows tier was empty when
  the screen opened before kind 3 loaded) and freezes on first edit like
  the recommended tier.
- NoteCompose/ThreadFeedView: render kind 31989 as a 'Recommended apps'
  card with the target kind chip and tappable app chips.
- Search: collapse the per-kind 31989 fan-out to the newest event per
  author so one user's recommendations don't flood the results.

https://claude.ai/code/session_015dX5vWqvXUYD8rzPYX8vTB
2026-06-12 00:52:43 +00:00
Claude 275c53ad7b feat: modernize inline payment cards and surface their descriptions
Redesign the three payment cards rendered in the middle of a post
(Lightning invoice, CLINK Offer, Cashu token) around a shared PaymentCard
scaffold that follows the wallet screens' Material3 idiom: tonal card,
icon + label header with a copy action, centered headline amount, and a
full-width themed Pay/Redeem button (no more hardcoded white text or
7sp mint lines).

Descriptions were not being rendered at all:
- BOLT-11: LnInvoiceUtil only decoded the amount from the HRP. Add
  tagged-field parsing (description 'd', expiry 'x', timestamp) with
  BOLT-11 spec-vector tests; the invoice card now shows the memo and
  flags expired invoices (Pay disabled). Desktop card shows it too.
- Cashu: V3 'memo'/'unit' and V4 'd'/'u' were parsed then dropped.
  CashuToken now carries them; the card shows the memo and no longer
  mislabels non-sat units (usd/eur cents formatted as decimals).
- CLINK Offers: the card now shows who gets paid (avatar + name from
  the pointer's pubkey, tappable to the profile).

https://claude.ai/code/session_019VuZ4y3ij6Ly4VVExE1W1W
2026-06-12 00:05:30 +00:00
Claude c3f59a92ba feat: tiered ordering for the app recommendations editor
Sort the management list as: my recommended apps, then apps authored
by my follows, then the rest (most recent first within each tier).
The ordering snapshot freezes at the first toggle so rows don't jump
mid-edit; deselected apps stay in place until the screen is reopened.

https://claude.ai/code/session_015dX5vWqvXUYD8rzPYX8vTB
2026-06-11 23:59:52 +00:00
Claude 917e38c19f fix: make rumor wrap rebroadcast reachable in both audit edge cases
- Bare-seal hosts (kind 13) carry no p tag, so the re-download filter's
  p constraint silently matched nothing for them; the p filter is now
  wrap-only (the ids filter is sufficient for seals)
- A just-sent private note has no relays until its self-wrap echoes
  back from the DM relays; the fetch now falls back to the account's
  own DM inbox relay set when note.relays is empty

Also pins the citation guarantee with RumorHostCitationTest: a rumor
note's nevent must encode the delivering wrap's id, never the private
rumor id, and public notes keep citing their own id.

https://claude.ai/code/session_01B39MQmrT3dz137nfpXABvo
2026-06-11 23:56:44 +00:00
Claude b9595d91a9 Merge remote-tracking branch 'origin/main' into claude/sweet-shannon-smjotq 2026-06-11 23:55:00 +00:00
Claude 38b16f0328 feat: editable NIP-89 app recommendations on profile + richer app cards
- Profile 'Apps' section now mirrors the Badges component: header with
  count and a Settings icon (own profile only) that opens a new
  management screen at Route.ProfileAppRecommendations.
- New ProfileAppRecommendationsScreen lists known kind 31990 app
  definitions (recommended first) with toggles that publish/remove the
  per-kind 31989 recommendation events, backed by a new relay
  subscription for the user's 31989s and recent 31990 candidates.
- Account gains recommendApp/unrecommendApp with mutex-serialized
  read-modify-write per d-tag, mirroring the profile-badges flow.
- Profile recommendations render as logo+name pills instead of bare
  35dp icons; in-post app definition cards now show platform
  availability (web/android/ios), handled event kinds as chips, and a
  Recommend/Recommended button.
- Quartz: AppDefinitionEvent.platformLinks() reader and
  AppRecommendationEvent.buildFromTags() to rebuild a 31989 while
  preserving other apps' tags; round-trip tests included.

https://claude.ai/code/session_015dX5vWqvXUYD8rzPYX8vTB
2026-06-11 23:37:27 +00:00
Claude 96eaefda9b fix: tie rumor host lifetime to the Note — replace the RumorHosts index
A memory audit found the global strong-reference RumorHosts index could
never be kept in sync with LocalCache.notes, which holds WeakReferences:
seven prune paths (pruneExpiredEvents — rumors inherit the seal's
expiration tag — hidden/old-message/replaceable/reaction/hidden-event
prunes, and cleanMemory) plus silent GC eviction dropped rumor notes
without clearing their entries, clear() had no callers (logout, account
removal, memory trim), and orphaned stubs accumulated unbounded.

The stub now lives on the Note (Note.rumorHost): whatever removes or
garbage-collects the note frees the stub, closing every leak path by
construction. Cost is one nullable reference per Note (~200-400 KB at a
50k-note steady state) versus the index's per-entry map overhead plus
unbounded orphan growth. All consumers already held the Note: toNEvent,
Account.broadcast, deleteEnvelopes, removeIfWrap, chat pruning, and the
ingestion pipeline. RumorHosts is deleted.

Also fixes the desktop regression the audit surfaced: the desktop
gift-wrap handler now records the wrap on the rumor note, so desktop
nevent citations of chat messages point at the wrap id again instead of
exposing the private rumor id.

https://claude.ai/code/session_01B39MQmrT3dz137nfpXABvo
2026-06-11 23:35:25 +00:00
Vitor PamplonaandGitHub d91988b26b Merge pull request #3185 from vitorpamplona/claude/focused-einstein-6jjqmj
Add unified profile payment screen with multi-rail support
2026-06-11 19:14:43 -04:00
Claude 98d8a73337 fix(profile): move the payment rail chips below the identity claims
The chip row now renders after the website link and external identities
(GitHub/Twitter/etc.) instead of between NIP-05 and the website.
2026-06-11 23:07:05 +00:00
Claude 86cd1315c2 fix(profile): equalize wrapped-row spacing across all Send Payment chip groups
Pay from, zap receipt, amount preset, and on-chain fee chips wrap with
the same 8dp row gap as the Receive-on pills. Material chips reserve a
48dp interactive height around their 32dp visual, inflating wrapped-row
gaps to ~24dp; the new shared ChipFlowRow drops that enforcement inside
the chip groups so the spacing matches.
2026-06-11 23:05:39 +00:00
Claude a311ffec22 fix(profile): wrap spacing on Send Payment chip rows + cashu mark on its chips
- All chip FlowRows on the Send Payment screen (Receive on, Pay from,
  zap types, amount presets, fee tiers) now declare an 8dp vertical
  arrangement so wrapped lines get the same gap as the in-row spacing —
  the custom Receive-on pills had no intrinsic padding and touched when
  the row broke.
- The cashu rail chip and the cashu 'Pay from' wallet chip use the Cashu
  vector mark (tinted with the chip content color) instead of the
  generic wallet symbol.
2026-06-11 22:34:39 +00:00
Vitor PamplonaandGitHub 1e23b14ff2 Merge pull request #3184 from vitorpamplona/claude/beautiful-turing-j0czsm
Add NIP-101e fitness workout support (Kind 1301)
2026-06-11 18:26:36 -04:00
Claude 3e9fce1858 refactor: replace WrappedEvent host tracking with the RumorHosts index
Delivery metadata no longer lives on quartz event classes. The mutable
host var on @Immutable events (with its dual @Transient annotations) is
gone, and any event kind can now be a rumor without subclassing anything
— kind-14 chats and kind-1 private replies use one mechanism.

- commons RumorHosts: rumor id → delivering envelope (the kind-1059
  wrap normally, a bare kind-13 seal otherwise), populated by the
  gift-wrap ingestion pipeline from the publicNote threaded through the
  handlers (the seal's host pointer was never needed)
- Note.toNEvent cites the envelope for ANY rumor — this also fixes
  kind-1 private replies, whose nevent previously exposed the private
  rumor id (kind-14s were already wrap-cited)
- Account: rumorHost() reads the index; relay computation refuses
  seals, inner DM messages, and unsigned rumors explicitly
- LocalCache: deleteWraps → deleteEnvelopes (also removes the seal
  layer the old host-chain walk missed); removeIfWrap and chat-history
  pruning read the index; index entries are dropped with their rumor
- quartz: SealedRumorEvent and BaseDMGroupEvent extend Event directly;
  GiftWrapEvent.unwrap no longer injects host stubs; WrappedEvent
  deleted

https://claude.ai/code/session_01B39MQmrT3dz137nfpXABvo
2026-06-11 22:18:50 +00:00
Claude 5635f89f3a feat(profile): drop Receive-on detail line; long-press chips copy destinations
The detail text under the Send Payment rail selector (e.g. the lightning
address, already visible in the recipient header) is gone. Instead every
chip carries its destination via long-press copy:

- Send Payment 'Receive on' chips copy the lightning address, the
  noffer pointer, the on-chain destination (announced target address or
  the pubkey-derived Taproot address — otherwise invisible), and the
  shared cashu mint URL. The chips are now custom selectable pills since
  M3 FilterChip has no long-press support.
- Profile rail chips gain the same copy values (clink noffer, derived
  taproot address, mint URL) alongside the existing lightning and
  payment-target copies.
- The announced bitcoin address moved from the detail line into the
  on-chain receipt note so it stays visible when it differs from the
  derived address.
2026-06-11 22:15:07 +00:00
Claude dcb6c6a2ba fix(profile): render rail and payment-target chips in one FlowRow
The wallet-rail chips and the NIP-A3 payment-target chips were two
separately padded FlowRows, so the gap between the two rows was about
double the in-row spacing. The target chips now render inside the same
FlowRow as the rail chips, wrapping together with uniform 6dp spacing.
DisplayPaymentTargets is gone; PaymentTargetChip is rendered by
DisplayPaymentRailChips directly.
2026-06-11 22:09:42 +00:00
Claude 1883f1b032 refactor: full-screen NewWorkout route + audit fixes
- Replace the NewWorkoutDialog with a Route.NewWorkout full screen
  (NewGoalScreen pattern: NewWorkoutViewModel + PostingTopBar), which
  also fixes the audit-found race where the dialog closed before the
  signer finished — the screen now pops back only after a successful
  sign/broadcast, keeping external-signer (Amber) flows alive.
- Move template building from Account.sendWorkout into the ViewModel.
- Render workout cards in thread view (ThreadFeedView fall-through gap).
- Snapshot parsed workout tags once per note (remember + WorkoutInfo)
  instead of re-scanning the tag array on every recomposition.
- Fix Double.trimmed() Int overflow on absurd distances.
- Flatten the distance-unit chip layout.

https://claude.ai/code/session_01Kpx53UEeJqqR7CASzMu6GB
2026-06-11 22:09:12 +00:00
David KasparandGitHub 8b9176bc02 Merge pull request #3179 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-06-12 00:08:29 +02:00
Claude adb59eb276 fix(profile): tint the cashu chip icon and brighten its purple
The Cashu vector is a monochrome black outline meant to be tinted like a
Material Symbol — with Color.Unspecified it rendered black and vanished
on dark backgrounds. Tint it with the chip color and lift the purple
from 0xFF7E57C2 to 0xFFA855F7 so the chip reads on both themes.
2026-06-11 22:06:43 +00:00
Crowdin Bot 344797ce87 New Crowdin translations by GitHub Action 2026-06-11 22:01:40 +00:00
Claude e7b4f8edbb feat(profile): unified payment rail chips on the profile header
Replaces the lightning-address icon+text row with a chip and completes
the rail set, so every way to pay a profile reads as one chip row:

- Lightning chip shows the lud16 (long-press still copies it) and opens
  the Send Payment screen on the Lightning rail.
- CLINK Offer chip moves into the same row (same look as before).
- New On-chain chip (when the chain backend is configured) and Cashu
  chip (when the logged-in user's cashu wallet shares a mint the
  recipient accepts), each opening their rail on the Send Payment
  screen.
- All four render through a shared ProfilePaymentChip pill that matches
  the NIP-A3 payment-target chips, replacing the old DisplayLNAddress
  row and the one-off clink chip in DrawAdditionalInfo.

https://claude.ai/code/session_01UERRsbDoRPz46Qx5HCXgAa
2026-06-11 21:59:47 +00:00
Vitor PamplonaandGitHub ae17c2378b Merge pull request #3183 from vitorpamplona/claude/friendly-lovelace-aw7vfj
Add pinned chatrooms feature with NIP-78 sync
2026-06-11 17:59:24 -04:00
Claude afa341f2fc fix(profile): rename rail selector label from 'Pay with' to 'Receive on'
The rail chips describe how the recipient receives the funds, not which
wallet pays — that's the 'Pay from' row below.
2026-06-11 21:51:09 +00:00
Claude 4361f95a17 feat: NIP-101e workout records (kind 1301) + Workouts feed screen
Quartz: new experimental/fitness/workout package shaped like nip88Polls —
WorkoutRecordEvent with per-tag classes (exercise, duration, distance,
elevation, calories, steps, heart rate, splits, strength sets/reps/weight,
source, workout_start_time), TagArrayBuilder/TagArray extensions, lax
RUNSTR-dialect parsing (unit defaults, HH:MM:SS or raw seconds), and
EventFactory + LocalCache registration. Covered by fixture tests.

Amethyst: new Workouts feed (drawer entry, route, follow-list top bar,
per-relay filter assemblers mirroring the Pictures feed) with a + FAB
opening a manual workout composer that publishes canonical kind-1301
events. Workout cards render stats chips and also display inside threads
via NoteCompose. Adds fitness Material Symbols glyphs and regenerates the
subset font.

https://claude.ai/code/session_01Kpx53UEeJqqR7CASzMu6GB
2026-06-11 21:48:32 +00:00
Claude a3a938253f feat(chat): sync pinned DM rooms via the NIP-78 AppSpecificData event
Pinned chatrooms were stored local-only in encrypted SharedPreferences, so
they were lost on uninstall and never reached other devices. Move them into
AccountSyncedSettings as a new 'chats' group in the encrypted settings blob
(each room serialized as its member pubkeys sorted ascending), publishing a
new AppSpecificData event on every pin/unpin like the other synced settings.

Local persistence now comes from the existing latestAppSpecificData event
backup, so the dedicated pinned_chatrooms preference is removed (the local
format never shipped, so no migration is needed). Pins arriving from another
device flow through AccountSyncedSettings.updateFrom and re-sort the chat
list via the existing pinnedChatrooms feed invalidation collector.

https://claude.ai/code/session_0131YwG6bE3yH8Kk9MxjMA5i
2026-06-11 21:47:17 +00:00
Vitor PamplonaandGitHub 3044e430ab Merge pull request #3182 from vitorpamplona/claude/awesome-gauss-hd9xjn
Add kotlinx-serialization support for CLINK protocol DTOs
2026-06-11 17:47:16 -04:00
Claude 9999d92bca fix: register CLINK DTO serializers in KotlinSerializationMapper for native targets
All CLINK tests failed on iosSimulatorArm64 with IllegalArgumentException
because OptimizedJsonMapper on native dispatches through
KotlinSerializationMapper, whose fromJsonTo/toJson type lists did not
include the CLINK payload DTOs (Jackson handles them reflectively on
JVM/Android, which is why only iOS failed).

Adds hand-written kotlinx serializers for OfferRequest/OfferResponse/
OfferReceipt, DebitRequest/DebitResponse, and ManageRequest/ManageResponse,
mirroring Jackson behavior: ManageResponse.details coerces a lone object
into a one-element list (ACCEPT_SINGLE_VALUE_AS_ARRAY) and
OfferRequest.payer_data round-trips as a free-form JSON object.

Covered by a JVM test driving KotlinSerializationMapper directly and
cross-checking against Jackson, since the native path shares this code.

https://claude.ai/code/session_01SevV4fUCumKZ1UscSz85vS
2026-06-11 21:33:49 +00:00
Claude e62bef8610 perf(chat): defer pinned-room state reads to the row and menu slots
Reading pinnedChatrooms.value in the UserRoomCompose body invalidated the
whole function scope on every pin toggle. Keep the single subscription but
read the set only inside the firstRow slot (pin icon) and the dropdown
menu-item text, so those two small scopes are the only ones that recompose.

https://claude.ai/code/session_0131YwG6bE3yH8Kk9MxjMA5i
2026-06-11 21:22:25 +00:00