Commit Graph

11082 Commits

Author SHA1 Message Date
Claude 6f3793e7ed docs: add performance rationale to secp256k1 optimization decisions
Document WHY each approach was chosen, what alternatives were tested,
and what the measured impact was — so future contributors don't
accidentally revert optimizations or repeat failed experiments.

Key decisions documented:
- uLt() expect/actual: why XOR on Android, Long.compareUnsigned on JVM,
  and why a shared inline fun in commonMain caused 30% JVM regression
- fieldMulReduceWith: why fused mul+reduce, why inline+crossinline,
  why NOT 5x52 limbs, why NOT single-method with all API branches
- @JvmField: why it's required on MutablePoint/AffinePoint/PointScratch,
  with bytecode counts showing ~7,450 + ~2,000 virtual getter calls
  eliminated per verify

https://claude.ai/code/session_01EMY5RnXb9rnsyU2KbXrSaY
2026-04-09 01:29:20 +00:00
Claude 30151295ad perf: make uLt() platform-specific to avoid JVM regression
The inline uLt() using XOR trick in commonMain regressed JVM by ~30%
because HotSpot's Long.compareUnsigned is a JIT intrinsic (single
unsigned CMP + SETB), while the XOR trick generates 2 extra XOR insns
that HotSpot doesn't optimize away.

Convert uLt to expect/actual:
- JVM: Long.compareUnsigned (HotSpot intrinsic)
- Android: XOR trick (avoids ULong.constructor-impl NOOP calls)
- Native: XOR trick (no JVM intrinsics available)

JVM verify: 2.1x → 1.5x (restored, slightly better than 1.6x baseline)
Android: unchanged (still uses XOR trick)

https://claude.ai/code/session_01EMY5RnXb9rnsyU2KbXrSaY
2026-04-09 01:29:20 +00:00
Claude aa9470e6bb perf: add @JvmField to eliminate ~7,450 virtual getter calls per verify
Bytecode analysis showed MutablePoint.x/y/z, AffinePoint.x/y, and all
PointScratch properties compile to invokevirtual getter calls instead
of direct field reads (getfield). Per verify:

  - MutablePoint getX/Y/Z: ~7,450 invokevirtual → getfield
  - PointScratch getT/getW/etc: ~2,000+ invokevirtual → getfield

Each invokevirtual has ~3-5ns overhead on ART vs ~1ns for getfield.
@JvmField eliminates the getter method entirely, compiling property
access to a direct field read. On non-JVM targets (iOS), @JvmField
is silently ignored.

https://claude.ai/code/session_01EMY5RnXb9rnsyU2KbXrSaY
2026-04-09 01:29:20 +00:00
Claude ab3a9076e3 perf: eliminate ULong.constructor-impl NOOP calls in unsigned comparisons
Bytecode analysis revealed that every `a.toULong() < b.toULong()`
comparison generates 2 invokestatic calls to ULong.constructor-impl
(NOOPs that return the input unchanged) plus Long.compareUnsigned.
Across all secp256k1 hot paths, this produced 554 NOOP invokestatic
calls in the bytecode, translating to ~18,000 wasted calls per verify.

Replace all toULong() comparisons with an inline uLt() helper that
uses the XOR-with-MIN_VALUE trick directly:

  (a xor Long.MIN_VALUE) < (b xor Long.MIN_VALUE)

This produces pure arithmetic bytecode (lxor, lcmp, ifge) with ZERO
method calls, eliminating all ULong.constructor-impl overhead.

Before: lload, invokestatic ULong.constructor-impl, lload,
        invokestatic ULong.constructor-impl, invokestatic
        Long.compareUnsigned, ifge  (6 bytecodes, 3 method calls)

After:  lload, ldc MIN_VALUE, lxor, lload, ldc MIN_VALUE, lxor,
        lcmp, ifge  (8 bytecodes, 0 method calls)

https://claude.ai/code/session_01EMY5RnXb9rnsyU2KbXrSaY
2026-04-09 01:29:20 +00:00
Claude 5add793abe perf: split Android fieldMulReduce into per-API methods for ART JIT
The previous approach inlined all 3 API-level branches into a single
fieldMulReduce method (~600 DEX instructions). ART's register allocator
produces suboptimal code for such large methods, causing stack spills
that negate the benefit of eliminating wrapper calls.

Split each API-level path into its own private function (~200 DEX
instructions each). ART JIT-compiles only the hot one (fieldMulApi35
on API 35+) with full optimization, while the tiny dispatch function
(fieldMulReduce) is easily devirtualized and inlined.

https://claude.ai/code/session_01EMY5RnXb9rnsyU2KbXrSaY
2026-04-09 01:29:20 +00:00
Claude 084230937b perf: fuse field multiply+reduce to eliminate ART wrapper overhead
On Android (ART), the unsignedMultiplyHigh wrapper function has per-call
branching for API level detection that prevents ART's JIT from inlining
the intrinsic into the hot loop. This creates ~10,000 extra function
calls per signature verify (20 wrapper calls × 500 field muls).

This commit introduces fieldMulReduce/fieldSqrReduce as expect/actual
functions that fuse U256.mulWide + FieldP.reduceWide into a single
compilation unit. The multiply-high intrinsic is passed as a crossinline
lambda and inlined at each call site, producing platform-specific code
with zero wrapper overhead:

- Android API 35+: Math.unsignedMultiplyHigh inlined directly (UMULH)
- Android API 31-34: Math.multiplyHigh + correction inlined (SMULH)
- Android API <31: pure-Kotlin fallback inlined
- JVM: Math.unsignedMultiplyHigh inlined directly
- Native: pure-Kotlin fallback inlined

The API level check happens ONCE per fieldMulReduce call (outermost
branch) rather than per multiply-high call (innermost loop), so ART
profiles and JIT-compiles only the hot path.

https://claude.ai/code/session_01EMY5RnXb9rnsyU2KbXrSaY
2026-04-09 01:29:19 +00:00
Vitor Pamplona f81cbfd7e4 Merge pull request #2187 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-04-08 20:00:41 -04:00
Crowdin Bot df243d4bf4 New Crowdin translations by GitHub Action 2026-04-08 23:59:08 +00:00
Vitor Pamplona d3907c10da Import function 2026-04-08 19:42:02 -04:00
Vitor Pamplona d2bb9789f5 Merge pull request #2186 from vitorpamplona/claude/add-nwc-connection-buttons-EWG8c
Add wallet connection UI controls to AddWalletScreen
2026-04-08 18:19:48 -04:00
Claude d07b8edd19 feat: add Connect Wallet, paste, and QR scan buttons to AddWalletScreen
Port the NWC connection buttons from the ZapSetup screen (UpdateZapAmountDialog)
to the AddWalletScreen used by the multi-wallet flow. Users can now connect a
local wallet app via deep link, paste an NWC URI from clipboard, or scan a QR
code — matching the same options already available in the zap settings.

https://claude.ai/code/session_01QFunqjudjjrrn6pnsUSPCS
2026-04-08 22:17:53 +00:00
Vitor Pamplona 0fa759cd58 Merge pull request #1988 from vitorpamplona/claude/multi-wallet-nwc-support-Fb04l
feat: add multi-wallet NWC support with balance view and default picker
2026-04-08 17:51:04 -04:00
Claude 55fc9c7caf feat: add wallet rename, dedicated add screen, and reorder controls
- AddWalletScreen: dedicated screen with name input + NWC URI paste,
  replacing the generic NIP47Setup flow for adding new wallets
- Rename: inline dialog on wallet cards to rename wallets
- Reorder: up/down arrow buttons on wallet cards to reorder the list
- AccountSettings: add renameNwcWallet() and moveNwcWallet() methods
- WalletViewModel: add addWallet(), renameWallet(), moveWallet()
- Fix client.send -> client.publish after main rename
- New Route.WalletAdd for the dedicated add wallet screen

https://claude.ai/code/session_013sWHKeE1uNfAZJWD4FU9mT
2026-04-08 21:46:26 +00:00
Claude d0935ff5ce feat: add multi-wallet NWC support with balance view and default picker
Migrate from a single NWC wallet connection to supporting multiple wallets.
Users can now add, remove, and manage multiple NWC wallets, view balance
and transactions per wallet, and select a default wallet for zaps.

Key changes:
- New NwcWalletEntry/NwcWalletEntryNorm data models for wallet storage
- AccountSettings: replace single zapPaymentRequest with nwcWallets list
  and defaultNwcWalletId, with backward-compatible changeZapPaymentRequest
- LocalPreferences: new persistence keys with automatic migration from
  legacy single-wallet format
- NwcSignerState: derives default wallet URI from multi-wallet settings,
  adds sendNwcRequestToWallet for targeting specific wallets
- Account: adds sendNwcRequestToWallet method
- WalletViewModel: supports wallet list, per-wallet balance/info fetching,
  wallet selection, set default, and remove operations
- WalletScreen: shows wallet cards with balance, default indicator, and
  management actions (set default, remove with confirmation)
- WalletDetailScreen: per-wallet detail view with balance, send/receive
- New Route.WalletDetail for per-wallet navigation

https://claude.ai/code/session_013sWHKeE1uNfAZJWD4FU9mT
2026-04-08 21:42:48 +00:00
Vitor Pamplona 86e4c85862 Merge pull request #2185 from vitorpamplona/claude/filter-feed-by-community-4pD5l
Remove redundant route parameter from Community FeedDefinition
2026-04-08 17:18:03 -04:00
Vitor Pamplona 58a508fcb4 Merge pull request #2183 from greenart7c3/claude/move-payment-targets-wallet-KQlnM
Integrate Lightning Address and Payment Targets into NIP47 Setup
2026-04-08 17:12:21 -04:00
Vitor Pamplona c2a1613e6f Merge pull request #2184 from vitorpamplona/claude/improve-chess-card-display-evYsA
Enhance chess UI with user profiles and player display
2026-04-08 17:11:58 -04:00
Claude b861a71c2c feat: replace hex pubkeys with user picture + name in chess cards
In chess note cards (NoteCompose), player hex keys were displayed as
raw strings. Now uses LoadUser + ClickableUserPicture + UsernameDisplay
to show proper profile pictures and display names for:
- Challenge cards (incoming/outgoing)
- Game end cards (both players)
- PGN metadata in game viewers (white/black players)

Added playerContent composable slot to PGNMetadata and ChessGameViewer
so callers can inject platform-specific user rendering.

https://claude.ai/code/session_0171mKrVEfQnNRabmT7Kv4gf
2026-04-08 20:53:56 +00:00
Claude 2435321070 feat: Filter home feed by community in-place instead of navigating away
Previously, selecting a community from the home screen top nav filter
would navigate to the community page. Now it filters the home feed
in-place, applying the community filter to all tabs (New Threads,
Conversations, Live) and adjusting subscriptions accordingly.

The in-place filtering infrastructure already existed (SingleCommunityTopNavFilter,
FilterByListParams, HomeOutboxEventsEoseManager) but was bypassed because
community FeedDefinitions had a route that triggered navigation.

https://claude.ai/code/session_0139NCoHmqvp3aRD3FUjuues
2026-04-08 20:42:19 +00:00
Vitor Pamplona b2a9215788 Fixes shadow clipping in the light theme on FAB buttons. 2026-04-08 16:29:06 -04:00
Vitor Pamplona bd8486d165 When looking at hashtags and geotags, the new post button creates exclusive posts in those communities 2026-04-08 16:02:51 -04:00
Vitor Pamplona a307643369 Show city name if filtering by geotag 2026-04-08 16:02:19 -04:00
Vitor Pamplona ca7e09575f Dont show exclusive content on All Follows 2026-04-08 16:01:59 -04:00
Claude f550a5f426 fix: consolidate wallet setup saves into a single signer call
All three saves (zap settings, lightning address, payment targets) now
run sequentially inside one accountViewModel.launchSigner block,
so the signer is only invoked once per save instead of three times.

- Extract sendPostSuspend() from UpdateZapAmountViewModel.sendPost()
- Extract saveLnAddressSuspend() from WalletViewModel.saveLnAddress()
- Extract savePaymentTargetsSuspend() from PaymentTargetsViewModel.savePaymentTargets()
- NIP47SetupScreen.onPost calls all three suspend fns in one launchSigner

https://claude.ai/code/session_017NPhwCnSzCuMn9sTX3ca37
2026-04-08 18:43:31 +00:00
Vitor Pamplona 154654bae2 Merge pull request #2182 from vitorpamplona/claude/relay-filter-in-place-NKQTF
Add relay feed support and refactor feed filtering logic
2026-04-08 14:41:46 -04:00
Vitor Pamplona 5b2127cb80 Fixes loading of the top nav feed name 2026-04-08 14:39:15 -04:00
Claude 144b82dbe3 refactor: inline lightning address and payment targets in wallet setup screen
- Remove separate Save/Manage buttons; both are now saved via the
  screen's existing SavingTopBar save action
- Lightning address: plain OutlinedTextField, saved on confirm
- Payment targets: inline editable list (Column, not LazyColumn) with
  add/delete directly in the scrollable content area
- Wire walletViewModel.saveLnAddress() and
  paymentTargetsViewModel.savePaymentTargets() into onPost
- Wire paymentTargetsViewModel.refresh() into onCancel

https://claude.ai/code/session_017NPhwCnSzCuMn9sTX3ca37
2026-04-08 18:32:08 +00:00
Vitor Pamplona 189dd35ff6 No need for this, the followList.match already does it 2026-04-08 14:29:35 -04:00
Claude 56a0ec26c6 feat: Filter home feed by geohash/location in-place instead of navigating away
Same approach as relay and hashtag: selecting a location from the top
nav filter now filters the home feed in-place across all tabs.

https://claude.ai/code/session_01PZLLjE7MWh7PPz1woVqmxM
2026-04-08 18:23:59 +00:00
Claude bbc4155c40 feat: move lightning address and payment targets to wallet setup screen
- Add trailingContent lambda to UpdateZapAmountContent so callers can
  inject sections inside its scrollable Column
- Inject lightning address field and payment targets row into
  NIP47SetupScreen via trailingContent
- Add WalletViewModel to NIP47SetupScreen to load/save the lightning address
- Add settings icon button to WalletScreen TopAppBar when wallet is configured,
  navigating back to NIP47SetupScreen
- Restore WalletScreen to its original layout (no ln/payment sections)

https://claude.ai/code/session_017NPhwCnSzCuMn9sTX3ca37
2026-04-08 18:23:25 +00:00
Claude 09fc5bf57f feat: Filter home feed by hashtag in-place instead of navigating away
Same approach as relay filtering: selecting a hashtag from the top nav
filter now filters the home feed in-place across all tabs, with
subscriptions scoped to that hashtag.

https://claude.ai/code/session_01PZLLjE7MWh7PPz1woVqmxM
2026-04-08 18:13:20 +00:00
Claude 05b352b61c fix: update WalletViewModel.init call in sub-screens
WalletReceiveScreen, WalletSendScreen, and WalletTransactionsScreen
were still passing Account instead of AccountViewModel after the
init signature change.

https://claude.ai/code/session_017NPhwCnSzCuMn9sTX3ca37
2026-04-08 18:13:05 +00:00
Vitor Pamplona 91a0b4eda3 Adds favorite relays to Global Feed 2026-04-08 14:04:15 -04:00
Claude d2cf09e5e1 feat: move lightning address and payment targets to wallet screen
- Add lightning address field with save button to WalletScreen
- Add payment targets navigation row to WalletScreen
- Remove lightning address field from profile editor (NewUserMetadataScreen)
- Remove payment targets entry from AllSettings
- Extend WalletViewModel to load/save the lightning address via userMetadata

https://claude.ai/code/session_017NPhwCnSzCuMn9sTX3ca37
2026-04-08 18:01:13 +00:00
Vitor Pamplona b05799a892 Fixes the check of the topnav fitler for global and relays 2026-04-08 13:59:31 -04:00
Vitor Pamplona 74d3d9e65c Merge pull request #2181 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-04-08 13:33:50 -04:00
Crowdin Bot ddc3c1d318 New Crowdin translations by GitHub Action 2026-04-08 17:30:00 +00:00
Vitor Pamplona 2b8c6339e3 Merge pull request #2176 from vitorpamplona/claude/ai-post-writing-help-CDPPw
Add AI writing assistance with ML Kit integration
2026-04-08 13:28:08 -04:00
Vitor Pamplona f6ec547d9b Merge branch 'claude/ai-post-writing-help-CDPPw' of https://github.com/vitorpamplona/amethyst into claude/ai-post-writing-help-CDPPw 2026-04-08 13:24:34 -04:00
Vitor Pamplona 598a630e13 Merge branch 'main' into claude/ai-post-writing-help-CDPPw 2026-04-08 13:23:55 -04:00
Vitor Pamplona 542d9520e1 AI text improvements is active by default 2026-04-08 13:22:53 -04:00
Vitor Pamplona 59457579fb Simplify text for new settings 2026-04-08 13:16:21 -04:00
Vitor Pamplona f71d9df922 Remove the mock 2026-04-08 13:14:57 -04:00
Vitor Pamplona 7d9d8eda11 reducing borders in the chip row 2026-04-08 13:13:37 -04:00
Claude 9f40d14a23 fix: show all AI tone chips at once instead of progressively
Use awaitAll() to collect all tone results before updating the map,
so all chips appear simultaneously when computation finishes.

https://claude.ai/code/session_01RbCYGrbbapRMike8WQy41F
2026-04-08 16:39:44 +00:00
Claude eb5421ccb1 Increase relay filter limits and use normalizeRelayUrl
- Kinds1: 50 -> 500, Kinds2: 5 -> 100, Conversation: 50 -> 500
- Use listName.url.normalizeRelayUrl() instead of NormalizedRelayUrl()

https://claude.ai/code/session_01PZLLjE7MWh7PPz1woVqmxM
2026-04-08 16:39:39 +00:00
Claude 6f6e876158 feat: precompute all AI tone results in parallel
Instead of computing on-tap, all 9 tones are precomputed in parallel
after a 1-second debounce when the user stops typing. Tone chips only
appear once results are ready. Tapping a chip instantly shows the
precomputed result. Text changes cancel and restart the computation.

https://claude.ai/code/session_01RbCYGrbbapRMike8WQy41F
2026-04-08 16:33:06 +00:00
Vitor Pamplona 792b311f87 Merge pull request #2180 from vitorpamplona/claude/move-relay-to-settings-aMMmi
Move Event Sync and Import Follows to Settings screen
2026-04-08 12:30:25 -04:00
Claude 29d00ac621 feat: Filter home feed by relay in-place instead of navigating away
When selecting a relay from the top nav filter, the home feed now
filters in-place (New Threads, Conversations, Live) showing only
posts from that relay, with subscriptions scoped to it.

https://claude.ai/code/session_01PZLLjE7MWh7PPz1woVqmxM
2026-04-08 16:26:50 +00:00
Claude 60d817b0c0 feat: move AI writing help to Application Preferences
Replace the sparkle toggle button in the compose toolbar with a
persistent setting in UI/Application Preferences. The new "Propose AI
text improvements" setting (Always/Never) controls whether the tone
chip row appears in the compose screen.

When enabled and the device supports on-device AI, the tone chips show
automatically below the text field. Removes the per-session toggle
button from BottomRowActions.

https://claude.ai/code/session_01RbCYGrbbapRMike8WQy41F
2026-04-08 16:24:48 +00:00